From 6f89b3f3d967f4fd39389f3d9beff73bd958f609 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Sat, 20 Mar 2021 00:01:40 +0100 Subject: [PATCH 001/361] Init Header Injection query --- .../Security/CWE-113/HeaderInjection.ql | 89 +++++++++++++++++++ .../Security/CWE-113/HeaderInjection.qlref | 0 .../Security/CWE-113/tests/django_bad.py | 15 ++++ .../Security/CWE-113/tests/flask_bad.py | 47 ++++++++++ 4 files changed, 151 insertions(+) create mode 100644 python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql create mode 100644 python/ql/src/experimental/Security/CWE-113/HeaderInjection.qlref create mode 100644 python/ql/src/experimental/Security/CWE-113/tests/django_bad.py create mode 100644 python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql new file mode 100644 index 00000000000..d03395f571d --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql @@ -0,0 +1,89 @@ +/** + * @name HTTP Header Injection + * @description User input should not be used in HTTP headers without first being escaped, + * otherwise a malicious user may be able to inject a value that could manipulate the response. + * @kind path-problem + * @problem.severity error + * @id python/header-injection + * @tags security + * external/cwe/cwe-113 + * external/cwe/cwe-079 + */ + +// determine precision above +import python +import semmle.python.dataflow.new.RemoteFlowSources +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.ApiGraphs +import DataFlow::PathGraph +import semmle.python.frameworks.Flask + +class WerkzeugHeader extends DataFlow::Node { + WerkzeugHeader() { + exists(DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead addMethod | + headerInstance = + API::moduleImport("werkzeug").getMember("datastructures").getMember("Headers").getACall() and + addMethod.getAttributeName() = "add" and + addMethod.getObject().getALocalSource() = headerInstance and + this = addMethod.(DataFlow::CallCfgNode).getArg(1) + ) + } +} + +class FlaskHeader extends DataFlow::Node { + FlaskHeader() { + exists( + DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, + AssignStmt sinkDeclaration + | + headerInstance = API::moduleImport("flask").getMember("Response").getACall() and + responseMethod.getAttributeName() = "headers" and + responseMethod.getObject().getALocalSource() = headerInstance and + sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and + this.asExpr() = sinkDeclaration.getValue() + ) + } +} + +class FlaskMakeResponse extends DataFlow::Node { + FlaskMakeResponse() { + exists( + DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, + AssignStmt sinkDeclaration + | + headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and + responseMethod.getAttributeName() = "headers" and + responseMethod.getObject().getALocalSource() = headerInstance and + ( + sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and + this.asExpr() = sinkDeclaration.getValue() + ) + //or + //extendMethod.getAttributeName() = "extend" and + //extendMethod.getObject().getALocalSource() = responseMethod and + //this = extendMethod.(DataFlow::CallCfgNode).getArg(0) + ) + } +} + +class HeaderInjectionSink extends DataFlow::Node { + HeaderInjectionSink() { + this instanceof WerkzeugHeader or + this instanceof FlaskHeader or + this instanceof FlaskMakeResponse + } +} + +class HeaderInjectionFlowConfig extends TaintTracking::Configuration { + HeaderInjectionFlowConfig() { this = "HeaderInjectionFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof HeaderInjectionSink } +} + +from HeaderInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "$@ header is constructed from a $@.", sink.getNode(), "This", + source.getNode(), "user-provided value" diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.qlref b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.qlref new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/src/experimental/Security/CWE-113/tests/django_bad.py b/python/ql/src/experimental/Security/CWE-113/tests/django_bad.py new file mode 100644 index 00000000000..b97d9137f46 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-113/tests/django_bad.py @@ -0,0 +1,15 @@ +import django.http + + +def django_setitem(request): + rfs_header = request.GET.get("rfs_header") + response = django.http.HttpResponse() + response.__setitem__('HeaderName', rfs_header) + return response + + +def django_response(request): + rfs_header = request.GET.get("rfs_header") + response = django.http.HttpResponse() + response['HeaderName'] = rfs_header + return response diff --git a/python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py b/python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py new file mode 100644 index 00000000000..1f011fe8802 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py @@ -0,0 +1,47 @@ +from flask import Response, request, Flask +from werkzeug.datastructures import Headers + +app = Flask(__name__) + + +@app.route('/werkzeug_headers') +def werkzeug_headers(): + rfs_header = request.args["rfs_header"] + response = Response() + headers = Headers() + headers.add("HeaderName", rfs_header) + response.headers = headers + return response + + +@app.route("/flask_Response") +def flask_Response(): + rfs_header = request.args["rfs_header"] + response = Response() + response.headers['HeaderName'] = rfs_header + return response + + +@app.route("/flask_make_response") +def flask_make_response(): + rfs_header = request.args["rfs_header"] + resp = make_response("hello") + resp.headers['HeaderName'] = rfs_header + return resp + + +@app.route("/flask_make_response_extend") +def flask_make_response_extend(): + rfs_header = request.args["rfs_header"] + resp = make_response("hello") + resp.headers.extend( + {'HeaderName': request.args["rfs_header"]}) + return resp + + +@app.route("/Response_arg") +def Response_arg(): + return Response(headers={'HeaderName': request.args["rfs_header"]}) + +# if __name__ == "__main__": +# app.run(debug=True) From 46c5cb1136c619a5a59744462ce63ad241e607a7 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 1 Apr 2021 14:21:45 +0200 Subject: [PATCH 002/361] Polish WerkzeugHeaderCall --- .../Security/CWE-113/HeaderInjection.ql | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql index d03395f571d..52180bd1372 100644 --- a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql +++ b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql @@ -17,18 +17,18 @@ import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking import semmle.python.ApiGraphs import DataFlow::PathGraph -import semmle.python.frameworks.Flask -class WerkzeugHeader extends DataFlow::Node { - WerkzeugHeader() { - exists(DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead addMethod | - headerInstance = +class WerkzeugHeaderCall extends DataFlow::CallCfgNode { + WerkzeugHeaderCall() { + exists(DataFlow::AttrRead addMethod | + this.getFunction() = addMethod and + addMethod.getObject().getALocalSource() = API::moduleImport("werkzeug").getMember("datastructures").getMember("Headers").getACall() and - addMethod.getAttributeName() = "add" and - addMethod.getObject().getALocalSource() = headerInstance and - this = addMethod.(DataFlow::CallCfgNode).getArg(1) + addMethod.getAttributeName() = "add" ) } + + DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } } class FlaskHeader extends DataFlow::Node { From 3be916e82b16e744146fdb5a7659c796fc2a543f Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 1 Apr 2021 15:56:03 +0200 Subject: [PATCH 003/361] Polish FlaskHeaderCall --- .../Security/CWE-113/HeaderInjection.ql | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql index 52180bd1372..e3f16eb80f5 100644 --- a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql +++ b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql @@ -31,8 +31,10 @@ class WerkzeugHeaderCall extends DataFlow::CallCfgNode { DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } } -class FlaskHeader extends DataFlow::Node { - FlaskHeader() { +class FlaskHeaderCall extends DataFlow::CallCfgNode { + DataFlow::Node headerInputNode; + + FlaskHeaderCall() { exists( DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, AssignStmt sinkDeclaration @@ -41,9 +43,12 @@ class FlaskHeader extends DataFlow::Node { responseMethod.getAttributeName() = "headers" and responseMethod.getObject().getALocalSource() = headerInstance and sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and - this.asExpr() = sinkDeclaration.getValue() + headerInputNode.asExpr() = sinkDeclaration.getValue() and + this.getFunction() = responseMethod ) } + + DataFlow::Node getHeaderInputNode() { result = headerInputNode } } class FlaskMakeResponse extends DataFlow::Node { @@ -69,8 +74,8 @@ class FlaskMakeResponse extends DataFlow::Node { class HeaderInjectionSink extends DataFlow::Node { HeaderInjectionSink() { - this instanceof WerkzeugHeader or - this instanceof FlaskHeader or + this instanceof WerkzeugHeaderCall or + this instanceof FlaskHeaderCall or this instanceof FlaskMakeResponse } } From bd894ae8b3c254799deb2ae48b9e51e30fc66364 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Sun, 4 Apr 2021 01:16:28 +0200 Subject: [PATCH 004/361] Fix flask test --- .../ql/src/experimental/Security/CWE-113/tests/flask_bad.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py b/python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py index 1f011fe8802..6f2968efb55 100644 --- a/python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py +++ b/python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py @@ -1,4 +1,4 @@ -from flask import Response, request, Flask +from flask import Response, request, Flask, make_response from werkzeug.datastructures import Headers app = Flask(__name__) @@ -35,7 +35,7 @@ def flask_make_response_extend(): rfs_header = request.args["rfs_header"] resp = make_response("hello") resp.headers.extend( - {'HeaderName': request.args["rfs_header"]}) + {'HeaderName': rfs_header}) return resp From 6158dd6bce85529e3661acd432c1e3abdbce51dd Mon Sep 17 00:00:00 2001 From: jorgectf Date: Sun, 4 Apr 2021 01:16:38 +0200 Subject: [PATCH 005/361] Finish Sinks --- .../Security/CWE-113/HeaderInjection.ql | 99 ++++++++++++++++--- 1 file changed, 84 insertions(+), 15 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql index e3f16eb80f5..c5d2984c150 100644 --- a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql +++ b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql @@ -31,7 +31,7 @@ class WerkzeugHeaderCall extends DataFlow::CallCfgNode { DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } } -class FlaskHeaderCall extends DataFlow::CallCfgNode { +class FlaskHeaderCall extends DataFlow::Node { DataFlow::Node headerInputNode; FlaskHeaderCall() { @@ -44,15 +44,17 @@ class FlaskHeaderCall extends DataFlow::CallCfgNode { responseMethod.getObject().getALocalSource() = headerInstance and sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and headerInputNode.asExpr() = sinkDeclaration.getValue() and - this.getFunction() = responseMethod + this.asExpr() = sinkDeclaration.getATarget() ) } DataFlow::Node getHeaderInputNode() { result = headerInputNode } } -class FlaskMakeResponse extends DataFlow::Node { - FlaskMakeResponse() { +class FlaskMakeResponseCall extends DataFlow::Node { + DataFlow::Node headerInputNode; + + FlaskMakeResponseCall() { exists( DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, AssignStmt sinkDeclaration @@ -60,23 +62,90 @@ class FlaskMakeResponse extends DataFlow::Node { headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and responseMethod.getAttributeName() = "headers" and responseMethod.getObject().getALocalSource() = headerInstance and - ( - sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and - this.asExpr() = sinkDeclaration.getValue() - ) - //or - //extendMethod.getAttributeName() = "extend" and - //extendMethod.getObject().getALocalSource() = responseMethod and - //this = extendMethod.(DataFlow::CallCfgNode).getArg(0) + sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and + this.asExpr() = sinkDeclaration.getATarget() and + headerInputNode.asExpr() = sinkDeclaration.getValue() ) } + + DataFlow::Node getHeaderInputNode() { result = headerInputNode } +} + +class FlaskMakeResponseExtendCall extends DataFlow::CallCfgNode { + DataFlow::Node headerInputNode; + + FlaskMakeResponseExtendCall() { + exists( + DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, + DataFlow::AttrRead extendMethod + | + headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and + responseMethod.getAttributeName() = "headers" and + responseMethod.getObject().getALocalSource() = headerInstance and + extendMethod.getAttributeName() = "extend" and + extendMethod.getObject().getALocalSource() = responseMethod and + this.getFunction() = extendMethod and + headerInputNode = this.getArg(0) + ) + } + + DataFlow::Node getHeaderInputNode() { result = headerInputNode } +} + +class FlaskResponseArg extends DataFlow::CallCfgNode { + DataFlow::Node headerInputNode; + + FlaskResponseArg() { + this = API::moduleImport("flask").getMember("Response").getACall() and + headerInputNode = this.getArgByName("headers") + } + + DataFlow::Node getHeaderInputNode() { result = headerInputNode } +} + +class DjangoResponseSetItemCall extends DataFlow::CallCfgNode { + DjangoResponseSetItemCall() { + exists(DataFlow::AttrRead setItemMethod | + this.getFunction() = setItemMethod and + setItemMethod.getObject().getALocalSource() = + API::moduleImport("django").getMember("http").getMember("HttpResponse").getACall() and + setItemMethod.getAttributeName() = "__setitem__" + ) + } + + DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } +} + +class DjangoResponseAssignCall extends DataFlow::Node { + DataFlow::Node headerInputNode; + + DjangoResponseAssignCall() { + exists( + DataFlow::CallCfgNode headerInstance, Subscript responseMethod, DataFlow::Node responseToNode, + AssignStmt sinkDeclaration + | + headerInstance = + API::moduleImport("django").getMember("http").getMember("HttpResponse").getACall() and + responseMethod.getValue() = responseToNode.asExpr() and + responseToNode.getALocalSource().asExpr() = headerInstance.asExpr() and + sinkDeclaration.getATarget() = responseMethod and + this.asExpr() = sinkDeclaration.getATarget() and + headerInputNode.asExpr() = sinkDeclaration.getValue() + ) + } + + DataFlow::Node getHeaderInputNode() { result = headerInputNode } } class HeaderInjectionSink extends DataFlow::Node { HeaderInjectionSink() { - this instanceof WerkzeugHeaderCall or - this instanceof FlaskHeaderCall or - this instanceof FlaskMakeResponse + this = any(WerkzeugHeaderCall a).getHeaderInputNode() or + this = any(FlaskHeaderCall a).getHeaderInputNode() or + this = any(FlaskMakeResponseCall a).getHeaderInputNode() or + this = any(FlaskMakeResponseExtendCall a).getHeaderInputNode() or + this = any(FlaskResponseArg a).getHeaderInputNode() or + this = any(DjangoResponseSetItemCall a).getHeaderInputNode() or + this = any(DjangoResponseAssignCall a).getHeaderInputNode() } } From b0c498629a39b2a02815ab9495193e1bd475f155 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 01:01:29 +0200 Subject: [PATCH 006/361] Init restructuring --- .../python/security/injection/HTTPHeaders.qll | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll diff --git a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll new file mode 100644 index 00000000000..1215710c1aa --- /dev/null +++ b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll @@ -0,0 +1,15 @@ +import python +import experimental.semmle.python.Concepts +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.dataflow.new.RemoteFlowSources + +class HeaderInjectionFlowConfig extends TaintTracking::Configuration { + HeaderInjectionFlowConfig() { this = "HeaderInjectionFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + sink = any(HeaderDeclaration headerDeclaration).getHeaderInputNode() + } +} From ce3fb6be21fc84248b387527f62367616a1fc79d Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 01:26:16 +0200 Subject: [PATCH 007/361] Improve qhelp --- .../Security/CWE-113/HeaderInjection.qhelp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 python/ql/src/experimental/Security/CWE-113/HeaderInjection.qhelp diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.qhelp b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.qhelp new file mode 100644 index 00000000000..33337294b9a --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.qhelp @@ -0,0 +1,26 @@ + + + +

If an HTTP Header is built using string concatenation or string formatting, and the +components of the concatenation include user input, a user +is likely to be able to manipulate the response.

+
+ + +

User input should not be included in an HTTP Header.

+
+ + +

In the following example, the code appends a user-provided value into a header.

+ + +
+ + +
  • OWASP: HTTP Response Splitting.
  • +
  • Python Security: HTTP header injection.
  • +
  • SonarSource: RSPEC-5167.
  • +
    +
    From 789c5857fa2962a31e3271594af2971519eb072a Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 01:26:28 +0200 Subject: [PATCH 008/361] Create qhelp example --- .../experimental/Security/CWE-113/header_injection.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 python/ql/src/experimental/Security/CWE-113/header_injection.py diff --git a/python/ql/src/experimental/Security/CWE-113/header_injection.py b/python/ql/src/experimental/Security/CWE-113/header_injection.py new file mode 100644 index 00000000000..117383710e3 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-113/header_injection.py @@ -0,0 +1,9 @@ +from flask import Response, request, Flask, make_response + + +@app.route("/flask_Response") +def flask_Response(): + rfs_header = request.args["rfs_header"] + response = Response() + response.headers['HeaderName'] = rfs_header + return response From e9c457455252654ce4fdade7edaf7e4047e2723b Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 01:26:53 +0200 Subject: [PATCH 009/361] Apply structure --- .../Security/CWE-113/HeaderInjection.ql | 154 +----------------- .../Security/CWE-113/HeaderInjection.qlref | 0 .../experimental/semmle/python/Concepts.qll | 14 ++ .../semmle/python/frameworks/Stdlib.qll | 130 +++++++++++++++ .../Security/CWE-113}/django_bad.py | 0 .../Security/CWE-113}/flask_bad.py | 0 6 files changed, 150 insertions(+), 148 deletions(-) delete mode 100644 python/ql/src/experimental/Security/CWE-113/HeaderInjection.qlref rename python/ql/{src/experimental/Security/CWE-113/tests => test/experimental/query-tests/Security/CWE-113}/django_bad.py (100%) rename python/ql/{src/experimental/Security/CWE-113/tests => test/experimental/query-tests/Security/CWE-113}/flask_bad.py (100%) diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql index c5d2984c150..3cb4a20d5de 100644 --- a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql +++ b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql @@ -1,10 +1,10 @@ /** * @name HTTP Header Injection - * @description User input should not be used in HTTP headers without first being escaped, - * otherwise a malicious user may be able to inject a value that could manipulate the response. + * @description User input should not be used in HTTP headers, otherwise a malicious user + * may be able to inject a value that could manipulate the response. * @kind path-problem * @problem.severity error - * @id python/header-injection + * @id py/header-injection * @tags security * external/cwe/cwe-113 * external/cwe/cwe-079 @@ -12,152 +12,10 @@ // determine precision above import python -import semmle.python.dataflow.new.RemoteFlowSources -import semmle.python.dataflow.new.DataFlow -import semmle.python.dataflow.new.TaintTracking -import semmle.python.ApiGraphs +import experimental.semmle.python.security.injection.HTTPHeaders import DataFlow::PathGraph -class WerkzeugHeaderCall extends DataFlow::CallCfgNode { - WerkzeugHeaderCall() { - exists(DataFlow::AttrRead addMethod | - this.getFunction() = addMethod and - addMethod.getObject().getALocalSource() = - API::moduleImport("werkzeug").getMember("datastructures").getMember("Headers").getACall() and - addMethod.getAttributeName() = "add" - ) - } - - DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } -} - -class FlaskHeaderCall extends DataFlow::Node { - DataFlow::Node headerInputNode; - - FlaskHeaderCall() { - exists( - DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, - AssignStmt sinkDeclaration - | - headerInstance = API::moduleImport("flask").getMember("Response").getACall() and - responseMethod.getAttributeName() = "headers" and - responseMethod.getObject().getALocalSource() = headerInstance and - sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and - headerInputNode.asExpr() = sinkDeclaration.getValue() and - this.asExpr() = sinkDeclaration.getATarget() - ) - } - - DataFlow::Node getHeaderInputNode() { result = headerInputNode } -} - -class FlaskMakeResponseCall extends DataFlow::Node { - DataFlow::Node headerInputNode; - - FlaskMakeResponseCall() { - exists( - DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, - AssignStmt sinkDeclaration - | - headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and - responseMethod.getAttributeName() = "headers" and - responseMethod.getObject().getALocalSource() = headerInstance and - sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and - this.asExpr() = sinkDeclaration.getATarget() and - headerInputNode.asExpr() = sinkDeclaration.getValue() - ) - } - - DataFlow::Node getHeaderInputNode() { result = headerInputNode } -} - -class FlaskMakeResponseExtendCall extends DataFlow::CallCfgNode { - DataFlow::Node headerInputNode; - - FlaskMakeResponseExtendCall() { - exists( - DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, - DataFlow::AttrRead extendMethod - | - headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and - responseMethod.getAttributeName() = "headers" and - responseMethod.getObject().getALocalSource() = headerInstance and - extendMethod.getAttributeName() = "extend" and - extendMethod.getObject().getALocalSource() = responseMethod and - this.getFunction() = extendMethod and - headerInputNode = this.getArg(0) - ) - } - - DataFlow::Node getHeaderInputNode() { result = headerInputNode } -} - -class FlaskResponseArg extends DataFlow::CallCfgNode { - DataFlow::Node headerInputNode; - - FlaskResponseArg() { - this = API::moduleImport("flask").getMember("Response").getACall() and - headerInputNode = this.getArgByName("headers") - } - - DataFlow::Node getHeaderInputNode() { result = headerInputNode } -} - -class DjangoResponseSetItemCall extends DataFlow::CallCfgNode { - DjangoResponseSetItemCall() { - exists(DataFlow::AttrRead setItemMethod | - this.getFunction() = setItemMethod and - setItemMethod.getObject().getALocalSource() = - API::moduleImport("django").getMember("http").getMember("HttpResponse").getACall() and - setItemMethod.getAttributeName() = "__setitem__" - ) - } - - DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } -} - -class DjangoResponseAssignCall extends DataFlow::Node { - DataFlow::Node headerInputNode; - - DjangoResponseAssignCall() { - exists( - DataFlow::CallCfgNode headerInstance, Subscript responseMethod, DataFlow::Node responseToNode, - AssignStmt sinkDeclaration - | - headerInstance = - API::moduleImport("django").getMember("http").getMember("HttpResponse").getACall() and - responseMethod.getValue() = responseToNode.asExpr() and - responseToNode.getALocalSource().asExpr() = headerInstance.asExpr() and - sinkDeclaration.getATarget() = responseMethod and - this.asExpr() = sinkDeclaration.getATarget() and - headerInputNode.asExpr() = sinkDeclaration.getValue() - ) - } - - DataFlow::Node getHeaderInputNode() { result = headerInputNode } -} - -class HeaderInjectionSink extends DataFlow::Node { - HeaderInjectionSink() { - this = any(WerkzeugHeaderCall a).getHeaderInputNode() or - this = any(FlaskHeaderCall a).getHeaderInputNode() or - this = any(FlaskMakeResponseCall a).getHeaderInputNode() or - this = any(FlaskMakeResponseExtendCall a).getHeaderInputNode() or - this = any(FlaskResponseArg a).getHeaderInputNode() or - this = any(DjangoResponseSetItemCall a).getHeaderInputNode() or - this = any(DjangoResponseAssignCall a).getHeaderInputNode() - } -} - -class HeaderInjectionFlowConfig extends TaintTracking::Configuration { - HeaderInjectionFlowConfig() { this = "HeaderInjectionFlowConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof HeaderInjectionSink } -} - from HeaderInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ header is constructed from a $@.", sink.getNode(), "This", - source.getNode(), "user-provided value" +select sink.getNode(), source, sink, "$@ HTTP header is constructed from a $@.", sink.getNode(), + "This", source.getNode(), "user-provided value" diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.qlref b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.qlref deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 904b7967ee8..530b8d20ec6 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -13,3 +13,17 @@ private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.TaintTracking private import experimental.semmle.python.Frameworks + +module HeaderDeclaration { + abstract class Range extends DataFlow::Node { + abstract DataFlow::Node getHeaderInputNode(); + } +} + +class HeaderDeclaration extends DataFlow::Node { + HeaderDeclaration::Range range; + + HeaderDeclaration() { this = range } + + DataFlow::Node getHeaderInputNode() { result = range.getHeaderInputNode() } +} diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 420caf0d73b..636a0621bd4 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -9,3 +9,133 @@ private import semmle.python.dataflow.new.TaintTracking private import semmle.python.dataflow.new.RemoteFlowSources private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs + +private module Headers { + private module Werkzeug { + class WerkzeugHeaderCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + WerkzeugHeaderCall() { + exists(DataFlow::AttrRead addMethod | + this.getFunction() = addMethod and + addMethod.getObject().getALocalSource() = + API::moduleImport("werkzeug") + .getMember("datastructures") + .getMember("Headers") + .getACall() and + addMethod.getAttributeName() = "add" + ) + } + + override DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } + } + } + + private module Flask { + class FlaskHeaderCall extends DataFlow::Node, HeaderDeclaration::Range { + DataFlow::Node headerInputNode; + + FlaskHeaderCall() { + exists( + DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, + AssignStmt sinkDeclaration + | + headerInstance = API::moduleImport("flask").getMember("Response").getACall() and + responseMethod.getAttributeName() = "headers" and + responseMethod.getObject().getALocalSource() = headerInstance and + sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and + headerInputNode.asExpr() = sinkDeclaration.getValue() and + this.asExpr() = sinkDeclaration.getATarget() + ) + } + + override DataFlow::Node getHeaderInputNode() { result = headerInputNode } + } + + class FlaskMakeResponseCall extends DataFlow::Node, HeaderDeclaration::Range { + DataFlow::Node headerInputNode; + + FlaskMakeResponseCall() { + exists( + DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, + AssignStmt sinkDeclaration + | + headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and + responseMethod.getAttributeName() = "headers" and + responseMethod.getObject().getALocalSource() = headerInstance and + sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and + this.asExpr() = sinkDeclaration.getATarget() and + headerInputNode.asExpr() = sinkDeclaration.getValue() + ) + } + + override DataFlow::Node getHeaderInputNode() { result = headerInputNode } + } + + class FlaskMakeResponseExtendCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + DataFlow::Node headerInputNode; + + FlaskMakeResponseExtendCall() { + exists( + DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, + DataFlow::AttrRead extendMethod + | + headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and + responseMethod.getAttributeName() = "headers" and + responseMethod.getObject().getALocalSource() = headerInstance and + extendMethod.getAttributeName() = "extend" and + extendMethod.getObject().getALocalSource() = responseMethod and + this.getFunction() = extendMethod and + headerInputNode = this.getArg(0) + ) + } + + override DataFlow::Node getHeaderInputNode() { result = headerInputNode } + } + + class FlaskResponseArg extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + DataFlow::Node headerInputNode; + + FlaskResponseArg() { + this = API::moduleImport("flask").getMember("Response").getACall() and + headerInputNode = this.getArgByName("headers") + } + + override DataFlow::Node getHeaderInputNode() { result = headerInputNode } + } + + class DjangoResponseSetItemCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + DjangoResponseSetItemCall() { + exists(DataFlow::AttrRead setItemMethod | + this.getFunction() = setItemMethod and + setItemMethod.getObject().getALocalSource() = + API::moduleImport("django").getMember("http").getMember("HttpResponse").getACall() and + setItemMethod.getAttributeName() = "__setitem__" + ) + } + + override DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } + } + } + + private module Django { + class DjangoResponseAssignCall extends DataFlow::Node, HeaderDeclaration::Range { + DataFlow::Node headerInputNode; + + DjangoResponseAssignCall() { + exists( + DataFlow::CallCfgNode headerInstance, Subscript responseMethod, + DataFlow::Node responseToNode, AssignStmt sinkDeclaration + | + headerInstance = + API::moduleImport("django").getMember("http").getMember("HttpResponse").getACall() and + responseMethod.getValue() = responseToNode.asExpr() and + responseToNode.getALocalSource().asExpr() = headerInstance.asExpr() and + sinkDeclaration.getATarget() = responseMethod and + this.asExpr() = sinkDeclaration.getATarget() and + headerInputNode.asExpr() = sinkDeclaration.getValue() + ) + } + + override DataFlow::Node getHeaderInputNode() { result = headerInputNode } + } + } +} diff --git a/python/ql/src/experimental/Security/CWE-113/tests/django_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-113/django_bad.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-113/tests/django_bad.py rename to python/ql/test/experimental/query-tests/Security/CWE-113/django_bad.py diff --git a/python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-113/flask_bad.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-113/tests/flask_bad.py rename to python/ql/test/experimental/query-tests/Security/CWE-113/flask_bad.py From 632dc61d5e6778fe9aa6767f257e0942b3be0010 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 01:28:22 +0200 Subject: [PATCH 010/361] Create qlref --- .../query-tests/Security/CWE-113/HeaderInjection.qlref | 1 + 1 file changed, 1 insertion(+) create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.qlref diff --git a/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.qlref new file mode 100644 index 00000000000..915175a7b6a --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-113/HeaderInjection.ql From f02c2855adc8e017f9c1d1a60aff3bc8124e27f0 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 01:28:38 +0200 Subject: [PATCH 011/361] Generate .expected --- .../Security/CWE-113/HeaderInjection.expected | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected diff --git a/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected new file mode 100644 index 00000000000..9e0eff704b6 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected @@ -0,0 +1,43 @@ +edges +| flask_bad.py:9:18:9:24 | ControlFlowNode for request | flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | +| flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | +| flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | +| flask_bad.py:19:18:19:24 | ControlFlowNode for request | flask_bad.py:19:18:19:29 | ControlFlowNode for Attribute | +| flask_bad.py:19:18:19:29 | ControlFlowNode for Attribute | flask_bad.py:19:18:19:43 | ControlFlowNode for Subscript | +| flask_bad.py:19:18:19:43 | ControlFlowNode for Subscript | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | +| flask_bad.py:27:18:27:24 | ControlFlowNode for request | flask_bad.py:27:18:27:29 | ControlFlowNode for Attribute | +| flask_bad.py:27:18:27:29 | ControlFlowNode for Attribute | flask_bad.py:27:18:27:43 | ControlFlowNode for Subscript | +| flask_bad.py:27:18:27:43 | ControlFlowNode for Subscript | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | +| flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute | +| flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute | flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | +| flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | +| flask_bad.py:44:44:44:50 | ControlFlowNode for request | flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute | +| flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute | flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | +| flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | +nodes +| flask_bad.py:9:18:9:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | +| flask_bad.py:19:18:19:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_bad.py:19:18:19:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_bad.py:19:18:19:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | +| flask_bad.py:27:18:27:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_bad.py:27:18:27:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_bad.py:27:18:27:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | +| flask_bad.py:35:18:35:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_bad.py:44:44:44:50 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +#select +| flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | flask_bad.py:9:18:9:24 | ControlFlowNode for request | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | This | flask_bad.py:9:18:9:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | flask_bad.py:19:18:19:24 | ControlFlowNode for request | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | This | flask_bad.py:19:18:19:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | flask_bad.py:27:18:27:24 | ControlFlowNode for request | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | This | flask_bad.py:27:18:27:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | $@ HTTP header is constructed from a $@. | flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | This | flask_bad.py:35:18:35:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | flask_bad.py:44:44:44:50 | ControlFlowNode for request | flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | $@ HTTP header is constructed from a $@. | flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | This | flask_bad.py:44:44:44:50 | ControlFlowNode for request | user-provided value | From 066504e79efaf953ab000bae3bec966193bba57f Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 18 Jun 2021 02:02:47 +0200 Subject: [PATCH 012/361] Checkout Stdlib.qll --- .../semmle/python/frameworks/Stdlib.qll | 130 ------------------ 1 file changed, 130 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 636a0621bd4..420caf0d73b 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -9,133 +9,3 @@ private import semmle.python.dataflow.new.TaintTracking private import semmle.python.dataflow.new.RemoteFlowSources private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs - -private module Headers { - private module Werkzeug { - class WerkzeugHeaderCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { - WerkzeugHeaderCall() { - exists(DataFlow::AttrRead addMethod | - this.getFunction() = addMethod and - addMethod.getObject().getALocalSource() = - API::moduleImport("werkzeug") - .getMember("datastructures") - .getMember("Headers") - .getACall() and - addMethod.getAttributeName() = "add" - ) - } - - override DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } - } - } - - private module Flask { - class FlaskHeaderCall extends DataFlow::Node, HeaderDeclaration::Range { - DataFlow::Node headerInputNode; - - FlaskHeaderCall() { - exists( - DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, - AssignStmt sinkDeclaration - | - headerInstance = API::moduleImport("flask").getMember("Response").getACall() and - responseMethod.getAttributeName() = "headers" and - responseMethod.getObject().getALocalSource() = headerInstance and - sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and - headerInputNode.asExpr() = sinkDeclaration.getValue() and - this.asExpr() = sinkDeclaration.getATarget() - ) - } - - override DataFlow::Node getHeaderInputNode() { result = headerInputNode } - } - - class FlaskMakeResponseCall extends DataFlow::Node, HeaderDeclaration::Range { - DataFlow::Node headerInputNode; - - FlaskMakeResponseCall() { - exists( - DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, - AssignStmt sinkDeclaration - | - headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and - responseMethod.getAttributeName() = "headers" and - responseMethod.getObject().getALocalSource() = headerInstance and - sinkDeclaration.getATarget() = responseMethod.asExpr().getParentNode() and - this.asExpr() = sinkDeclaration.getATarget() and - headerInputNode.asExpr() = sinkDeclaration.getValue() - ) - } - - override DataFlow::Node getHeaderInputNode() { result = headerInputNode } - } - - class FlaskMakeResponseExtendCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { - DataFlow::Node headerInputNode; - - FlaskMakeResponseExtendCall() { - exists( - DataFlow::CallCfgNode headerInstance, DataFlow::AttrRead responseMethod, - DataFlow::AttrRead extendMethod - | - headerInstance = API::moduleImport("flask").getMember("make_response").getACall() and - responseMethod.getAttributeName() = "headers" and - responseMethod.getObject().getALocalSource() = headerInstance and - extendMethod.getAttributeName() = "extend" and - extendMethod.getObject().getALocalSource() = responseMethod and - this.getFunction() = extendMethod and - headerInputNode = this.getArg(0) - ) - } - - override DataFlow::Node getHeaderInputNode() { result = headerInputNode } - } - - class FlaskResponseArg extends DataFlow::CallCfgNode, HeaderDeclaration::Range { - DataFlow::Node headerInputNode; - - FlaskResponseArg() { - this = API::moduleImport("flask").getMember("Response").getACall() and - headerInputNode = this.getArgByName("headers") - } - - override DataFlow::Node getHeaderInputNode() { result = headerInputNode } - } - - class DjangoResponseSetItemCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { - DjangoResponseSetItemCall() { - exists(DataFlow::AttrRead setItemMethod | - this.getFunction() = setItemMethod and - setItemMethod.getObject().getALocalSource() = - API::moduleImport("django").getMember("http").getMember("HttpResponse").getACall() and - setItemMethod.getAttributeName() = "__setitem__" - ) - } - - override DataFlow::Node getHeaderInputNode() { result = this.getArg(1) } - } - } - - private module Django { - class DjangoResponseAssignCall extends DataFlow::Node, HeaderDeclaration::Range { - DataFlow::Node headerInputNode; - - DjangoResponseAssignCall() { - exists( - DataFlow::CallCfgNode headerInstance, Subscript responseMethod, - DataFlow::Node responseToNode, AssignStmt sinkDeclaration - | - headerInstance = - API::moduleImport("django").getMember("http").getMember("HttpResponse").getACall() and - responseMethod.getValue() = responseToNode.asExpr() and - responseToNode.getALocalSource().asExpr() = headerInstance.asExpr() and - sinkDeclaration.getATarget() = responseMethod and - this.asExpr() = sinkDeclaration.getATarget() and - headerInputNode.asExpr() = sinkDeclaration.getValue() - ) - } - - override DataFlow::Node getHeaderInputNode() { result = headerInputNode } - } - } -} From 4963caf5067c0467e7a88f1b361dfda09c4b9822 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 18 Jun 2021 02:03:27 +0200 Subject: [PATCH 013/361] Rewrite frameworks modeling --- .../experimental/semmle/python/Frameworks.qll | 3 + .../semmle/python/frameworks/Django.qll | 78 +++++++++++++++++++ .../semmle/python/frameworks/Flask.qll | 74 ++++++++++++++++++ .../semmle/python/frameworks/Werkzeug.qll | 31 ++++++++ 4 files changed, 186 insertions(+) create mode 100644 python/ql/src/experimental/semmle/python/frameworks/Django.qll create mode 100644 python/ql/src/experimental/semmle/python/frameworks/Flask.qll create mode 100644 python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll diff --git a/python/ql/src/experimental/semmle/python/Frameworks.qll b/python/ql/src/experimental/semmle/python/Frameworks.qll index ca1dd04e57d..da57f56e8cc 100644 --- a/python/ql/src/experimental/semmle/python/Frameworks.qll +++ b/python/ql/src/experimental/semmle/python/Frameworks.qll @@ -3,3 +3,6 @@ */ private import experimental.semmle.python.frameworks.Stdlib +private import experimental.semmle.python.frameworks.Flask +private import experimental.semmle.python.frameworks.Django +private import experimental.semmle.python.frameworks.Werkzeug diff --git a/python/ql/src/experimental/semmle/python/frameworks/Django.qll b/python/ql/src/experimental/semmle/python/frameworks/Django.qll new file mode 100644 index 00000000000..3353881fff8 --- /dev/null +++ b/python/ql/src/experimental/semmle/python/frameworks/Django.qll @@ -0,0 +1,78 @@ +/** + * Provides classes modeling security-relevant aspects of the `django` PyPI package. + * See https://www.djangoproject.com/. + */ + +private import python +private import semmle.python.frameworks.Django +private import semmle.python.dataflow.new.DataFlow +private import experimental.semmle.python.Concepts +private import semmle.python.ApiGraphs + +private module PrivateDjango { + API::Node django() { result = API::moduleImport("django") } + + private module django { + API::Node http() { result = django().getMember("http") } + + module http { + API::Node response() { result = http().getMember("response") } + + module response { + module HttpResponse { + API::Node baseClassRef() { + result = response().getMember("HttpResponse").getReturn() + or + // Handle `django.http.HttpResponse` alias + result = http().getMember("HttpResponse").getReturn() + } + + /** Gets a reference to a header instance. */ + private DataFlow::LocalSourceNode headerInstance(DataFlow::TypeTracker t) { + t.start() and + ( + exists(SubscriptNode subscript | + subscript.getObject() = baseClassRef().getAUse().asCfgNode() and + result.asCfgNode() = subscript + ) + or + result.(DataFlow::AttrRead).getObject() = baseClassRef().getAUse() + ) + or + exists(DataFlow::TypeTracker t2 | result = headerInstance(t2).track(t2, t)) + } + + /** Gets a reference to a header instance use. */ + private DataFlow::Node headerInstance() { + headerInstance(DataFlow::TypeTracker::end()).flowsTo(result) + } + + /** Gets a reference to a header instance call with `__setitem__`. */ + private DataFlow::Node headerSetItemCall() { + result = headerInstance() and + result.(DataFlow::AttrRead).getAttributeName() = "__setitem__" + } + + class DjangoResponseSetItemCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + DjangoResponseSetItemCall() { this.getFunction() = headerSetItemCall() } + + override DataFlow::Node getHeaderInput() { result = this.getArg([0, 1]) } + } + + class DjangoResponseDefinition extends DataFlow::Node, HeaderDeclaration::Range { + DataFlow::Node headerInput; + + DjangoResponseDefinition() { + this.asCfgNode().(DefinitionNode) = headerInstance().asCfgNode() and + headerInput.asCfgNode() = this.asCfgNode().(DefinitionNode).getValue() + } + + override DataFlow::Node getHeaderInput() { + result.asExpr() in [headerInput.asExpr(), this.asExpr().(Subscript).getIndex()] + } + } + } + } + } + } +} diff --git a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll new file mode 100644 index 00000000000..4ed3ed58e3c --- /dev/null +++ b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll @@ -0,0 +1,74 @@ +/** + * Provides classes modeling security-relevant aspects of the `flask` PyPI package. + * See https://flask.palletsprojects.com/en/1.1.x/. + */ + +private import python +private import semmle.python.frameworks.Flask +private import semmle.python.dataflow.new.DataFlow +private import experimental.semmle.python.Concepts +private import semmle.python.ApiGraphs + +module ExperimentalFlask { + /** + * A reference to either `flask.make_response` function, or the `make_response` method on + * an instance of `flask.Flask`. This creates an instance of the `flask_response` + * class (class-attribute on a flask application), which by default is + * `flask.Response`. + * + * See + * - https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.make_response + * - https://flask.palletsprojects.com/en/1.1.x/api/#flask.make_response + */ + private API::Node flaskMakeResponse() { + result in [ + API::moduleImport("flask").getMember("make_response"), + Flask::FlaskApp::instance().getMember("make_response") + ] + } + + /** Gets a reference to a header instance. */ + private DataFlow::LocalSourceNode headerInstance(DataFlow::TypeTracker t) { + t.start() and + result.(DataFlow::AttrRead).getObject().getALocalSource() = + [Flask::Response::classRef(), flaskMakeResponse()].getReturn().getAUse() + or + exists(DataFlow::TypeTracker t2 | result = headerInstance(t2).track(t2, t)) + } + + /** Gets a reference to a header instance use. */ + private DataFlow::Node headerInstance() { + headerInstance(DataFlow::TypeTracker::end()).flowsTo(result) + } + + /** Gets a reference to a header instance call/subscript */ + private DataFlow::Node headerInstanceCall() { + headerInstance() in [result.(DataFlow::AttrRead), result.(DataFlow::AttrRead).getObject()] or + headerInstance().asExpr() = result.asExpr().(Subscript).getObject() + } + + class FlaskHeaderDefinition extends DataFlow::Node, HeaderDeclaration::Range { + DataFlow::Node headerInput; + + FlaskHeaderDefinition() { + this.asCfgNode().(DefinitionNode) = headerInstanceCall().asCfgNode() and + headerInput.asCfgNode() = this.asCfgNode().(DefinitionNode).getValue() + } + + override DataFlow::Node getHeaderInput() { + result.asExpr() in [headerInput.asExpr(), this.asExpr().(Subscript).getIndex()] + } + } + + private class FlaskMakeResponseExtend extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + FlaskMakeResponseExtend() { this.getFunction() = headerInstanceCall() } + + override DataFlow::Node getHeaderInput() { result = this.getArg(0) } + } + + private class FlaskResponse extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + FlaskResponse() { this = Flask::Response::classRef().getACall() } + + override DataFlow::Node getHeaderInput() { result = this.getArgByName("headers") } + } +} diff --git a/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll b/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll new file mode 100644 index 00000000000..4c7e68f165a --- /dev/null +++ b/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll @@ -0,0 +1,31 @@ +/** + * Provides classes modeling security-relevant aspects of the `Werkzeug` PyPI package. + * See + * - https://pypi.org/project/Werkzeug/ + * - https://werkzeug.palletsprojects.com/en/1.0.x/#werkzeug + */ + +private import python +private import semmle.python.frameworks.Flask +private import semmle.python.dataflow.new.DataFlow +private import experimental.semmle.python.Concepts +private import semmle.python.ApiGraphs + +private module Werkzeug { + module datastructures { + module Headers { + class WerkzeugHeaderAddCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + WerkzeugHeaderAddCall() { + this.getFunction().(DataFlow::AttrRead).getObject().getALocalSource() = + API::moduleImport("werkzeug") + .getMember("datastructures") + .getMember("Headers") + .getACall() and + this.getFunction().(DataFlow::AttrRead).getAttributeName() = "add" + } + + override DataFlow::Node getHeaderInput() { result = this.getArg(_) } + } + } + } +} From dcb1da338b1a8d4c378b1ac88d04c5e0dce970f9 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 18 Jun 2021 02:03:56 +0200 Subject: [PATCH 014/361] Extend documentation --- .../experimental/semmle/python/Concepts.qll | 23 +++++++++++++++++-- .../python/security/injection/HTTPHeaders.qll | 5 +++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 530b8d20ec6..2036a6a671e 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -14,16 +14,35 @@ private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.TaintTracking private import experimental.semmle.python.Frameworks +/** Provides classes for modeling HTTP Header APIs. */ module HeaderDeclaration { + /** + * A data-flow node that collects functions setting HTTP Headers' content. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `HeaderDeclaration` instead. + */ abstract class Range extends DataFlow::Node { - abstract DataFlow::Node getHeaderInputNode(); + /** + * Gets the argument containing the header value. + */ + abstract DataFlow::Node getHeaderInput(); } } +/** + * A data-flow node that collects functions setting HTTP Headers' content. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `HeaderDeclaration` instead. + */ class HeaderDeclaration extends DataFlow::Node { HeaderDeclaration::Range range; HeaderDeclaration() { this = range } - DataFlow::Node getHeaderInputNode() { result = range.getHeaderInputNode() } + /** + * Gets the argument containing the header value. + */ + DataFlow::Node getHeaderInput() { result = range.getHeaderInput() } } diff --git a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll index 1215710c1aa..e049caa2609 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll @@ -4,12 +4,15 @@ import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking import semmle.python.dataflow.new.RemoteFlowSources +/** + * A taint-tracking configuration for detecting HTTP Header injections. + */ class HeaderInjectionFlowConfig extends TaintTracking::Configuration { HeaderInjectionFlowConfig() { this = "HeaderInjectionFlowConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } override predicate isSink(DataFlow::Node sink) { - sink = any(HeaderDeclaration headerDeclaration).getHeaderInputNode() + sink = any(HeaderDeclaration headerDeclaration).getHeaderInput() } } From 017a778a20d8980700966d54f98b6041b78ad08f Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 18 Jun 2021 20:21:11 +0200 Subject: [PATCH 015/361] Polish make_response and fix extend argument --- .../src/experimental/semmle/python/frameworks/Flask.qll | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll index 4ed3ed58e3c..7ad1aa2e358 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll @@ -21,10 +21,9 @@ module ExperimentalFlask { * - https://flask.palletsprojects.com/en/1.1.x/api/#flask.make_response */ private API::Node flaskMakeResponse() { - result in [ - API::moduleImport("flask").getMember("make_response"), - Flask::FlaskApp::instance().getMember("make_response") - ] + result = + [API::moduleImport("flask"), Flask::FlaskApp::instance()] + .getMember(["make_response", "jsonify", "make_default_options_response"]) } /** Gets a reference to a header instance. */ @@ -63,7 +62,7 @@ module ExperimentalFlask { private class FlaskMakeResponseExtend extends DataFlow::CallCfgNode, HeaderDeclaration::Range { FlaskMakeResponseExtend() { this.getFunction() = headerInstanceCall() } - override DataFlow::Node getHeaderInput() { result = this.getArg(0) } + override DataFlow::Node getHeaderInput() { result = this.getArg(_) } } private class FlaskResponse extends DataFlow::CallCfgNode, HeaderDeclaration::Range { From b10ade17beeeefe3b5811f8b7a97c60b8b14555a Mon Sep 17 00:00:00 2001 From: jorgectf Date: Sun, 20 Jun 2021 00:13:59 +0200 Subject: [PATCH 016/361] Update HeaderDeclaration input naming --- python/ql/src/experimental/semmle/python/Concepts.qll | 4 ++-- .../ql/src/experimental/semmle/python/frameworks/Django.qll | 4 ++-- .../ql/src/experimental/semmle/python/frameworks/Flask.qll | 6 +++--- .../src/experimental/semmle/python/frameworks/Werkzeug.qll | 2 +- .../semmle/python/security/injection/HTTPHeaders.qll | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 309e40b4471..a3d2104df52 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -159,7 +159,7 @@ module HeaderDeclaration { /** * Gets the argument containing the header value. */ - abstract DataFlow::Node getHeaderInput(); + abstract DataFlow::Node getAnInput(); } } @@ -177,5 +177,5 @@ class HeaderDeclaration extends DataFlow::Node { /** * Gets the argument containing the header value. */ - DataFlow::Node getHeaderInput() { result = range.getHeaderInput() } + DataFlow::Node getAnInput() { result = range.getAnInput() } } diff --git a/python/ql/src/experimental/semmle/python/frameworks/Django.qll b/python/ql/src/experimental/semmle/python/frameworks/Django.qll index 3353881fff8..68153dfae00 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Django.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Django.qll @@ -56,7 +56,7 @@ private module PrivateDjango { class DjangoResponseSetItemCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { DjangoResponseSetItemCall() { this.getFunction() = headerSetItemCall() } - override DataFlow::Node getHeaderInput() { result = this.getArg([0, 1]) } + override DataFlow::Node getAnInput() { result = this.getArg([0, 1]) } } class DjangoResponseDefinition extends DataFlow::Node, HeaderDeclaration::Range { @@ -67,7 +67,7 @@ private module PrivateDjango { headerInput.asCfgNode() = this.asCfgNode().(DefinitionNode).getValue() } - override DataFlow::Node getHeaderInput() { + override DataFlow::Node getAnInput() { result.asExpr() in [headerInput.asExpr(), this.asExpr().(Subscript).getIndex()] } } diff --git a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll index 7ad1aa2e358..a62c38bb060 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll @@ -54,7 +54,7 @@ module ExperimentalFlask { headerInput.asCfgNode() = this.asCfgNode().(DefinitionNode).getValue() } - override DataFlow::Node getHeaderInput() { + override DataFlow::Node getAnInput() { result.asExpr() in [headerInput.asExpr(), this.asExpr().(Subscript).getIndex()] } } @@ -62,12 +62,12 @@ module ExperimentalFlask { private class FlaskMakeResponseExtend extends DataFlow::CallCfgNode, HeaderDeclaration::Range { FlaskMakeResponseExtend() { this.getFunction() = headerInstanceCall() } - override DataFlow::Node getHeaderInput() { result = this.getArg(_) } + override DataFlow::Node getAnInput() { result = this.getArg(_) } } private class FlaskResponse extends DataFlow::CallCfgNode, HeaderDeclaration::Range { FlaskResponse() { this = Flask::Response::classRef().getACall() } - override DataFlow::Node getHeaderInput() { result = this.getArgByName("headers") } + override DataFlow::Node getAnInput() { result = this.getArgByName("headers") } } } diff --git a/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll b/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll index 4c7e68f165a..d37fefe2af8 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll @@ -24,7 +24,7 @@ private module Werkzeug { this.getFunction().(DataFlow::AttrRead).getAttributeName() = "add" } - override DataFlow::Node getHeaderInput() { result = this.getArg(_) } + override DataFlow::Node getAnInput() { result = this.getArg(_) } } } } diff --git a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll index e049caa2609..d31a7d5ac9d 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll @@ -13,6 +13,6 @@ class HeaderInjectionFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } override predicate isSink(DataFlow::Node sink) { - sink = any(HeaderDeclaration headerDeclaration).getHeaderInput() + sink = any(HeaderDeclaration headerDeclaration).getAnInput() } } From b866f1b21eb89710c69c7460f1890e1e204fa386 Mon Sep 17 00:00:00 2001 From: haby0 Date: Fri, 2 Jul 2021 19:30:33 +0800 Subject: [PATCH 017/361] Add CWE-348 ClientSuppliedIpUsedInSecurityCheck --- .../ClientSuppliedIpUsedInSecurityCheck.py | 35 +++++ .../ClientSuppliedIpUsedInSecurityCheck.qhelp | 35 +++++ .../ClientSuppliedIpUsedInSecurityCheck.ql | 48 +++++++ ...ClientSuppliedIpUsedInSecurityCheckLib.qll | 130 ++++++++++++++++++ ...ientSuppliedIpUsedInSecurityCheck.expected | 11 ++ .../ClientSuppliedIpUsedInSecurityCheck.py | 35 +++++ .../ClientSuppliedIpUsedInSecurityCheck.qlref | 1 + 7 files changed, 295 insertions(+) create mode 100644 python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py create mode 100644 python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qhelp create mode 100644 python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql create mode 100644 python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qlref diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py new file mode 100644 index 00000000000..5ae8d3dd1ab --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :ip address spoofing +""" +from flask import Flask +from flask import request + +app = Flask(__name__) + +@app.route('/bad1') +def bad1(): + client_ip = request.headers.get('x-forwarded-for') + if not client_ip.startswith('192.168.'): + raise Exception('ip illegal') + return 'bad1' + +@app.route('/bad2') +def bad2(): + client_ip = request.headers.get('x-forwarded-for') + if not client_ip == '127.0.0.1': + raise Exception('ip illegal') + return 'bad2' + +@app.route('/good1') +def good1(): + client_ip = request.headers.get('x-forwarded-for') + client_ip = client_ip.split(',')[client_ip.split(',').length - 1] + if not client_ip == '127.0.0.1': + raise Exception('ip illegal') + return 'good1' + +if __name__ == '__main__': + app.debug = True + app.run() \ No newline at end of file diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qhelp b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qhelp new file mode 100644 index 00000000000..653c93341c9 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qhelp @@ -0,0 +1,35 @@ + + + +

    An original client IP address is retrieved from an http header (X-Forwarded-For or X-Real-IP or Proxy-Client-IP +etc.), which is used to ensure security. Attackers can forge the value of these identifiers to +bypass a ban-list, for example.

    + +
    + + +

    Do not trust the values of HTTP headers allegedly identifying the originating IP. If you are aware your application will run behind some reverse proxies then the last entry of a X-Forwarded-For header value may be more trustworthy than the rest of it because some reverse proxies append the IP address they observed to the end of any remote-supplied header.

    + +
    + + +

    The following examples show the bad case and the good case respectively. +In bad1 method and bad2 method, the client ip the X-Forwarded-For is split into comma-separated values, but the less-trustworthy first one is used. Both of these examples could be deceived by providing a forged HTTP header. The method +good1 similarly splits an X-Forwarded-For value, but uses the last, more-trustworthy entry.

    + + + +
    + + +
  • Dennis Schneider: +Prevent IP address spoofing with X-Forwarded-For header when using AWS ELB and Clojure Ring +
  • + +
  • Security Rule Zero: A Warning about X-Forwarded-For +
  • + +
    +
    diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql new file mode 100644 index 00000000000..7866fbd681c --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql @@ -0,0 +1,48 @@ +/** + * @name IP address spoofing + * @description A remote endpoint identifier is read from an HTTP header. Attackers can modify the value + * of the identifier to forge the client ip. + * @kind path-problem + * @problem.severity error + * @precision high + * @id py/ip-address-spoofing + * @tags security + * external/cwe/cwe-348 + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import ClientSuppliedIpUsedInSecurityCheckLib +import DataFlow::PathGraph + +/** + * Taint-tracking configuration tracing flow from obtaining a client ip from an HTTP header to a sensitive use. + */ +class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configuration { + ClientSuppliedIpUsedInSecurityCheckConfig() { this = "ClientSuppliedIpUsedInSecurityCheckConfig" } + + override predicate isSource(DataFlow::Node source) { + source instanceof ClientSuppliedIpUsedInSecurityCheck + } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof ClientSuppliedIpUsedInSecurityCheckSink + } + + override predicate isSanitizer(DataFlow::Node node) { + exists(Subscript ss | + not ss.getIndex().(IntegerLiteral).getText() = "0" and + ss.getObject().(Call).getFunc().(Attribute).getName() = "split" and + ss.getObject().(Call).getArg(0).(StrConst).getText() = "," and + ss.getObject().(Call).getFunc().(Attribute).getObject() = node.asExpr() + ) + } +} + +from + ClientSuppliedIpUsedInSecurityCheckConfig config, DataFlow::PathNode source, + DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "IP address spoofing might include code from $@.", + source.getNode(), "this user input" diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll new file mode 100644 index 00000000000..49af8b2bbf5 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll @@ -0,0 +1,130 @@ +private import python +private import semmle.python.Concepts +private import semmle.python.ApiGraphs +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources + +/** + * A data flow source of the client ip obtained according to the remote endpoint identifier specified + * (`X-Forwarded-For`, `X-Real-IP`, `Proxy-Client-IP`, etc.) in the header. + * + * For example: `request.headers.get("X-Forwarded-For")`. + */ +abstract class ClientSuppliedIpUsedInSecurityCheck extends DataFlow::CallCfgNode { } + +private class FlaskClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { + FlaskClientSuppliedIpUsedInSecurityCheck() { + this = + API::moduleImport("flask") + .getMember("request") + .getMember("headers") + .getMember(["get", "get_all", "getlist"]) + .getACall() and + this.getArg(0).asCfgNode().getNode().(StrConst).getText().toLowerCase() = + clientIpParameterName() + } +} + +private class DjangoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { + DjangoClientSuppliedIpUsedInSecurityCheck() { + exists(RemoteFlowSource rfs, DataFlow::LocalSourceNode lsn | + rfs.getSourceType() = "django.http.request.HttpRequest" and rfs.asCfgNode() = lsn.asCfgNode() + | + lsn.flowsTo(DataFlow::exprNode(this.getFunction() + .asExpr() + .(Attribute) + .getObject() + .(Attribute) + .getObject())) and + this.getFunction().asExpr().(Attribute).getName() = "get" and + this.getFunction().asExpr().(Attribute).getObject().(Attribute).getName() in [ + "headers", "META" + ] and + this.getArg(0).asCfgNode().getNode().(StrConst).getText().toLowerCase() = + clientIpParameterName() + ) + } +} + +private string clientIpParameterName() { + result in [ + "x-forwarded-for", "x_forwarded_for", "x-real-ip", "x_real_ip", "proxy-client-ip", + "proxy_client_ip", "wl-proxy-client-ip", "wl_proxy_client_ip", "http_x_forwarded_for", + "http-x-forwarded-for", "http_x_forwarded", "http_x_cluster_client_ip", "http_client_ip", + "http_forwarded_for", "http_forwarded", "http_via", "remote_addr" + ] +} + +/** A data flow sink for ip address forgery vulnerabilities. */ +abstract class ClientSuppliedIpUsedInSecurityCheckSink extends DataFlow::Node { } + +/** A data flow sink for sql operation. */ +private class SqlOperationSink extends ClientSuppliedIpUsedInSecurityCheckSink { + SqlOperationSink() { this = any(SqlExecution e).getSql() } +} + +/** + * A data flow sink for remote client ip comparison. + * + * For example: `if not ipAddr.startswith('192.168.') : ...` determine whether the client ip starts + * with `192.168.`, and the program can be deceived by forging the ip address. + */ +private class CompareSink extends ClientSuppliedIpUsedInSecurityCheckSink { + CompareSink() { + exists(Call call | + call.getFunc().(Attribute).getName() = "startswith" and + call.getArg(0).(StrConst).getText().regexpMatch(getIpAddressRegex()) and + not call.getArg(0).(StrConst).getText() = "0:0:0:0:0:0:0:1" and + call.getFunc().(Attribute).getObject() = this.asExpr() + ) + or + exists(Compare compare | + ( + compare.getOp(0) instanceof Eq or + compare.getOp(0) instanceof NotEq + ) and + ( + compare.getLeft() = this.asExpr() and + compare.getComparator(0).(StrConst).getText() instanceof PrivateHostName and + not compare.getComparator(0).(StrConst).getText() = "0:0:0:0:0:0:0:1" + or + compare.getComparator(0) = this.asExpr() and + compare.getLeft().(StrConst).getText() instanceof PrivateHostName and + not compare.getLeft().(StrConst).getText() = "0:0:0:0:0:0:0:1" + ) + ) + or + exists(Compare compare | + ( + compare.getOp(0) instanceof In or + compare.getOp(0) instanceof NotIn + ) and + ( + compare.getLeft() = this.asExpr() + or + compare.getComparator(0) = this.asExpr() + ) + ) + or + exists(Call call | + call.getFunc().(Attribute).getName() = "add" and + call.getArg(0) = this.asExpr() + ) + } +} + +string getIpAddressRegex() { + result = + "^((10\\.((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?)|(192\\.168\\.)|172\\.(1[6789]|2[0-9]|3[01])\\.)((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)$" +} + +/** + * A string matching private host names of IPv4 and IPv6, which only matches the host portion therefore checking for port is not necessary. + * Several examples are localhost, reserved IPv4 IP addresses including 127.0.0.1, 10.x.x.x, 172.16.x,x, 192.168.x,x, and reserved IPv6 addresses including [0:0:0:0:0:0:0:1] and [::1] + */ +private class PrivateHostName extends string { + bindingset[this] + PrivateHostName() { + this.regexpMatch("(?i)localhost(?:[:/?#].*)?|127\\.0\\.0\\.1(?:[:/?#].*)?|10(?:\\.[0-9]+){3}(?:[:/?#].*)?|172\\.16(?:\\.[0-9]+){2}(?:[:/?#].*)?|192.168(?:\\.[0-9]+){2}(?:[:/?#].*)?|\\[?0:0:0:0:0:0:0:1\\]?(?:[:/?#].*)?|\\[?::1\\]?(?:[:/?#].*)?") + } +} diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected new file mode 100644 index 00000000000..2e6442cc17f --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected @@ -0,0 +1,11 @@ +edges +| ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | +| ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | +nodes +| ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | +| ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | +#select +| ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | this user input | +| ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | this user input | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py new file mode 100644 index 00000000000..3edb73e575f --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :ip address spoofing +""" +from flask import Flask +from flask import request + +app = Flask(__name__) + +@app.route('/bad1') +def bad1(): + client_ip = request.headers.get('x-forwarded-for') + if not client_ip.startswith('192.168.'): + raise Exception('ip illegal') + return 'bad1' + +@app.route('/bad2') +def bad2(): + client_ip = request.headers.get('x-forwarded-for') + if not client_ip == '127.0.0.1': + raise Exception('ip illegal') + return 'bad2' + +@app.route('/good1') +def good1(): + client_ip = request.headers.get('x-forwarded-for') + client_ip = client_ip.split(',')[client_ip.split(',').length - 1] + if not client_ip == '127.0.0.1': + raise Exception('ip illegal') + return 'good1' + +if __name__ == '__main__': + app.debug = True + app.run() diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qlref b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qlref new file mode 100644 index 00000000000..2a1775fe06a --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql \ No newline at end of file From e8d08279168c4dd494acdea4baa2448fb9c25804 Mon Sep 17 00:00:00 2001 From: haby0 Date: Mon, 5 Jul 2021 10:42:15 +0800 Subject: [PATCH 018/361] Add tornado source --- ...ClientSuppliedIpUsedInSecurityCheckLib.qll | 21 +++++++++++ ...ientSuppliedIpUsedInSecurityCheck.expected | 20 ++++++----- ...dIpUsedInSecurityCheck.py => flask_bad.py} | 8 ----- .../Security/CWE-348/flask_good.py | 21 +++++++++++ .../Security/CWE-348/tornado_bad.py | 36 +++++++++++++++++++ 5 files changed, 90 insertions(+), 16 deletions(-) rename python/ql/test/experimental/query-tests/Security/CWE-348/{ClientSuppliedIpUsedInSecurityCheck.py => flask_bad.py} (69%) create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-348/flask_good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-348/tornado_bad.py diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll index 49af8b2bbf5..8113fd17c9d 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll @@ -46,6 +46,27 @@ private class DjangoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIp } } +private class TornadoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { + TornadoClientSuppliedIpUsedInSecurityCheck() { + exists(RemoteFlowSource rfs, DataFlow::LocalSourceNode lsn | + rfs.getSourceType() = "tornado.web.RequestHandler" and rfs.asCfgNode() = lsn.asCfgNode() + | + lsn.flowsTo(DataFlow::exprNode(this.getFunction() + .asExpr() + .(Attribute) + .getObject() + .(Attribute) + .getObject() + .(Attribute) + .getObject())) and + this.getFunction().asExpr().(Attribute).getName() in ["get", "get_list"] and + this.getFunction().asExpr().(Attribute).getObject().(Attribute).getName() = "headers" and + this.getArg(0).asCfgNode().getNode().(StrConst).getText().toLowerCase() = + clientIpParameterName() + ) + } +} + private string clientIpParameterName() { result in [ "x-forwarded-for", "x_forwarded_for", "x-real-ip", "x_real_ip", "proxy-client-ip", diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected index 2e6442cc17f..38536f2b7a2 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected @@ -1,11 +1,15 @@ edges -| ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | -| ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | +| flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | +| flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | +| tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | nodes -| ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | -| ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | +| flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | +| flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | +| tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | #select -| ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | this user input | -| ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | this user input | +| flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | this user input | +| flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | this user input | +| tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | this user input | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py b/python/ql/test/experimental/query-tests/Security/CWE-348/flask_bad.py similarity index 69% rename from python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py rename to python/ql/test/experimental/query-tests/Security/CWE-348/flask_bad.py index 3edb73e575f..b357a9316fd 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-348/flask_bad.py @@ -22,14 +22,6 @@ def bad2(): raise Exception('ip illegal') return 'bad2' -@app.route('/good1') -def good1(): - client_ip = request.headers.get('x-forwarded-for') - client_ip = client_ip.split(',')[client_ip.split(',').length - 1] - if not client_ip == '127.0.0.1': - raise Exception('ip illegal') - return 'good1' - if __name__ == '__main__': app.debug = True app.run() diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/flask_good.py b/python/ql/test/experimental/query-tests/Security/CWE-348/flask_good.py new file mode 100644 index 00000000000..da42c59724a --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-348/flask_good.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :ip address spoofing +""" +from flask import Flask +from flask import request + +app = Flask(__name__) + +@app.route('/good1') +def good1(): + client_ip = request.headers.get('x-forwarded-for') + client_ip = client_ip.split(',')[len(client_ip.split(',')) - 1] + if not client_ip == '127.0.0.1': + raise Exception('ip illegal') + return 'good1' + +if __name__ == '__main__': + app.debug = True + app.run() diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/tornado_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-348/tornado_bad.py new file mode 100644 index 00000000000..23ad29d8b09 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-348/tornado_bad.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :ip address spoofing +""" +import tornado.httpserver +import tornado.options +import tornado.web +import tornado.ioloop + +from tornado.options import define, options + +define("port", default=8000, help="run on the given port,default 8000", type=int) + + +class IndexHandler(tornado.web.RequestHandler): + def get(self): + client_ip = self.request.headers.get('x-forwarded-for') + if client_ip: + client_ip = client_ip.split(',')[len(client_ip.split(',')) - 1] + else: + client_ip = self.request.headers.get('REMOTE_ADDR', None) + if not client_ip == '127.0.0.1': + raise Exception('ip illegal') + self.write("hello.") + +handlers = [(r"/", IndexHandler)] + +if __name__ == "__main__": + tornado.options.parse_command_line() + app = tornado.web.Application( + handlers + ) + http_server = tornado.httpserver.HTTPServer(app) + http_server.listen(options.port) + tornado.ioloop.IOLoop.instance().start() From 8d0386b049a03778251e7a8893daf1623f14b3d8 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Sun, 25 Jul 2021 04:35:22 +0200 Subject: [PATCH 019/361] Split into `getNameArg` and `getValueArg` --- .../experimental/semmle/python/Concepts.qll | 20 ++++++++++++---- .../semmle/python/frameworks/Django.qll | 10 +++++--- .../semmle/python/frameworks/Flask.qll | 23 ++++++++++++++----- .../semmle/python/frameworks/Werkzeug.qll | 4 +++- .../python/security/injection/HTTPHeaders.qll | 4 +++- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index a3d2104df52..d5e99205bb1 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -150,21 +150,26 @@ class LDAPEscape extends DataFlow::Node { /** Provides classes for modeling HTTP Header APIs. */ module HeaderDeclaration { /** - * A data-flow node that collects functions setting HTTP Headers' content. + * A data-flow node that collects functions setting HTTP Headers. * * Extend this class to model new APIs. If you want to refine existing API models, * extend `HeaderDeclaration` instead. */ abstract class Range extends DataFlow::Node { + /** + * Gets the argument containing the header name. + */ + abstract DataFlow::Node getNameArg(); + /** * Gets the argument containing the header value. */ - abstract DataFlow::Node getAnInput(); + abstract DataFlow::Node getValueArg(); } } /** - * A data-flow node that collects functions setting HTTP Headers' content. + * A data-flow node that collects functions setting HTTP Headers. * * Extend this class to model new APIs. If you want to refine existing API models, * extend `HeaderDeclaration` instead. @@ -175,7 +180,12 @@ class HeaderDeclaration extends DataFlow::Node { HeaderDeclaration() { this = range } /** - * Gets the argument containing the header value. + * Gets the argument containing the header name. */ - DataFlow::Node getAnInput() { result = range.getAnInput() } + DataFlow::Node getNameArg() { result = range.getNameArg() } + + /** + * Gets the argument containing the header name. + */ + DataFlow::Node getValueArg() { result = range.getValueArg() } } diff --git a/python/ql/src/experimental/semmle/python/frameworks/Django.qll b/python/ql/src/experimental/semmle/python/frameworks/Django.qll index 68153dfae00..c525b73b40e 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Django.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Django.qll @@ -56,7 +56,9 @@ private module PrivateDjango { class DjangoResponseSetItemCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range { DjangoResponseSetItemCall() { this.getFunction() = headerSetItemCall() } - override DataFlow::Node getAnInput() { result = this.getArg([0, 1]) } + override DataFlow::Node getNameArg() { result = this.getArg(0) } + + override DataFlow::Node getValueArg() { result = this.getArg(1) } } class DjangoResponseDefinition extends DataFlow::Node, HeaderDeclaration::Range { @@ -67,9 +69,11 @@ private module PrivateDjango { headerInput.asCfgNode() = this.asCfgNode().(DefinitionNode).getValue() } - override DataFlow::Node getAnInput() { - result.asExpr() in [headerInput.asExpr(), this.asExpr().(Subscript).getIndex()] + override DataFlow::Node getNameArg() { + result.asExpr() = this.asExpr().(Subscript).getIndex() } + + override DataFlow::Node getValueArg() { result = headerInput } } } } diff --git a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll index a62c38bb060..9c66d9a4601 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll @@ -54,20 +54,31 @@ module ExperimentalFlask { headerInput.asCfgNode() = this.asCfgNode().(DefinitionNode).getValue() } - override DataFlow::Node getAnInput() { - result.asExpr() in [headerInput.asExpr(), this.asExpr().(Subscript).getIndex()] - } + override DataFlow::Node getNameArg() { result.asExpr() = this.asExpr().(Subscript).getIndex() } + + override DataFlow::Node getValueArg() { result = headerInput } } private class FlaskMakeResponseExtend extends DataFlow::CallCfgNode, HeaderDeclaration::Range { - FlaskMakeResponseExtend() { this.getFunction() = headerInstanceCall() } + KeyValuePair item; - override DataFlow::Node getAnInput() { result = this.getArg(_) } + FlaskMakeResponseExtend() { + this.getFunction() = headerInstanceCall() and + item = this.getArg(_).asExpr().(Dict).getAnItem() + } + + override DataFlow::Node getNameArg() { result.asExpr() = item.getKey() } + + override DataFlow::Node getValueArg() { result.asExpr() = item.getValue() } } private class FlaskResponse extends DataFlow::CallCfgNode, HeaderDeclaration::Range { + KeyValuePair item; + FlaskResponse() { this = Flask::Response::classRef().getACall() } - override DataFlow::Node getAnInput() { result = this.getArgByName("headers") } + override DataFlow::Node getNameArg() { result.asExpr() = item.getKey() } + + override DataFlow::Node getValueArg() { result.asExpr() = item.getValue() } } } diff --git a/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll b/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll index d37fefe2af8..dce67c258fb 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Werkzeug.qll @@ -24,7 +24,9 @@ private module Werkzeug { this.getFunction().(DataFlow::AttrRead).getAttributeName() = "add" } - override DataFlow::Node getAnInput() { result = this.getArg(_) } + override DataFlow::Node getNameArg() { result = this.getArg(0) } + + override DataFlow::Node getValueArg() { result = this.getArg(1) } } } } diff --git a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll index d31a7d5ac9d..4ba70cd37a2 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll @@ -13,6 +13,8 @@ class HeaderInjectionFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } override predicate isSink(DataFlow::Node sink) { - sink = any(HeaderDeclaration headerDeclaration).getAnInput() + exists(HeaderDeclaration headerDeclaration | + sink in [headerDeclaration.getNameArg(), headerDeclaration.getValueArg()] + ) } } From 246302453f2ada56acb16dc88baf64d446c9706e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Sep 2021 13:46:18 +0100 Subject: [PATCH 020/361] C++: Add CleartextTransmission query. --- .../CWE/CWE-311/CleartextStorage.inc.qhelp | 2 +- .../CWE/CWE-311/CleartextTransmission.qhelp | 5 +++ .../CWE/CWE-311/CleartextTransmission.ql | 33 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.qhelp create mode 100644 cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp b/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp index eb9a6f8adce..47540e6cf3a 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp @@ -9,7 +9,7 @@ storage.

    -

    Ensure that sensitive information is always encrypted before being stored, especially before writing to a file. +

    Ensure that sensitive information is always encrypted before being stored or transmitted, especially before writing to a file. It may be wise to encrypt information before it is put into a buffer that may be readable in memory.

    In general, decrypt sensitive information only at the point where it is necessary for it to be used in diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.qhelp b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.qhelp new file mode 100644 index 00000000000..d715abca84c --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.qhelp @@ -0,0 +1,5 @@ + + + diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql new file mode 100644 index 00000000000..25a173e4362 --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -0,0 +1,33 @@ +/** + * @name Cleartext transmission of sensitive information + * @description Transmitting sensitive information across a network in + * cleartext can expose it to an attacker. + * @kind problem + * @problem.severity warning + * @security-severity 7.5 TODO + * @precision high + * @id cpp/cleartext-transmission + * @tags security + * external/cwe/cwe-319 + */ + +import cpp +import semmle.code.cpp.security.SensitiveExprs +import semmle.code.cpp.security.FileWrite +import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.valuenumbering.GlobalValueNumbering + +// TODO: network send? + +/** + * TODO + */ +class NetworkRecv extends FunctionCall { + NetworkRecv() { this.getTarget().hasGlobalName("recv") } + + Expr getData() { result = this.getArgument(1) } +} + +from NetworkRecv recv, SensitiveExpr e +where DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(recv.(NetworkRecv).getData())) +select recv, e From cd5a5347fcdaee8455158dd5f7bb909a8d425626 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Sep 2021 13:42:59 +0100 Subject: [PATCH 021/361] C++: Add basic test. --- .../tests/CleartextTransmission.expected | 2 + .../semmle/tests/CleartextTransmission.qlref | 1 + .../CWE/CWE-311/semmle/tests/test3.cpp | 61 +++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.qlref create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected new file mode 100644 index 00000000000..70c9b6bfbfd --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -0,0 +1,2 @@ +| test3.cpp:39:3:39:6 | call to recv | test3.cpp:39:15:39:22 | password | +| test3.cpp:47:3:47:6 | call to recv | test3.cpp:47:15:47:22 | password | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.qlref new file mode 100644 index 00000000000..bb3fc66f1f1 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-311/CleartextTransmission.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp new file mode 100644 index 00000000000..5eafd2dcb70 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -0,0 +1,61 @@ + +typedef unsigned long size_t; + +size_t strlen(const char *s); + +void send(int a, const void *buf, size_t bufLen, int d); +void recv(int a, void *buf, size_t bufLen, int d); + +void LogonUserA(int a, int b, const char *password, int d, int e, int f); + +int val(); + +void test_send(const char *password1, const char *password2, const char *password_hash, const char *message) +{ + { + LogonUserA(val(), val(), password1, val(), val(), val()); // proof `password` is plaintext + + send(val(), password1, strlen(password1), val()); // BAD: `password` is sent plaintext (certainly) [NOT DETECTED] + } + + { + send(val(), password2, strlen(password2), val()); // BAD: `password` is sent plaintext (probably) [NOT DETECTED] + } + + { + send(val(), password_hash, strlen(password_hash), val()); // GOOD: `password` is sent encrypted + } + + { + send(val(), message, strlen(message), val()); // GOOD: `message` is not a password + } +} + +void test_receive() +{ + { + char password[256]; + + recv(val(), password, 256, val()); // BAD: `password` is received plaintext (certainly) + + LogonUserA(val(), val(), password, val(), val(), val()); // (proof `password` is plaintext) + } + + { + char password[256]; + + recv(val(), password, 256, val()); // BAD: `password` is received plaintext (probably) + } + + { + char password_hash[256]; + + recv(val(), password_hash, 256, val()); // GOOD: `password` is received encrypted + } + + { + char message[256]; + + recv(val(), message, 256, val()); // GOOD: `message` is not a password + } +} From 190bc2f0da608d8d75efcc13fff76ef9a1da149a Mon Sep 17 00:00:00 2001 From: Jorge <46056498+jorgectf@users.noreply.github.com> Date: Tue, 7 Sep 2021 19:42:37 +0200 Subject: [PATCH 022/361] Apply suggestions from code review Co-authored-by: Taus --- python/ql/src/experimental/semmle/python/Concepts.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index d5e99205bb1..1b42420b4c1 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -185,7 +185,7 @@ class HeaderDeclaration extends DataFlow::Node { DataFlow::Node getNameArg() { result = range.getNameArg() } /** - * Gets the argument containing the header name. + * Gets the argument containing the header value. */ DataFlow::Node getValueArg() { result = range.getValueArg() } } From 352eab0eca16c46532102e6889e45e4d3222326a Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 7 Sep 2021 19:44:25 +0200 Subject: [PATCH 023/361] Fix `HeaderDeclaration` class' comment --- python/ql/src/experimental/semmle/python/Concepts.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 1b42420b4c1..4cffcff949c 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -171,8 +171,8 @@ module HeaderDeclaration { /** * A data-flow node that collects functions setting HTTP Headers. * - * Extend this class to model new APIs. If you want to refine existing API models, - * extend `HeaderDeclaration` instead. + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `HeaderDeclaration::Range` instead. */ class HeaderDeclaration extends DataFlow::Node { HeaderDeclaration::Range range; From 9b198c6d0ae8fa1a3d9a7e03499c24585bf5e0c8 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 18 Aug 2021 16:52:04 +0200 Subject: [PATCH 024/361] Python: Add some module initialization tests --- .../dataflow/module-initialization/base.py | 1 + .../dataflow/module-initialization/m1.py | 10 ++++++ .../dataflow/module-initialization/test.py | 33 +++++++++++++++++++ .../module-initialization/testOnce.py | 33 +++++++++++++++++++ .../test/experimental/dataflow/validTest.py | 3 ++ 5 files changed, 80 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/module-initialization/base.py create mode 100644 python/ql/test/experimental/dataflow/module-initialization/m1.py create mode 100644 python/ql/test/experimental/dataflow/module-initialization/test.py create mode 100644 python/ql/test/experimental/dataflow/module-initialization/testOnce.py diff --git a/python/ql/test/experimental/dataflow/module-initialization/base.py b/python/ql/test/experimental/dataflow/module-initialization/base.py new file mode 100644 index 00000000000..611e0a87735 --- /dev/null +++ b/python/ql/test/experimental/dataflow/module-initialization/base.py @@ -0,0 +1 @@ +foo = 3 diff --git a/python/ql/test/experimental/dataflow/module-initialization/m1.py b/python/ql/test/experimental/dataflow/module-initialization/m1.py new file mode 100644 index 00000000000..653dfb91997 --- /dev/null +++ b/python/ql/test/experimental/dataflow/module-initialization/m1.py @@ -0,0 +1,10 @@ +# constant +foo = 42 + +import base + +def passOn(x): + return x + +# depends on other constant +bar = passOn(base.foo) diff --git a/python/ql/test/experimental/dataflow/module-initialization/test.py b/python/ql/test/experimental/dataflow/module-initialization/test.py new file mode 100644 index 00000000000..83531bdd92f --- /dev/null +++ b/python/ql/test/experimental/dataflow/module-initialization/test.py @@ -0,0 +1,33 @@ +# 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") + +import base + +base.foo = 42 + +import m1 + +def test_const(): + SINK(m1.foo) + +def test_overwritten(): + SINK(m1.bar) diff --git a/python/ql/test/experimental/dataflow/module-initialization/testOnce.py b/python/ql/test/experimental/dataflow/module-initialization/testOnce.py new file mode 100644 index 00000000000..663f8acb997 --- /dev/null +++ b/python/ql/test/experimental/dataflow/module-initialization/testOnce.py @@ -0,0 +1,33 @@ +# 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") + +import m1 + +import base + +base.foo = 42 + +def test_const(): + SINK(m1.foo) + +def test_unoverwritten(): + SINK_F(m1.bar) diff --git a/python/ql/test/experimental/dataflow/validTest.py b/python/ql/test/experimental/dataflow/validTest.py index 2367344580b..080bb6bf24f 100644 --- a/python/ql/test/experimental/dataflow/validTest.py +++ b/python/ql/test/experimental/dataflow/validTest.py @@ -56,3 +56,6 @@ if __name__ == "__main__": check_tests_valid("variable-capture.in") check_tests_valid("variable-capture.nonlocal") check_tests_valid("variable-capture.dict") + # The below fails when trying to import modules + # check_tests_valid("module-initialization.test") + # check_tests_valid("module-initialization.testOnce") From a9c409403c91efb1671e91cd3774267fdbadb289 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 8 Sep 2021 14:44:36 +0200 Subject: [PATCH 025/361] Python: more tests and comments --- .../dataflow/new/internal/DataFlowPrivate.qll | 3 ++ .../module-initialization/localFlow.expected | 45 +++++++++++++++++++ .../module-initialization/localFlow.ql | 20 +++++++++ .../module-initialization/multiphase.py | 43 ++++++++++++++++++ .../test/experimental/dataflow/validTest.py | 1 + 5 files changed, 112 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/module-initialization/localFlow.expected create mode 100644 python/ql/test/experimental/dataflow/module-initialization/localFlow.ql create mode 100644 python/ql/test/experimental/dataflow/module-initialization/multiphase.py 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 074289b00fd..9a6d4e572c0 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -245,6 +245,9 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { /** * Holds if there is an Essa flow step from `nodeFrom` to `nodeTo` that does not switch between * local and global SSA variables. + * + * This predicate is currently empty, since `EssaFlow::essaFlowStep` never goes between `EssaNode`s. + * (It only starts in an `EssaNode` in a single case, namely `defToFirstUse` which ends in a `CfgNode`.) */ private predicate localEssaStep(EssaNode nodeFrom, EssaNode nodeTo) { EssaFlow::essaFlowStep(nodeFrom, nodeTo) and diff --git a/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected b/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected new file mode 100644 index 00000000000..686c3d33017 --- /dev/null +++ b/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected @@ -0,0 +1,45 @@ +| base.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | base.py:1:1:1:3 | GSSA Variable foo | +| m1.py:2:7:2:8 | ControlFlowNode for IntegerLiteral | m1.py:2:1:2:3 | GSSA Variable foo | +| m1.py:4:8:4:11 | ControlFlowNode for ImportExpr | m1.py:4:8:4:11 | GSSA Variable base | +| m1.py:4:8:4:11 | GSSA Variable base | m1.py:10:14:10:17 | ControlFlowNode for base | +| m1.py:6:1:6:14 | ControlFlowNode for FunctionExpr | m1.py:6:5:6:10 | GSSA Variable passOn | +| m1.py:6:5:6:10 | GSSA Variable passOn | m1.py:10:7:10:12 | ControlFlowNode for passOn | +| m1.py:10:7:10:22 | ControlFlowNode for passOn() | m1.py:10:1:10:3 | GSSA Variable bar | +| multiphase.py:0:0:0:0 | GSSA Variable __file__ | multiphase.py:4:50:4:57 | ControlFlowNode for __file__ | +| multiphase.py:0:0:0:0 | GSSA Variable expects | multiphase.py:37:2:37:8 | ControlFlowNode for expects | +| multiphase.py:1:8:1:10 | ControlFlowNode for ImportExpr | multiphase.py:1:8:1:10 | GSSA Variable sys | +| multiphase.py:1:8:1:10 | GSSA Variable sys | multiphase.py:4:1:4:3 | ControlFlowNode for sys | +| multiphase.py:2:8:2:9 | ControlFlowNode for ImportExpr | multiphase.py:2:8:2:9 | GSSA Variable os | +| multiphase.py:2:8:2:9 | GSSA Variable os | multiphase.py:4:17:4:18 | ControlFlowNode for os | +| multiphase.py:4:17:4:18 | ControlFlowNode for os | multiphase.py:4:33:4:34 | ControlFlowNode for os | +| multiphase.py:4:17:4:18 | [post read] ControlFlowNode for os | multiphase.py:4:33:4:34 | ControlFlowNode for os | +| multiphase.py:8:1:8:9 | GSSA Variable NONSOURCE | multiphase.py:34:7:34:15 | ControlFlowNode for NONSOURCE | +| multiphase.py:8:13:8:26 | ControlFlowNode for Str | multiphase.py:8:1:8:9 | GSSA Variable NONSOURCE | +| multiphase.py:9:10:9:17 | ControlFlowNode for Str | multiphase.py:9:1:9:6 | GSSA Variable SOURCE | +| multiphase.py:12:1:12:17 | ControlFlowNode for FunctionExpr | multiphase.py:12:5:12:13 | GSSA Variable is_source | +| multiphase.py:16:1:16:12 | ControlFlowNode for FunctionExpr | multiphase.py:16:5:16:8 | GSSA Variable SINK | +| multiphase.py:23:1:23:14 | ControlFlowNode for FunctionExpr | multiphase.py:23:5:23:10 | GSSA Variable SINK_F | +| multiphase.py:29:1:29:14 | ControlFlowNode for FunctionExpr | multiphase.py:29:5:29:11 | GSSA Variable set_foo | +| multiphase.py:29:5:29:11 | GSSA Variable set_foo | multiphase.py:35:1:35:7 | ControlFlowNode for set_foo | +| multiphase.py:34:7:34:15 | ControlFlowNode for NONSOURCE | multiphase.py:34:1:34:3 | GSSA Variable foo | +| multiphase.py:37:2:37:11 | ControlFlowNode for expects()() | multiphase.py:38:5:38:15 | GSSA Variable test_phases | +| test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | +| test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | +| test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | +| test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | +| test.py:17:1:17:14 | ControlFlowNode for FunctionExpr | test.py:17:5:17:10 | GSSA Variable SINK_F | +| test.py:23:8:23:11 | ControlFlowNode for ImportExpr | test.py:23:8:23:11 | GSSA Variable base | +| test.py:23:8:23:11 | GSSA Variable base | test.py:25:1:25:4 | ControlFlowNode for base | +| test.py:27:8:27:9 | ControlFlowNode for ImportExpr | test.py:27:8:27:9 | GSSA Variable m1 | +| test.py:29:1:29:17 | ControlFlowNode for FunctionExpr | test.py:29:5:29:14 | GSSA Variable test_const | +| test.py:32:1:32:23 | ControlFlowNode for FunctionExpr | test.py:32:5:32:20 | GSSA Variable test_overwritten | +| testOnce.py:2:13:2:26 | ControlFlowNode for Str | testOnce.py:2:1:2:9 | GSSA Variable NONSOURCE | +| testOnce.py:3:10:3:17 | ControlFlowNode for Str | testOnce.py:3:1:3:6 | GSSA Variable SOURCE | +| testOnce.py:6:1:6:17 | ControlFlowNode for FunctionExpr | testOnce.py:6:5:6:13 | GSSA Variable is_source | +| testOnce.py:10:1:10:12 | ControlFlowNode for FunctionExpr | testOnce.py:10:5:10:8 | GSSA Variable SINK | +| testOnce.py:17:1:17:14 | ControlFlowNode for FunctionExpr | testOnce.py:17:5:17:10 | GSSA Variable SINK_F | +| testOnce.py:23:8:23:9 | ControlFlowNode for ImportExpr | testOnce.py:23:8:23:9 | GSSA Variable m1 | +| testOnce.py:25:8:25:11 | ControlFlowNode for ImportExpr | testOnce.py:25:8:25:11 | GSSA Variable base | +| testOnce.py:25:8:25:11 | GSSA Variable base | testOnce.py:27:1:27:4 | ControlFlowNode for base | +| testOnce.py:29:1:29:17 | ControlFlowNode for FunctionExpr | testOnce.py:29:5:29:14 | GSSA Variable test_const | +| testOnce.py:32:1:32:25 | ControlFlowNode for FunctionExpr | testOnce.py:32:5:32:22 | GSSA Variable test_unoverwritten | diff --git a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql new file mode 100644 index 00000000000..281881c0de8 --- /dev/null +++ b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql @@ -0,0 +1,20 @@ +// This query should be more focused yet. +import python +import semmle.python.dataflow.new.DataFlow + +pragma[inline] +predicate inCodebase(DataFlow::Node node) { exists(node.getLocation().getFile().getRelativePath()) } + +predicate isTopLevel(DataFlow::Node node) { node.getScope() instanceof Module } + +predicate inFocus(DataFlow::Node node) { + isTopLevel(node) and + inCodebase(node) +} + +from DataFlow::Node nodeFrom, DataFlow::Node nodeTo +where + inFocus(nodeFrom) and + inFocus(nodeTo) and + DataFlow::localFlowStep(nodeFrom, nodeTo) +select nodeFrom, nodeTo diff --git a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py new file mode 100644 index 00000000000..ad41e7e8bfa --- /dev/null +++ b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py @@ -0,0 +1,43 @@ +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname((__file__)))) +from testlib import * + +# 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") + +def set_foo(): + global foo + print(foo) + foo = SOURCE + +foo = NONSOURCE +set_foo() + +@expects(2) +def test_phases(): + global foo + SINK(foo) + foo = NONSOURCE + set_foo() + SINK(foo) diff --git a/python/ql/test/experimental/dataflow/validTest.py b/python/ql/test/experimental/dataflow/validTest.py index 080bb6bf24f..aaa0e792f2c 100644 --- a/python/ql/test/experimental/dataflow/validTest.py +++ b/python/ql/test/experimental/dataflow/validTest.py @@ -56,6 +56,7 @@ if __name__ == "__main__": check_tests_valid("variable-capture.in") check_tests_valid("variable-capture.nonlocal") check_tests_valid("variable-capture.dict") + check_tests_valid("module-initialization.multiphase") # The below fails when trying to import modules # check_tests_valid("module-initialization.test") # check_tests_valid("module-initialization.testOnce") From e27b3162e5890238014ac8a1cbf6630d4bd2f776 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 9 Sep 2021 12:43:08 +0200 Subject: [PATCH 026/361] Python: rewrite `simpleLocalFlowStep` to take into account the split between import time and runtime. --- .../dataflow/new/internal/DataFlowPrivate.qll | 66 ++++++++++++------- .../dataflow/fieldflow/allLocalFlow.expected | 9 +++ .../dataflow/fieldflow/globalStep.expected | 18 +++++ .../module-initialization/localFlow.expected | 13 ++++ .../module-initialization/localFlow.ql | 1 + 5 files changed, 84 insertions(+), 23 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 9a6d4e572c0..e047ee048a9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -152,6 +152,7 @@ class DataFlowExpr = Expr; * Flow comes from definitions, uses and refinements. */ // TODO: Consider constraining `nodeFrom` and `nodeTo` to be in the same scope. +// If they have different enclosing callables, we get consistency errors. module EssaFlow { predicate essaFlowStep(Node nodeFrom, Node nodeTo) { // Definition @@ -225,41 +226,64 @@ module EssaFlow { //-------- /** * This is the local flow predicate that is used as a building block in global - * data flow. It is a strict subset of the `localFlowStep` predicate, as it - * excludes SSA flow through instance fields. + * data flow. + * + * Local flow can happen either at import time, when the module is initialised + * or at runtime when callables in the module are called. */ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { - // If there is ESSA-flow out of a node `node`, we want flow + // If there is local flow out of a node `node`, we want flow // both out of `node` and any post-update node of `node`. exists(Node node | - EssaFlow::essaFlowStep(node, nodeTo) and nodeFrom = update(node) and ( - not node instanceof EssaNode or - not nodeTo instanceof EssaNode or - localEssaStep(node, nodeTo) + importTimeLocalFlowStep(node, nodeTo) or + runtimeLocalFlowStep(node, nodeTo) ) ) } /** - * Holds if there is an Essa flow step from `nodeFrom` to `nodeTo` that does not switch between - * local and global SSA variables. - * - * This predicate is currently empty, since `EssaFlow::essaFlowStep` never goes between `EssaNode`s. - * (It only starts in an `EssaNode` in a single case, namely `defToFirstUse` which ends in a `CfgNode`.) + * Holds if `node` is found at the top level of a module. */ -private predicate localEssaStep(EssaNode nodeFrom, EssaNode nodeTo) { - EssaFlow::essaFlowStep(nodeFrom, nodeTo) and +pragma[inline] +predicate isTopLevel(Node node) { node.getScope() instanceof Module } + +/** Holds if there is local flow from `nodeFrom` to `nodeTo` at import time. */ +predicate importTimeLocalFlowStep(Node nodeFrom, Node nodeTo) { + // As a proxy for whether statements can be executed at import time, + // we check if they appear at the top level. + // This will miss statements inside functions called from the top level. + isTopLevel(nodeFrom) and + isTopLevel(nodeTo) and ( - nodeFrom.getVar() instanceof GlobalSsaVariable and - nodeTo.getVar() instanceof GlobalSsaVariable + EssaFlow::essaFlowStep(nodeFrom, nodeTo) or - not nodeFrom.getVar() instanceof GlobalSsaVariable and - not nodeTo.getVar() instanceof GlobalSsaVariable + exists(SsaVariable def | + def = any(SsaVariable var).getAnUltimateDefinition() and + def.getDefinition() = nodeFrom.asCfgNode() and + def.getVariable() = nodeTo.(ModuleVariableNode).getVariable() + ) ) } +/** Holds if there is local flow from `nodeFrom` to `nodeTo` at runtime. */ +predicate runtimeLocalFlowStep(Node nodeFrom, Node nodeTo) { + // Anything not at the top level can be executed at runtime. + not isTopLevel(nodeFrom) and + not isTopLevel(nodeTo) and + EssaFlow::essaFlowStep(nodeFrom, nodeTo) +} + +/** `ModuleVariable`s are accessed via jump steps at runtime. */ +predicate runtimeJumpStep(Node nodeFrom, Node nodeTo) { + // Module variable read + nodeFrom.(ModuleVariableNode).getARead() = nodeTo + or + // Module variable write + nodeFrom = nodeTo.(ModuleVariableNode).getAWrite() +} + /** * Holds if `result` is either `node`, or the post-update node for `node`. */ @@ -860,11 +884,7 @@ string ppReprType(DataFlowType t) { none() } * taken into account. */ predicate jumpStep(Node nodeFrom, Node nodeTo) { - // Module variable read - nodeFrom.(ModuleVariableNode).getARead() = nodeTo - or - // Module variable write - nodeFrom = nodeTo.(ModuleVariableNode).getAWrite() + runtimeJumpStep(nodeFrom, nodeTo) or // Read of module attribute: exists(AttrRead r, ModuleValue mv | diff --git a/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected b/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected index e288b7fd157..8f6d203f6af 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected @@ -2,6 +2,7 @@ | examples.py:0:0:0:0 | GSSA Variable SOURCE | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | | examples.py:0:0:0:0 | GSSA Variable object | examples.py:6:13:6:18 | ControlFlowNode for object | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:6:7:6:11 | GSSA Variable MyObj | +| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | | examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:25:9:25:13 | ControlFlowNode for MyObj | | examples.py:6:13:6:18 | ControlFlowNode for object | examples.py:11:17:11:22 | ControlFlowNode for object | | examples.py:7:5:7:28 | ControlFlowNode for FunctionExpr | examples.py:7:9:7:16 | SSA variable __init__ | @@ -67,8 +68,10 @@ | examples.py:55:5:55:5 | SSA variable a | examples.py:56:12:56:12 | ControlFlowNode for a | | examples.py:55:9:55:15 | ControlFlowNode for Attribute | examples.py:55:5:55:5 | SSA variable a | | test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | +| test.py:3:1:3:6 | ControlFlowNode for SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | | test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | +| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | | test.py:6:15:6:15 | ControlFlowNode for x | test.py:6:15:6:15 | SSA variable x | | test.py:6:15:6:15 | SSA variable x | test.py:7:12:7:12 | ControlFlowNode for x | | test.py:7:12:7:12 | ControlFlowNode for x | test.py:7:29:7:29 | ControlFlowNode for x | @@ -77,17 +80,20 @@ | test.py:7:58:7:58 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | | test.py:10:1:10:12 | GSSA Variable is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | +| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | | test.py:10:10:10:10 | ControlFlowNode for x | test.py:10:10:10:10 | SSA variable x | | test.py:10:10:10:10 | SSA variable x | test.py:11:18:11:18 | ControlFlowNode for x | | test.py:11:18:11:18 | ControlFlowNode for x | test.py:14:34:14:34 | ControlFlowNode for x | | test.py:11:18:11:18 | [post arg] ControlFlowNode for x | test.py:14:34:14:34 | ControlFlowNode for x | | test.py:17:1:17:14 | ControlFlowNode for FunctionExpr | test.py:17:5:17:10 | GSSA Variable SINK_F | | test.py:17:1:17:14 | GSSA Variable is_source | test.py:18:8:18:16 | ControlFlowNode for is_source | +| test.py:17:5:17:10 | ControlFlowNode for SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | | test.py:17:12:17:12 | ControlFlowNode for x | test.py:17:12:17:12 | SSA variable x | | test.py:17:12:17:12 | SSA variable x | test.py:18:18:18:18 | ControlFlowNode for x | | test.py:18:18:18:18 | ControlFlowNode for x | test.py:19:34:19:34 | ControlFlowNode for x | | test.py:18:18:18:18 | [post arg] ControlFlowNode for x | test.py:19:34:19:34 | ControlFlowNode for x | | test.py:25:1:25:20 | ControlFlowNode for ClassExpr | test.py:25:7:25:11 | GSSA Variable MyObj | +| test.py:25:7:25:11 | ControlFlowNode for MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | | test.py:25:13:25:18 | ControlFlowNode for object | test.py:33:17:33:22 | ControlFlowNode for object | | test.py:26:5:26:28 | ControlFlowNode for FunctionExpr | test.py:26:9:26:16 | SSA variable __init__ | | test.py:26:18:26:21 | ControlFlowNode for self | test.py:26:18:26:21 | SSA variable self | @@ -100,6 +106,7 @@ | test.py:29:22:29:24 | ControlFlowNode for foo | test.py:29:22:29:24 | SSA variable foo | | test.py:29:22:29:24 | SSA variable foo | test.py:30:20:30:22 | ControlFlowNode for foo | | test.py:33:1:33:24 | ControlFlowNode for ClassExpr | test.py:33:7:33:15 | GSSA Variable NestedObj | +| test.py:33:7:33:15 | ControlFlowNode for NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | | test.py:34:5:34:23 | ControlFlowNode for FunctionExpr | test.py:34:9:34:16 | SSA variable __init__ | | test.py:34:5:34:23 | GSSA Variable MyObj | test.py:35:20:35:24 | ControlFlowNode for MyObj | | test.py:34:18:34:21 | ControlFlowNode for self | test.py:34:18:34:21 | SSA variable self | @@ -109,6 +116,7 @@ | test.py:37:16:37:19 | SSA variable self | test.py:38:16:38:19 | ControlFlowNode for self | | test.py:41:1:41:19 | ControlFlowNode for FunctionExpr | test.py:41:5:41:10 | GSSA Variable setFoo | | test.py:41:1:41:19 | GSSA Variable SINK_F | test.py:42:5:42:10 | ControlFlowNode for SINK_F | +| test.py:41:5:41:10 | ControlFlowNode for setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | | test.py:41:12:41:14 | ControlFlowNode for obj | test.py:41:12:41:14 | SSA variable obj | | test.py:41:12:41:14 | SSA variable obj | test.py:42:12:42:14 | ControlFlowNode for obj | | test.py:41:17:41:17 | ControlFlowNode for x | test.py:41:17:41:17 | SSA variable x | @@ -166,6 +174,7 @@ | test.py:86:11:86:27 | ControlFlowNode for MyObj() | test.py:86:5:86:7 | SSA variable obj | | test.py:90:1:90:30 | ControlFlowNode for FunctionExpr | test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | | test.py:90:1:90:30 | GSSA Variable MyObj | test.py:91:11:91:15 | ControlFlowNode for MyObj | +| test.py:90:5:90:26 | ControlFlowNode for fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | | test.py:90:28:90:28 | ControlFlowNode for x | test.py:90:28:90:28 | SSA variable x | | test.py:90:28:90:28 | SSA variable x | test.py:91:17:91:17 | ControlFlowNode for x | | test.py:91:5:91:7 | SSA variable obj | test.py:92:9:92:11 | ControlFlowNode for obj | diff --git a/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected b/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected index 1dde97a8d04..9634fcc303b 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected @@ -42,6 +42,8 @@ | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:25:9:25:13 | ControlFlowNode for MyObj | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:49:7:49:11 | ControlFlowNode for MyObj | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:49:7:49:11 | ControlFlowNode for MyObj | +| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | +| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | | examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | | examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | | examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:25:9:25:13 | ControlFlowNode for MyObj | @@ -534,12 +536,16 @@ | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | test.py:49:5:49:10 | ControlFlowNode for setFoo | | test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | | test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | +| test.py:3:1:3:6 | ControlFlowNode for SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | +| test.py:3:1:3:6 | ControlFlowNode for SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:3:1:3:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:3:1:3:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | | test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | | test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | +| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | +| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | | test.py:6:5:6:13 | GSSA Variable is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | | test.py:6:5:6:13 | GSSA Variable is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | | test.py:6:15:6:15 | ControlFlowNode for x | test.py:6:15:6:15 | SSA variable x | @@ -634,6 +640,8 @@ | test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | | test.py:10:1:10:12 | GSSA Variable is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | | test.py:10:1:10:12 | GSSA Variable is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | +| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | +| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | | test.py:10:5:10:8 | GSSA Variable SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | | test.py:10:5:10:8 | GSSA Variable SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | | test.py:10:10:10:10 | ControlFlowNode for x | test.py:10:10:10:10 | SSA variable x | @@ -684,6 +692,8 @@ | test.py:17:1:17:14 | ControlFlowNode for FunctionExpr | test.py:17:5:17:10 | GSSA Variable SINK_F | | test.py:17:1:17:14 | GSSA Variable is_source | test.py:18:8:18:16 | ControlFlowNode for is_source | | test.py:17:1:17:14 | GSSA Variable is_source | test.py:18:8:18:16 | ControlFlowNode for is_source | +| test.py:17:5:17:10 | ControlFlowNode for SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | +| test.py:17:5:17:10 | ControlFlowNode for SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | | test.py:17:5:17:10 | GSSA Variable SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | | test.py:17:5:17:10 | GSSA Variable SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | | test.py:17:12:17:12 | ControlFlowNode for x | test.py:17:12:17:12 | SSA variable x | @@ -722,6 +732,8 @@ | test.py:19:34:19:34 | [post arg] ControlFlowNode for x | test.py:42:12:42:18 | [post arg] ControlFlowNode for Attribute | | test.py:25:1:25:20 | ControlFlowNode for ClassExpr | test.py:25:7:25:11 | GSSA Variable MyObj | | test.py:25:1:25:20 | ControlFlowNode for ClassExpr | test.py:25:7:25:11 | GSSA Variable MyObj | +| test.py:25:7:25:11 | ControlFlowNode for MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | +| test.py:25:7:25:11 | ControlFlowNode for MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | | test.py:25:7:25:11 | GSSA Variable MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | | test.py:25:7:25:11 | GSSA Variable MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | | test.py:25:13:25:18 | ControlFlowNode for object | test.py:33:17:33:22 | ControlFlowNode for object | @@ -805,6 +817,8 @@ | test.py:30:20:30:22 | ControlFlowNode for foo | test.py:30:9:30:12 | [post store] ControlFlowNode for self [Attribute foo] | | test.py:33:1:33:24 | ControlFlowNode for ClassExpr | test.py:33:7:33:15 | GSSA Variable NestedObj | | test.py:33:1:33:24 | ControlFlowNode for ClassExpr | test.py:33:7:33:15 | GSSA Variable NestedObj | +| test.py:33:7:33:15 | ControlFlowNode for NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | +| test.py:33:7:33:15 | ControlFlowNode for NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | | test.py:33:7:33:15 | GSSA Variable NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | | test.py:33:7:33:15 | GSSA Variable NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | | test.py:34:5:34:23 | ControlFlowNode for FunctionExpr | test.py:34:9:34:16 | SSA variable __init__ | @@ -865,6 +879,8 @@ | test.py:41:1:41:19 | ControlFlowNode for FunctionExpr | test.py:41:5:41:10 | GSSA Variable setFoo | | test.py:41:1:41:19 | GSSA Variable SINK_F | test.py:42:5:42:10 | ControlFlowNode for SINK_F | | test.py:41:1:41:19 | GSSA Variable SINK_F | test.py:42:5:42:10 | ControlFlowNode for SINK_F | +| test.py:41:5:41:10 | ControlFlowNode for setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | +| test.py:41:5:41:10 | ControlFlowNode for setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | | test.py:41:5:41:10 | GSSA Variable setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | | test.py:41:5:41:10 | GSSA Variable setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | | test.py:41:12:41:14 | ControlFlowNode for obj | test.py:41:12:41:14 | SSA variable obj | @@ -1191,6 +1207,8 @@ | test.py:90:1:90:30 | ControlFlowNode for FunctionExpr | test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | | test.py:90:1:90:30 | GSSA Variable MyObj | test.py:91:11:91:15 | ControlFlowNode for MyObj | | test.py:90:1:90:30 | GSSA Variable MyObj | test.py:91:11:91:15 | ControlFlowNode for MyObj | +| test.py:90:5:90:26 | ControlFlowNode for fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | +| test.py:90:5:90:26 | ControlFlowNode for fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | | test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | | test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | | test.py:90:28:90:28 | ControlFlowNode for x | test.py:90:28:90:28 | SSA variable x | diff --git a/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected b/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected index 686c3d33017..bfa46534af0 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected +++ b/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected @@ -13,32 +13,45 @@ | multiphase.py:2:8:2:9 | GSSA Variable os | multiphase.py:4:17:4:18 | ControlFlowNode for os | | multiphase.py:4:17:4:18 | ControlFlowNode for os | multiphase.py:4:33:4:34 | ControlFlowNode for os | | multiphase.py:4:17:4:18 | [post read] ControlFlowNode for os | multiphase.py:4:33:4:34 | ControlFlowNode for os | +| multiphase.py:8:1:8:9 | ControlFlowNode for NONSOURCE | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable NONSOURCE in Module multiphase | | multiphase.py:8:1:8:9 | GSSA Variable NONSOURCE | multiphase.py:34:7:34:15 | ControlFlowNode for NONSOURCE | | multiphase.py:8:13:8:26 | ControlFlowNode for Str | multiphase.py:8:1:8:9 | GSSA Variable NONSOURCE | +| multiphase.py:9:1:9:6 | ControlFlowNode for SOURCE | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module multiphase | | multiphase.py:9:10:9:17 | ControlFlowNode for Str | multiphase.py:9:1:9:6 | GSSA Variable SOURCE | | multiphase.py:12:1:12:17 | ControlFlowNode for FunctionExpr | multiphase.py:12:5:12:13 | GSSA Variable is_source | +| multiphase.py:12:5:12:13 | ControlFlowNode for is_source | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module multiphase | | multiphase.py:16:1:16:12 | ControlFlowNode for FunctionExpr | multiphase.py:16:5:16:8 | GSSA Variable SINK | +| multiphase.py:16:5:16:8 | ControlFlowNode for SINK | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module multiphase | | multiphase.py:23:1:23:14 | ControlFlowNode for FunctionExpr | multiphase.py:23:5:23:10 | GSSA Variable SINK_F | | multiphase.py:29:1:29:14 | ControlFlowNode for FunctionExpr | multiphase.py:29:5:29:11 | GSSA Variable set_foo | +| multiphase.py:29:5:29:11 | ControlFlowNode for set_foo | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable set_foo in Module multiphase | | multiphase.py:29:5:29:11 | GSSA Variable set_foo | multiphase.py:35:1:35:7 | ControlFlowNode for set_foo | +| multiphase.py:34:1:34:3 | ControlFlowNode for foo | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable foo in Module multiphase | | multiphase.py:34:7:34:15 | ControlFlowNode for NONSOURCE | multiphase.py:34:1:34:3 | GSSA Variable foo | | multiphase.py:37:2:37:11 | ControlFlowNode for expects()() | multiphase.py:38:5:38:15 | GSSA Variable test_phases | | test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | | test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | +| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | | test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | +| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | | test.py:17:1:17:14 | ControlFlowNode for FunctionExpr | test.py:17:5:17:10 | GSSA Variable SINK_F | | test.py:23:8:23:11 | ControlFlowNode for ImportExpr | test.py:23:8:23:11 | GSSA Variable base | | test.py:23:8:23:11 | GSSA Variable base | test.py:25:1:25:4 | ControlFlowNode for base | | test.py:27:8:27:9 | ControlFlowNode for ImportExpr | test.py:27:8:27:9 | GSSA Variable m1 | +| test.py:27:8:27:9 | ControlFlowNode for m1 | test.py:0:0:0:0 | ModuleVariableNode for Global Variable m1 in Module test | | test.py:29:1:29:17 | ControlFlowNode for FunctionExpr | test.py:29:5:29:14 | GSSA Variable test_const | | test.py:32:1:32:23 | ControlFlowNode for FunctionExpr | test.py:32:5:32:20 | GSSA Variable test_overwritten | | testOnce.py:2:13:2:26 | ControlFlowNode for Str | testOnce.py:2:1:2:9 | GSSA Variable NONSOURCE | | testOnce.py:3:10:3:17 | ControlFlowNode for Str | testOnce.py:3:1:3:6 | GSSA Variable SOURCE | | testOnce.py:6:1:6:17 | ControlFlowNode for FunctionExpr | testOnce.py:6:5:6:13 | GSSA Variable is_source | +| testOnce.py:6:5:6:13 | ControlFlowNode for is_source | testOnce.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module testOnce | | testOnce.py:10:1:10:12 | ControlFlowNode for FunctionExpr | testOnce.py:10:5:10:8 | GSSA Variable SINK | +| testOnce.py:10:5:10:8 | ControlFlowNode for SINK | testOnce.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module testOnce | | testOnce.py:17:1:17:14 | ControlFlowNode for FunctionExpr | testOnce.py:17:5:17:10 | GSSA Variable SINK_F | +| testOnce.py:17:5:17:10 | ControlFlowNode for SINK_F | testOnce.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module testOnce | | testOnce.py:23:8:23:9 | ControlFlowNode for ImportExpr | testOnce.py:23:8:23:9 | GSSA Variable m1 | +| testOnce.py:23:8:23:9 | ControlFlowNode for m1 | testOnce.py:0:0:0:0 | ModuleVariableNode for Global Variable m1 in Module testOnce | | testOnce.py:25:8:25:11 | ControlFlowNode for ImportExpr | testOnce.py:25:8:25:11 | GSSA Variable base | | testOnce.py:25:8:25:11 | GSSA Variable base | testOnce.py:27:1:27:4 | ControlFlowNode for base | | testOnce.py:29:1:29:17 | ControlFlowNode for FunctionExpr | testOnce.py:29:5:29:14 | GSSA Variable test_const | diff --git a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql index 281881c0de8..f4b587d6d89 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql +++ b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql @@ -5,6 +5,7 @@ import semmle.python.dataflow.new.DataFlow pragma[inline] predicate inCodebase(DataFlow::Node node) { exists(node.getLocation().getFile().getRelativePath()) } +pragma[inline] predicate isTopLevel(DataFlow::Node node) { node.getScope() instanceof Module } predicate inFocus(DataFlow::Node node) { From 6c5596d17ee77ae920076194bf2495e9efe78a37 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 9 Sep 2021 13:45:44 +0200 Subject: [PATCH 027/361] Python: rewrite test --- .../module-initialization/localFlow.expected | 58 ------------------- .../module-initialization/localFlow.ql | 47 ++++++++++----- .../module-initialization/multiphase.py | 35 ++++++----- 3 files changed, 50 insertions(+), 90 deletions(-) diff --git a/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected b/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected index bfa46534af0..e69de29bb2d 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected +++ b/python/ql/test/experimental/dataflow/module-initialization/localFlow.expected @@ -1,58 +0,0 @@ -| base.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | base.py:1:1:1:3 | GSSA Variable foo | -| m1.py:2:7:2:8 | ControlFlowNode for IntegerLiteral | m1.py:2:1:2:3 | GSSA Variable foo | -| m1.py:4:8:4:11 | ControlFlowNode for ImportExpr | m1.py:4:8:4:11 | GSSA Variable base | -| m1.py:4:8:4:11 | GSSA Variable base | m1.py:10:14:10:17 | ControlFlowNode for base | -| m1.py:6:1:6:14 | ControlFlowNode for FunctionExpr | m1.py:6:5:6:10 | GSSA Variable passOn | -| m1.py:6:5:6:10 | GSSA Variable passOn | m1.py:10:7:10:12 | ControlFlowNode for passOn | -| m1.py:10:7:10:22 | ControlFlowNode for passOn() | m1.py:10:1:10:3 | GSSA Variable bar | -| multiphase.py:0:0:0:0 | GSSA Variable __file__ | multiphase.py:4:50:4:57 | ControlFlowNode for __file__ | -| multiphase.py:0:0:0:0 | GSSA Variable expects | multiphase.py:37:2:37:8 | ControlFlowNode for expects | -| multiphase.py:1:8:1:10 | ControlFlowNode for ImportExpr | multiphase.py:1:8:1:10 | GSSA Variable sys | -| multiphase.py:1:8:1:10 | GSSA Variable sys | multiphase.py:4:1:4:3 | ControlFlowNode for sys | -| multiphase.py:2:8:2:9 | ControlFlowNode for ImportExpr | multiphase.py:2:8:2:9 | GSSA Variable os | -| multiphase.py:2:8:2:9 | GSSA Variable os | multiphase.py:4:17:4:18 | ControlFlowNode for os | -| multiphase.py:4:17:4:18 | ControlFlowNode for os | multiphase.py:4:33:4:34 | ControlFlowNode for os | -| multiphase.py:4:17:4:18 | [post read] ControlFlowNode for os | multiphase.py:4:33:4:34 | ControlFlowNode for os | -| multiphase.py:8:1:8:9 | ControlFlowNode for NONSOURCE | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable NONSOURCE in Module multiphase | -| multiphase.py:8:1:8:9 | GSSA Variable NONSOURCE | multiphase.py:34:7:34:15 | ControlFlowNode for NONSOURCE | -| multiphase.py:8:13:8:26 | ControlFlowNode for Str | multiphase.py:8:1:8:9 | GSSA Variable NONSOURCE | -| multiphase.py:9:1:9:6 | ControlFlowNode for SOURCE | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module multiphase | -| multiphase.py:9:10:9:17 | ControlFlowNode for Str | multiphase.py:9:1:9:6 | GSSA Variable SOURCE | -| multiphase.py:12:1:12:17 | ControlFlowNode for FunctionExpr | multiphase.py:12:5:12:13 | GSSA Variable is_source | -| multiphase.py:12:5:12:13 | ControlFlowNode for is_source | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module multiphase | -| multiphase.py:16:1:16:12 | ControlFlowNode for FunctionExpr | multiphase.py:16:5:16:8 | GSSA Variable SINK | -| multiphase.py:16:5:16:8 | ControlFlowNode for SINK | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module multiphase | -| multiphase.py:23:1:23:14 | ControlFlowNode for FunctionExpr | multiphase.py:23:5:23:10 | GSSA Variable SINK_F | -| multiphase.py:29:1:29:14 | ControlFlowNode for FunctionExpr | multiphase.py:29:5:29:11 | GSSA Variable set_foo | -| multiphase.py:29:5:29:11 | ControlFlowNode for set_foo | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable set_foo in Module multiphase | -| multiphase.py:29:5:29:11 | GSSA Variable set_foo | multiphase.py:35:1:35:7 | ControlFlowNode for set_foo | -| multiphase.py:34:1:34:3 | ControlFlowNode for foo | multiphase.py:0:0:0:0 | ModuleVariableNode for Global Variable foo in Module multiphase | -| multiphase.py:34:7:34:15 | ControlFlowNode for NONSOURCE | multiphase.py:34:1:34:3 | GSSA Variable foo | -| multiphase.py:37:2:37:11 | ControlFlowNode for expects()() | multiphase.py:38:5:38:15 | GSSA Variable test_phases | -| test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | -| test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | -| test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | -| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | -| test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | -| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | -| test.py:17:1:17:14 | ControlFlowNode for FunctionExpr | test.py:17:5:17:10 | GSSA Variable SINK_F | -| test.py:23:8:23:11 | ControlFlowNode for ImportExpr | test.py:23:8:23:11 | GSSA Variable base | -| test.py:23:8:23:11 | GSSA Variable base | test.py:25:1:25:4 | ControlFlowNode for base | -| test.py:27:8:27:9 | ControlFlowNode for ImportExpr | test.py:27:8:27:9 | GSSA Variable m1 | -| test.py:27:8:27:9 | ControlFlowNode for m1 | test.py:0:0:0:0 | ModuleVariableNode for Global Variable m1 in Module test | -| test.py:29:1:29:17 | ControlFlowNode for FunctionExpr | test.py:29:5:29:14 | GSSA Variable test_const | -| test.py:32:1:32:23 | ControlFlowNode for FunctionExpr | test.py:32:5:32:20 | GSSA Variable test_overwritten | -| testOnce.py:2:13:2:26 | ControlFlowNode for Str | testOnce.py:2:1:2:9 | GSSA Variable NONSOURCE | -| testOnce.py:3:10:3:17 | ControlFlowNode for Str | testOnce.py:3:1:3:6 | GSSA Variable SOURCE | -| testOnce.py:6:1:6:17 | ControlFlowNode for FunctionExpr | testOnce.py:6:5:6:13 | GSSA Variable is_source | -| testOnce.py:6:5:6:13 | ControlFlowNode for is_source | testOnce.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module testOnce | -| testOnce.py:10:1:10:12 | ControlFlowNode for FunctionExpr | testOnce.py:10:5:10:8 | GSSA Variable SINK | -| testOnce.py:10:5:10:8 | ControlFlowNode for SINK | testOnce.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module testOnce | -| testOnce.py:17:1:17:14 | ControlFlowNode for FunctionExpr | testOnce.py:17:5:17:10 | GSSA Variable SINK_F | -| testOnce.py:17:5:17:10 | ControlFlowNode for SINK_F | testOnce.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module testOnce | -| testOnce.py:23:8:23:9 | ControlFlowNode for ImportExpr | testOnce.py:23:8:23:9 | GSSA Variable m1 | -| testOnce.py:23:8:23:9 | ControlFlowNode for m1 | testOnce.py:0:0:0:0 | ModuleVariableNode for Global Variable m1 in Module testOnce | -| testOnce.py:25:8:25:11 | ControlFlowNode for ImportExpr | testOnce.py:25:8:25:11 | GSSA Variable base | -| testOnce.py:25:8:25:11 | GSSA Variable base | testOnce.py:27:1:27:4 | ControlFlowNode for base | -| testOnce.py:29:1:29:17 | ControlFlowNode for FunctionExpr | testOnce.py:29:5:29:14 | GSSA Variable test_const | -| testOnce.py:32:1:32:25 | ControlFlowNode for FunctionExpr | testOnce.py:32:5:32:22 | GSSA Variable test_unoverwritten | diff --git a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql index f4b587d6d89..4c334607876 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql +++ b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql @@ -1,21 +1,40 @@ // This query should be more focused yet. import python -import semmle.python.dataflow.new.DataFlow +import experimental.dataflow.TestUtil.FlowTest +private import semmle.python.dataflow.new.internal.PrintNode +private import semmle.python.dataflow.new.internal.DataFlowPrivate as DP -pragma[inline] -predicate inCodebase(DataFlow::Node node) { exists(node.getLocation().getFile().getRelativePath()) } +class ImportTimeLocalFlowTest extends InlineExpectationsTest { + ImportTimeLocalFlowTest() { this = "ImportTimeLocalFlowTest" } -pragma[inline] -predicate isTopLevel(DataFlow::Node node) { node.getScope() instanceof Module } + override string getARelevantTag() { result = "importTimeFlow" } -predicate inFocus(DataFlow::Node node) { - isTopLevel(node) and - inCodebase(node) + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(DataFlow::Node nodeFrom, DataFlow::ModuleVariableNode nodeTo | + DP::importTimeLocalFlowStep(nodeFrom, nodeTo) + | + nodeFrom.getLocation().getFile().getBaseName() = "multiphase.py" and + location = nodeFrom.getLocation() and + tag = "importTimeFlow" and + value = "\"" + prettyNode(nodeTo).replaceAll("\"", "'") + "\"" and + element = nodeTo.toString() + ) + } } -from DataFlow::Node nodeFrom, DataFlow::Node nodeTo -where - inFocus(nodeFrom) and - inFocus(nodeTo) and - DataFlow::localFlowStep(nodeFrom, nodeTo) -select nodeFrom, nodeTo +class RuntimeLocalFlowTest extends FlowTest { + RuntimeLocalFlowTest() { this = "RuntimeLocalFlowTest" } + + override string flowTag() { result = "runtimFlow" } + + override predicate relevantFlow(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + nodeFrom.getLocation().getFile().getBaseName() = "multiphase.py" and + // results are displayed next to `nodeTo`, so we need a line to write on + nodeTo.getLocation().getStartLine() > 0 and + ( + nodeFrom instanceof DataFlow::ModuleVariableNode or + nodeTo instanceof DataFlow::ModuleVariableNode + ) and + DP::runtimeJumpStep(nodeFrom, nodeTo) + } +} diff --git a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py index ad41e7e8bfa..afb167d2099 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py +++ b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py @@ -5,39 +5,38 @@ sys.path.append(os.path.dirname(os.path.dirname((__file__)))) from testlib import * # These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" +NONSOURCE = "not a source" #$ importTimeFlow="ModuleVariableNode for Global Variable NONSOURCE in Module multiphase" +SOURCE = "source" #$ importTimeFlow="ModuleVariableNode for Global Variable SOURCE in Module multiphase" -def is_source(x): +def is_source(x): #$ importTimeFlow="ModuleVariableNode for Global Variable is_source in Module multiphase" 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") +def SINK(x): #$ importTimeFlow="ModuleVariableNode for Global Variable SINK in Module multiphase" + if is_source(x): #$ runtimFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-17 -> is_source" + print("OK") #$ runtimFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-18 -> print" else: - print("Unexpected flow", x) + print("Unexpected flow", x) #$ runtimFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-20 -> print" def SINK_F(x): - if is_source(x): - print("Unexpected flow", x) + if is_source(x): #$ runtimFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-24 -> is_source" + print("Unexpected flow", x) #$ runtimFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-25 -> print" else: - print("OK") + print("OK") #$ runtimFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-27 -> print" -def set_foo(): +def set_foo(): #$ importTimeFlow="ModuleVariableNode for Global Variable set_foo in Module multiphase" global foo - print(foo) - foo = SOURCE + foo = SOURCE #$ runtimFlow="ModuleVariableNode for Global Variable SOURCE in Module multiphase, l:-31 -> SOURCE" MISSING:importTimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase" -foo = NONSOURCE +foo = NONSOURCE #$ importTimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase" set_foo() @expects(2) def test_phases(): global foo - SINK(foo) - foo = NONSOURCE - set_foo() - SINK(foo) + SINK(foo) #$ runtimFlow="ModuleVariableNode for Global Variable SINK in Module multiphase, l:-39 -> SINK" runtimFlow="ModuleVariableNode for Global Variable foo in Module multiphase, l:-39 -> foo" + foo = NONSOURCE #$ runtimFlow="ModuleVariableNode for Global Variable NONSOURCE in Module multiphase, l:-40 -> NONSOURCE" + set_foo() #$ runtimFlow="ModuleVariableNode for Global Variable set_foo in Module multiphase, l:-41 -> set_foo" + SINK(foo) #$ runtimFlow="ModuleVariableNode for Global Variable SINK in Module multiphase, l:-42 -> SINK" runtimFlow="ModuleVariableNode for Global Variable foo in Module multiphase, l:-42 -> foo" From 29ad3bf7f814fbcaa054aaa144c53dea9bd362ae Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Sep 2021 18:08:54 +0100 Subject: [PATCH 028/361] C++: Test dataflow and other slightly more complex cases. --- .../tests/CleartextTransmission.expected | 5 +- .../CWE/CWE-311/semmle/tests/test3.cpp | 93 +++++++++++++++++-- 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index 70c9b6bfbfd..0dd4d240c15 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -1,2 +1,3 @@ -| test3.cpp:39:3:39:6 | call to recv | test3.cpp:39:15:39:22 | password | -| test3.cpp:47:3:47:6 | call to recv | test3.cpp:47:15:47:22 | password | +| test3.cpp:41:3:41:6 | call to recv | test3.cpp:41:15:41:22 | password | +| test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password | +| test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index 5eafd2dcb70..99fb6e9e640 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -1,10 +1,12 @@ typedef unsigned long size_t; +#define STDIN_FILENO (0) size_t strlen(const char *s); -void send(int a, const void *buf, size_t bufLen, int d); -void recv(int a, void *buf, size_t bufLen, int d); +void send(int fd, const void *buf, size_t bufLen, int d); +void recv(int fd, void *buf, size_t bufLen, int d); +void read(int fd, void *buf, size_t bufLen); void LogonUserA(int a, int b, const char *password, int d, int e, int f); @@ -13,17 +15,17 @@ int val(); void test_send(const char *password1, const char *password2, const char *password_hash, const char *message) { { - LogonUserA(val(), val(), password1, val(), val(), val()); // proof `password` is plaintext + LogonUserA(val(), val(), password1, val(), val(), val()); // proof `password1` is plaintext - send(val(), password1, strlen(password1), val()); // BAD: `password` is sent plaintext (certainly) [NOT DETECTED] + send(val(), password1, strlen(password1), val()); // BAD: `password1` is sent plaintext (certainly) [NOT DETECTED] } { - send(val(), password2, strlen(password2), val()); // BAD: `password` is sent plaintext (probably) [NOT DETECTED] + send(val(), password2, strlen(password2), val()); // BAD: `password2` is sent plaintext (probably) [NOT DETECTED] } { - send(val(), password_hash, strlen(password_hash), val()); // GOOD: `password` is sent encrypted + send(val(), password_hash, strlen(password_hash), val()); // GOOD: `password_hash` is sent encrypted } { @@ -59,3 +61,82 @@ void test_receive() recv(val(), message, 256, val()); // GOOD: `message` is not a password } } + +void test_dataflow(const char *password1) +{ + { + const char *ptr = password1; + + send(val(), ptr, strlen(ptr), val()); // BAD: `password` is sent plaintext [NOT DETECTED] + } + + { + char password[256]; + char *ptr = password; + + recv(val(), ptr, 256, val()); // BAD: `password` is received plaintext + } + + { + char buffer[256]; + + recv(val(), buffer, 256, val()); // BAD: `password` is received plaintext [NOT DETECTED] + + char *password = buffer; + } +} + +void test_read() +{ + { + char password[256]; + int fd = val(); + + read(fd, password, 256); // BAD: `password` is received plaintext [NOT DETECTED] + } + + { + char password[256]; + int fd = STDIN_FILENO; + + read(fd, password, 256); // GOOD: `password` is received from stdin, not a network socket + } +} + +void my_recv(char *buffer, size_t bufferSize) +{ + recv(val(), buffer, bufferSize, val()); +} + +const char *id(const char *buffer) +{ + return buffer; +} + +char *global_password; + +char *get_global_str() +{ + return global_password; +} + +void test_interprocedural(const char *password1) +{ + { + char password[256]; + + my_recv(password, 256); // BAD: `password` is received plaintext [NOT DETECTED] + } + + { + const char *ptr = id(password1); + + send(val(), ptr, strlen(ptr), val()); // BAD: `password1` is sent plaintext [NOT DETECTED] + } + + { + char *data = get_global_str(); + + send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext [NOT DETECTED] + } +} From 1707d67adb4934636cdd3abc7a5d88b9715c6360 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Sep 2021 17:39:10 +0100 Subject: [PATCH 029/361] C++: Support 'send' as well. --- .../CWE/CWE-311/CleartextTransmission.ql | 39 ++++++++++++++----- .../tests/CleartextTransmission.expected | 3 ++ .../CWE/CWE-311/semmle/tests/test3.cpp | 6 +-- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 25a173e4362..5e1796b1874 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -17,17 +17,36 @@ import semmle.code.cpp.security.FileWrite import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering -// TODO: network send? - /** - * TODO + * A function call that sends or receives data over a network. */ -class NetworkRecv extends FunctionCall { - NetworkRecv() { this.getTarget().hasGlobalName("recv") } - - Expr getData() { result = this.getArgument(1) } +abstract class NetworkSendRecv extends FunctionCall { + /** + * Gets the expression for the buffer to be sent from / received into. + */ + abstract Expr getDataExpr(); } -from NetworkRecv recv, SensitiveExpr e -where DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(recv.(NetworkRecv).getData())) -select recv, e +/** + * A function call that sends data over a network. + * + * note: functions such as `read` may be reading from a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it probably isn't very important which query reports a result as long as its reported exactly once. + */ +class NetworkSend extends NetworkSendRecv { + NetworkSend() { this.getTarget().hasGlobalName("send") } + + override Expr getDataExpr() { result = this.getArgument(1) } +} + +/** + * A function call that receives data over a network. + */ +class NetworkRecv extends NetworkSendRecv { + NetworkRecv() { this.getTarget().hasGlobalName("recv") } + + override Expr getDataExpr() { result = this.getArgument(1) } +} + +from NetworkSendRecv transmission, SensitiveExpr e +where DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(transmission.getDataExpr())) +select transmission, e diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index 0dd4d240c15..c68fabc02dc 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -1,3 +1,6 @@ +| test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 | +| test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 | | test3.cpp:41:3:41:6 | call to recv | test3.cpp:41:15:41:22 | password | | test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password | +| test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 | | test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index 99fb6e9e640..68f863b9048 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -17,11 +17,11 @@ void test_send(const char *password1, const char *password2, const char *passwor { LogonUserA(val(), val(), password1, val(), val(), val()); // proof `password1` is plaintext - send(val(), password1, strlen(password1), val()); // BAD: `password1` is sent plaintext (certainly) [NOT DETECTED] + send(val(), password1, strlen(password1), val()); // BAD: `password1` is sent plaintext (certainly) } { - send(val(), password2, strlen(password2), val()); // BAD: `password2` is sent plaintext (probably) [NOT DETECTED] + send(val(), password2, strlen(password2), val()); // BAD: `password2` is sent plaintext (probably) } { @@ -67,7 +67,7 @@ void test_dataflow(const char *password1) { const char *ptr = password1; - send(val(), ptr, strlen(ptr), val()); // BAD: `password` is sent plaintext [NOT DETECTED] + send(val(), ptr, strlen(ptr), val()); // BAD: `password` is sent plaintext } { From 3ba9e806357a0ce0e59817a0c208807d1f024e95 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 7 Sep 2021 13:09:01 +0100 Subject: [PATCH 030/361] C++: Support various functions / variants. --- .../Security/CWE/CWE-311/CleartextTransmission.ql | 12 ++++++++++-- .../semmle/tests/CleartextTransmission.expected | 2 ++ .../Security/CWE/CWE-311/semmle/tests/test3.cpp | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 5e1796b1874..b9a87f2dd32 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -33,7 +33,10 @@ abstract class NetworkSendRecv extends FunctionCall { * note: functions such as `read` may be reading from a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it probably isn't very important which query reports a result as long as its reported exactly once. */ class NetworkSend extends NetworkSendRecv { - NetworkSend() { this.getTarget().hasGlobalName("send") } + NetworkSend() { + this.getTarget() + .hasGlobalName(["send", "sendto", "sendmsg", "write", "writev", "pwritev", "pwritev2"]) + } override Expr getDataExpr() { result = this.getArgument(1) } } @@ -42,7 +45,12 @@ class NetworkSend extends NetworkSendRecv { * A function call that receives data over a network. */ class NetworkRecv extends NetworkSendRecv { - NetworkRecv() { this.getTarget().hasGlobalName("recv") } + NetworkRecv() { + this.getTarget() + .hasGlobalName([ + "recv", "recvfrom", "recvmsg", "read", "pread", "readv", "preadv", "preadv2" + ]) + } override Expr getDataExpr() { result = this.getArgument(1) } } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index c68fabc02dc..7cea9ccb588 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -4,3 +4,5 @@ | test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password | | test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 | | test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password | +| test3.cpp:95:3:95:6 | call to read | test3.cpp:95:12:95:19 | password | +| test3.cpp:102:3:102:6 | call to read | test3.cpp:102:12:102:19 | password | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index 68f863b9048..e291e46cbcf 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -92,14 +92,14 @@ void test_read() char password[256]; int fd = val(); - read(fd, password, 256); // BAD: `password` is received plaintext [NOT DETECTED] + read(fd, password, 256); // BAD: `password` is received plaintext } { char password[256]; int fd = STDIN_FILENO; - read(fd, password, 256); // GOOD: `password` is received from stdin, not a network socket + read(fd, password, 256); // GOOD: `password` is received from stdin, not a network socket [FALSE POSITIVE] } } From e696eaaa2f2fa91d75a1e65a62ae2b3e6b97271b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 7 Sep 2021 13:49:22 +0100 Subject: [PATCH 031/361] C++: Fix false positives involving STDIN_FILENO. --- .../CWE/CWE-311/CleartextTransmission.ql | 16 +++++++++++++++- .../semmle/tests/CleartextTransmission.expected | 1 - .../Security/CWE/CWE-311/semmle/tests/test3.cpp | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index b9a87f2dd32..2a53ae68024 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -21,6 +21,12 @@ import semmle.code.cpp.valuenumbering.GlobalValueNumbering * A function call that sends or receives data over a network. */ abstract class NetworkSendRecv extends FunctionCall { + /** + * Gets the expression for the socket or similar object used for sending or + * receiving data. + */ + abstract Expr getSocketExpr(); + /** * Gets the expression for the buffer to be sent from / received into. */ @@ -38,6 +44,8 @@ class NetworkSend extends NetworkSendRecv { .hasGlobalName(["send", "sendto", "sendmsg", "write", "writev", "pwritev", "pwritev2"]) } + override Expr getSocketExpr() { result = this.getArgument(0) } + override Expr getDataExpr() { result = this.getArgument(1) } } @@ -52,9 +60,15 @@ class NetworkRecv extends NetworkSendRecv { ]) } + override Expr getSocketExpr() { result = this.getArgument(0) } + override Expr getDataExpr() { result = this.getArgument(1) } } from NetworkSendRecv transmission, SensitiveExpr e -where DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(transmission.getDataExpr())) +where + DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(transmission.getDataExpr())) and + not exists(Zero zero | + DataFlow::localFlow(DataFlow::exprNode(zero), DataFlow::exprNode(transmission.getSocketExpr())) + ) select transmission, e diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index 7cea9ccb588..55c09e5820b 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -5,4 +5,3 @@ | test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 | | test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password | | test3.cpp:95:3:95:6 | call to read | test3.cpp:95:12:95:19 | password | -| test3.cpp:102:3:102:6 | call to read | test3.cpp:102:12:102:19 | password | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index e291e46cbcf..02ccc90396b 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -99,7 +99,7 @@ void test_read() char password[256]; int fd = STDIN_FILENO; - read(fd, password, 256); // GOOD: `password` is received from stdin, not a network socket [FALSE POSITIVE] + read(fd, password, 256); // GOOD: `password` is received from stdin, not a network socket } } From f58177f292a3b83215a94aa1ccf4dfb29ad8a15d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 8 Sep 2021 13:32:33 +0100 Subject: [PATCH 032/361] C++: Full dataflow version. --- .../CWE/CWE-311/CleartextTransmission.ql | 35 ++++++++++++++----- .../tests/CleartextTransmission.expected | 17 +++++---- .../CWE/CWE-311/semmle/tests/test3.cpp | 6 ++-- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 2a53ae68024..9923fbe7c87 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -5,7 +5,7 @@ * @kind problem * @problem.severity warning * @security-severity 7.5 TODO - * @precision high + * @precision high TODO * @id cpp/cleartext-transmission * @tags security * external/cwe/cwe-319 @@ -13,9 +13,7 @@ import cpp import semmle.code.cpp.security.SensitiveExprs -import semmle.code.cpp.security.FileWrite import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.valuenumbering.GlobalValueNumbering /** * A function call that sends or receives data over a network. @@ -65,10 +63,31 @@ class NetworkRecv extends NetworkSendRecv { override Expr getDataExpr() { result = this.getArgument(1) } } -from NetworkSendRecv transmission, SensitiveExpr e +/** + * Taint flow from a sensitive expression to a network operation with data + * tainted by that expression. + */ +class SensitiveSendRecvConfiguration extends DataFlow::Configuration { + SensitiveSendRecvConfiguration() { this = "SensitiveSendRecvConfiguration" } + + override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr } + + override predicate isSink(DataFlow::Node sink) { + exists(NetworkSendRecv transmission | + sink.asExpr() = transmission.getDataExpr() and + not exists(Zero zero | + DataFlow::localFlow(DataFlow::exprNode(zero), + DataFlow::exprNode(transmission.getSocketExpr())) + ) + ) + } +} + +from SensitiveSendRecvConfiguration config1, Expr source, Expr sink where - DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(transmission.getDataExpr())) and - not exists(Zero zero | - DataFlow::localFlow(DataFlow::exprNode(zero), DataFlow::exprNode(transmission.getSocketExpr())) + exists(DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode | + config1.hasFlowPath(sourceNode, sinkNode) and + source = sourceNode.getNode().asExpr() and + sink = sinkNode.getNode().asExpr() ) -select transmission, e +select sink, source diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index 55c09e5820b..9f3e9900a0b 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -1,7 +1,10 @@ -| test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 | -| test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 | -| test3.cpp:41:3:41:6 | call to recv | test3.cpp:41:15:41:22 | password | -| test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password | -| test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 | -| test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password | -| test3.cpp:95:3:95:6 | call to read | test3.cpp:95:12:95:19 | password | +| test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 | +| test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 | +| test3.cpp:41:15:41:22 | password | test3.cpp:41:15:41:22 | password | +| test3.cpp:49:15:49:22 | password | test3.cpp:49:15:49:22 | password | +| test3.cpp:70:15:70:17 | ptr | test3.cpp:68:21:68:29 | password1 | +| test3.cpp:77:15:77:17 | ptr | test3.cpp:75:15:75:22 | password | +| test3.cpp:95:12:95:19 | password | test3.cpp:95:12:95:19 | password | +| test3.cpp:108:14:108:19 | buffer | test3.cpp:128:11:128:18 | password | +| test3.cpp:134:15:134:17 | ptr | test3.cpp:132:24:132:32 | password1 | +| test3.cpp:140:15:140:18 | data | test3.cpp:120:9:120:23 | global_password | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index 02ccc90396b..b949667af0c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -125,18 +125,18 @@ void test_interprocedural(const char *password1) { char password[256]; - my_recv(password, 256); // BAD: `password` is received plaintext [NOT DETECTED] + my_recv(password, 256); // BAD: `password` is received plaintext [detected on line 108] } { const char *ptr = id(password1); - send(val(), ptr, strlen(ptr), val()); // BAD: `password1` is sent plaintext [NOT DETECTED] + send(val(), ptr, strlen(ptr), val()); // BAD: `password1` is sent plaintext } { char *data = get_global_str(); - send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext [NOT DETECTED] + send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext } } From ee7ccd79368a5cbd8bd7cb5d49baac185a0182cf Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 13 Sep 2021 11:11:32 +0100 Subject: [PATCH 033/361] C++: Upgrade to path problem. --- .../CWE/CWE-311/CleartextTransmission.ql | 25 +++++++--- .../tests/CleartextTransmission.expected | 49 +++++++++++++++---- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 9923fbe7c87..6fd6910211e 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -2,7 +2,7 @@ * @name Cleartext transmission of sensitive information * @description Transmitting sensitive information across a network in * cleartext can expose it to an attacker. - * @kind problem + * @kind path-problem * @problem.severity warning * @security-severity 7.5 TODO * @precision high TODO @@ -14,6 +14,7 @@ import cpp import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.dataflow.DataFlow +import DataFlow::PathGraph /** * A function call that sends or receives data over a network. @@ -83,11 +84,19 @@ class SensitiveSendRecvConfiguration extends DataFlow::Configuration { } } -from SensitiveSendRecvConfiguration config1, Expr source, Expr sink +from + SensitiveSendRecvConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink, + NetworkSendRecv transmission, string msg where - exists(DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode | - config1.hasFlowPath(sourceNode, sinkNode) and - source = sourceNode.getNode().asExpr() and - sink = sinkNode.getNode().asExpr() - ) -select sink, source + config.hasFlowPath(source, sink) and + sink.getNode().asExpr() = transmission.getDataExpr() and + if transmission instanceof NetworkSend + then + msg = + "This operation transmits '" + sink.toString() + + "', which may contain unencrypted sensitive data from $@" + else + msg = + "This operation receives into '" + sink.toString() + + "', which may put unencrypted sensitive data into $@" +select transmission, source, sink, msg, source, source.getNode().asExpr().toString() diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index 9f3e9900a0b..bf997ee45a2 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -1,10 +1,39 @@ -| test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 | -| test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 | -| test3.cpp:41:15:41:22 | password | test3.cpp:41:15:41:22 | password | -| test3.cpp:49:15:49:22 | password | test3.cpp:49:15:49:22 | password | -| test3.cpp:70:15:70:17 | ptr | test3.cpp:68:21:68:29 | password1 | -| test3.cpp:77:15:77:17 | ptr | test3.cpp:75:15:75:22 | password | -| test3.cpp:95:12:95:19 | password | test3.cpp:95:12:95:19 | password | -| test3.cpp:108:14:108:19 | buffer | test3.cpp:128:11:128:18 | password | -| test3.cpp:134:15:134:17 | ptr | test3.cpp:132:24:132:32 | password1 | -| test3.cpp:140:15:140:18 | data | test3.cpp:120:9:120:23 | global_password | +edges +| test3.cpp:68:21:68:29 | password1 | test3.cpp:70:15:70:17 | ptr | +| test3.cpp:75:15:75:22 | password | test3.cpp:77:15:77:17 | ptr | +| test3.cpp:106:20:106:25 | buffer | test3.cpp:108:14:108:19 | buffer | +| test3.cpp:120:9:120:23 | global_password | test3.cpp:138:16:138:29 | call to get_global_str | +| test3.cpp:128:11:128:18 | password | test3.cpp:106:20:106:25 | buffer | +| test3.cpp:132:21:132:22 | call to id | test3.cpp:134:15:134:17 | ptr | +| test3.cpp:132:24:132:32 | password1 | test3.cpp:132:21:132:22 | call to id | +| test3.cpp:138:16:138:29 | call to get_global_str | test3.cpp:140:15:140:18 | data | +nodes +| test3.cpp:20:15:20:23 | password1 | semmle.label | password1 | +| test3.cpp:24:15:24:23 | password2 | semmle.label | password2 | +| test3.cpp:41:15:41:22 | password | semmle.label | password | +| test3.cpp:49:15:49:22 | password | semmle.label | password | +| test3.cpp:68:21:68:29 | password1 | semmle.label | password1 | +| test3.cpp:70:15:70:17 | ptr | semmle.label | ptr | +| test3.cpp:75:15:75:22 | password | semmle.label | password | +| test3.cpp:77:15:77:17 | ptr | semmle.label | ptr | +| test3.cpp:95:12:95:19 | password | semmle.label | password | +| test3.cpp:106:20:106:25 | buffer | semmle.label | buffer | +| test3.cpp:108:14:108:19 | buffer | semmle.label | buffer | +| test3.cpp:120:9:120:23 | global_password | semmle.label | global_password | +| test3.cpp:128:11:128:18 | password | semmle.label | password | +| test3.cpp:132:21:132:22 | call to id | semmle.label | call to id | +| test3.cpp:132:24:132:32 | password1 | semmle.label | password1 | +| test3.cpp:134:15:134:17 | ptr | semmle.label | ptr | +| test3.cpp:138:16:138:29 | call to get_global_str | semmle.label | call to get_global_str | +| test3.cpp:140:15:140:18 | data | semmle.label | data | +#select +| test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@ | test3.cpp:20:15:20:23 | password1 | password1 | +| test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@ | test3.cpp:24:15:24:23 | password2 | password2 | +| test3.cpp:41:3:41:6 | call to recv | test3.cpp:41:15:41:22 | password | test3.cpp:41:15:41:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:41:15:41:22 | password | password | +| test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password | test3.cpp:49:15:49:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:49:15:49:22 | password | password | +| test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 | test3.cpp:70:15:70:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:68:21:68:29 | password1 | password1 | +| test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password | test3.cpp:77:15:77:17 | ptr | This operation receives into 'ptr', which may put unencrypted sensitive data into $@ | test3.cpp:75:15:75:22 | password | password | +| test3.cpp:95:3:95:6 | call to read | test3.cpp:95:12:95:19 | password | test3.cpp:95:12:95:19 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:95:12:95:19 | password | password | +| test3.cpp:108:2:108:5 | call to recv | test3.cpp:128:11:128:18 | password | test3.cpp:108:14:108:19 | buffer | This operation receives into 'buffer', which may put unencrypted sensitive data into $@ | test3.cpp:128:11:128:18 | password | password | +| test3.cpp:134:3:134:6 | call to send | test3.cpp:132:24:132:32 | password1 | test3.cpp:134:15:134:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:132:24:132:32 | password1 | password1 | +| test3.cpp:140:3:140:6 | call to send | test3.cpp:120:9:120:23 | global_password | test3.cpp:140:15:140:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:120:9:120:23 | global_password | global_password | From 0e8064dbf9e6fa328fa9112a669ce92951c065bd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 13 Sep 2021 14:53:13 +0100 Subject: [PATCH 034/361] C++: Add a test demonstrating taint. --- .../Security/CWE/CWE-311/semmle/tests/test3.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index b949667af0c..1e35220f854 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -140,3 +140,16 @@ void test_interprocedural(const char *password1) send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext } } + +char *strncpy(char *s1, const char *s2, size_t n); + +void test_taint(const char *password) +{ + { + char buffer[16]; + + strncpy(buffer, password, 16); + buffer[15] = 0; + send(val(), buffer, 16, val()); // BAD: `password` is (partially) sent plaintext [NOT DETECTED] + } +} From 67c6b35845b116c7baf54ed7dd399cbcc13a30d1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 13 Sep 2021 14:44:30 +0100 Subject: [PATCH 035/361] C++: We get many more real world results using taint tracking. --- cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql | 4 ++-- .../CWE/CWE-311/semmle/tests/CleartextTransmission.expected | 4 ++++ .../query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 6fd6910211e..123c7437990 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -13,7 +13,7 @@ import cpp import semmle.code.cpp.security.SensitiveExprs -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking import DataFlow::PathGraph /** @@ -68,7 +68,7 @@ class NetworkRecv extends NetworkSendRecv { * Taint flow from a sensitive expression to a network operation with data * tainted by that expression. */ -class SensitiveSendRecvConfiguration extends DataFlow::Configuration { +class SensitiveSendRecvConfiguration extends TaintTracking::Configuration { SensitiveSendRecvConfiguration() { this = "SensitiveSendRecvConfiguration" } override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index bf997ee45a2..ae2333ba8c9 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -7,6 +7,7 @@ edges | test3.cpp:132:21:132:22 | call to id | test3.cpp:134:15:134:17 | ptr | | test3.cpp:132:24:132:32 | password1 | test3.cpp:132:21:132:22 | call to id | | test3.cpp:138:16:138:29 | call to get_global_str | test3.cpp:140:15:140:18 | data | +| test3.cpp:151:19:151:26 | password | test3.cpp:153:15:153:20 | buffer | nodes | test3.cpp:20:15:20:23 | password1 | semmle.label | password1 | | test3.cpp:24:15:24:23 | password2 | semmle.label | password2 | @@ -26,6 +27,8 @@ nodes | test3.cpp:134:15:134:17 | ptr | semmle.label | ptr | | test3.cpp:138:16:138:29 | call to get_global_str | semmle.label | call to get_global_str | | test3.cpp:140:15:140:18 | data | semmle.label | data | +| test3.cpp:151:19:151:26 | password | semmle.label | password | +| test3.cpp:153:15:153:20 | buffer | semmle.label | buffer | #select | test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@ | test3.cpp:20:15:20:23 | password1 | password1 | | test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@ | test3.cpp:24:15:24:23 | password2 | password2 | @@ -37,3 +40,4 @@ nodes | test3.cpp:108:2:108:5 | call to recv | test3.cpp:128:11:128:18 | password | test3.cpp:108:14:108:19 | buffer | This operation receives into 'buffer', which may put unencrypted sensitive data into $@ | test3.cpp:128:11:128:18 | password | password | | test3.cpp:134:3:134:6 | call to send | test3.cpp:132:24:132:32 | password1 | test3.cpp:134:15:134:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:132:24:132:32 | password1 | password1 | | test3.cpp:140:3:140:6 | call to send | test3.cpp:120:9:120:23 | global_password | test3.cpp:140:15:140:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:120:9:120:23 | global_password | global_password | +| test3.cpp:153:3:153:6 | call to send | test3.cpp:151:19:151:26 | password | test3.cpp:153:15:153:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:151:19:151:26 | password | password | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index 1e35220f854..010ed2c8062 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -150,6 +150,6 @@ void test_taint(const char *password) strncpy(buffer, password, 16); buffer[15] = 0; - send(val(), buffer, 16, val()); // BAD: `password` is (partially) sent plaintext [NOT DETECTED] + send(val(), buffer, 16, val()); // BAD: `password` is (partially) sent plaintext } } From 8f152a5bfb2cc624db4644f608144eb09ff87ce8 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 13 Sep 2021 16:50:00 +0200 Subject: [PATCH 036/361] Python: Port regex concepts and adapt PolyRedos --- python/ql/lib/semmle/python/Concepts.qll | 46 ++++++ .../lib/semmle/python/frameworks/Stdlib.qll | 152 ++++++++++++++++++ .../PolynomialReDoSCustomizations.qll | 136 +--------------- 3 files changed, 199 insertions(+), 135 deletions(-) diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index 5517347e692..95bf56d11df 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -355,6 +355,41 @@ module SqlExecution { } } +/** + * A data-flow node that executes a regular expression. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `RegexExecution::Range` instead. + */ +class RegexExecution extends DataFlow::Node { + RegexExecution::Range range; + + RegexExecution() { this = range } + + /** Gets the data flow node for the regex being compiled by this node. */ + DataFlow::Node getRegexNode() { result = range.getRegexNode() } + + /** Gets a dataflow node for the string to be searched or matched against. */ + DataFlow::Node getString() { result = range.getString() } +} + +/** Provides classes for modeling new regular-expression execution APIs. */ +module RegexExecution { + /** + * A data-flow node that executes a regular expression. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `RegexExecution` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets the data flow node for the regex being compiled by this node. */ + abstract DataFlow::Node getRegexNode(); + + /** Gets a dataflow node for the string to be searched or matched against. */ + abstract DataFlow::Node getString(); + } +} + /** * A data-flow node that escapes meta-characters, which could be used to prevent * injection attacks. @@ -411,6 +446,9 @@ module Escaping { /** Gets the escape-kind for escaping a string so it can safely be included in HTML. */ string getHtmlKind() { result = "html" } + + /** Gets the escape-kind for escaping a string so it can safely be included in HTML. */ + string getRegexKind() { result = "regex" } // TODO: If adding an XML kind, update the modeling of the `MarkupSafe` PyPI package. // // Technically it claims to escape for both HTML and XML, but for now we don't have @@ -427,6 +465,14 @@ class HtmlEscaping extends Escaping { HtmlEscaping() { range.getKind() = Escaping::getHtmlKind() } } +/** + * An escape of a string so it can be safely included in + * the body of a regex. + */ +class RegexEscaping extends Escaping { + RegexEscaping() { range.getKind() = Escaping::getRegexKind() } +} + /** Provides classes for modeling HTTP-related APIs. */ module HTTP { import semmle.python.web.HttpConstants diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 539f0dcabb0..d85e2408453 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1497,6 +1497,158 @@ private module StdlibPrivate { } } +// --------------------------------------------------------------------------- +// re +// --------------------------------------------------------------------------- +/** + * List of methods in the `re` module immediately executing a regular expression. + * + * See https://docs.python.org/3/library/re.html#module-contents + */ +private class RegexExecutionMethod extends string { + RegexExecutionMethod() { + this in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"] + } +} + +/** Gets the index of the argument representing the string to be searched by a regex. */ +int stringArg(RegexExecutionMethod method) { + method in ["match", "fullmatch", "search", "split", "findall", "finditer"] and + result = 1 + or + method in ["sub", "subn"] and + result = 2 +} + +/** + * A a call to a method from the `re` module immediately executing a regular expression. + * + * See `RegexExecutionMethods` + */ +private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range { + RegexExecutionMethod method; + + DirectRegex() { this = API::moduleImport("re").getMember(method).getACall() } + + override DataFlow::Node getRegexNode() { + result in [this.getArg(0), this.getArgByName("pattern")] + } + + override DataFlow::Node getString() { + result in [this.getArg(stringArg(method)), this.getArgByName("string")] + } +} + +/** Helper module for tracking compiled regexes. */ +private module CompiledRegexes { + private import semmle.python.dataflow.new.DataFlow2 + private import semmle.python.RegexTreeView + + // TODO: This module should be refactored once API graphs are more expressinve. + /** A configuration for finding uses of compiled regexes. */ + class RegexDefinitionConfiguration extends DataFlow2::Configuration { + RegexDefinitionConfiguration() { this = "RegexDefinitionConfiguration" } + + override predicate isSource(DataFlow::Node source) { source instanceof RegexDefinitonSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof RegexDefinitionSink } + } + + /** A regex compilation. */ + class RegexDefinitonSource extends DataFlow::CallCfgNode { + DataFlow::Node regexNode; + + RegexDefinitonSource() { + this = API::moduleImport("re").getMember("compile").getACall() and + regexNode in [this.getArg(0), this.getArgByName("pattern")] + } + + /** Gets the data flow node for the regex being compiled by this node. */ + DataFlow::Node getRegexNode() { result = regexNode } + } + + /** A use of a compiled regex. */ + class RegexDefinitionSink extends DataFlow::Node { + RegexExecutionMethod method; + DataFlow::CallCfgNode executingCall; + + RegexDefinitionSink() { + executingCall = + API::moduleImport("re").getMember("compile").getReturn().getMember(method).getACall() and + this = executingCall.getFunction().(DataFlow::AttrRead).getObject() + } + + /** Gets the method used to execute the regex. */ + RegexExecutionMethod getMethod() { result = method } + + /** Gets the data flow node for the executing call. */ + DataFlow::CallCfgNode getExecutingCall() { result = executingCall } + } +} + +private import CompiledRegexes + +/** + * A call on compiled regular expression (obtained via `re.compile`) executing a + * regular expression. + * + * Given the following example: + * + * ```py + * pattern = re.compile(input) + * pattern.match(s) + * ``` + * + * This class will identify that `re.compile` compiles `input` and afterwards + * executes `re`'s `match`. As a result, `this` will refer to `pattern.match(s)` + * and `this.getRegexNode()` will return the node for `input` (`re.compile`'s first argument). + * + * + * See `RegexExecutionMethods` + * + * See https://docs.python.org/3/library/re.html#regular-expression-objects + */ +private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution { + DataFlow::Node regexNode; + RegexExecutionMethod method; + + CompiledRegex() { + exists( + RegexDefinitionConfiguration conf, RegexDefinitonSource source, RegexDefinitionSink sink + | + conf.hasFlow(source, sink) and + regexNode = source.getRegexNode() and + method = sink.getMethod() and + this = sink.getExecutingCall() + ) + } + + override DataFlow::Node getRegexNode() { result = regexNode } + + override DataFlow::Node getString() { + result in [this.getArg(stringArg(method) - 1), this.getArgByName("string")] + } +} + +/** + * A call to 're.escape'. + * See https://docs.python.org/3/library/re.html#re.escape + */ +private class ReEscapeCall extends Escaping::Range, DataFlow::CallCfgNode { + DataFlow::Node regexNode; + + ReEscapeCall() { + this = API::moduleImport("re").getMember("escape").getACall() and + regexNode in [this.getArg(0), this.getArgByName("pattern")] + } + + override DataFlow::Node getAnInput() { result = regexNode } + + override DataFlow::Node getOutput() { result = this } + + override string getKind() { result = Escaping::getRegexKind() } +} + // --------------------------------------------------------------------------- // OTHER // --------------------------------------------------------------------------- diff --git a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll index cbaf3b982e9..33d88c5d0ed 100644 --- a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll @@ -60,7 +60,7 @@ module PolynomialReDoS { RegExpTerm t; RegexExecutionAsSink() { - exists(CompiledRegexes::RegexExecution re | + exists(RegexExecution re | re.getRegexNode().asExpr() = t.getRegex() and this = re.getString() ) and @@ -76,137 +76,3 @@ module PolynomialReDoS { */ class StringConstCompareAsSanitizerGuard extends SanitizerGuard, StringConstCompare { } } - -/** Helper module for tracking compiled regexes. */ -private module CompiledRegexes { - // TODO: This module should be refactored and merged with the experimental work done on detecting - // regex injections, such that this can be expressed from just using a concept. - /** A configuration for finding uses of compiled regexes. */ - class RegexDefinitionConfiguration extends DataFlow2::Configuration { - RegexDefinitionConfiguration() { this = "RegexDefinitionConfiguration" } - - override predicate isSource(DataFlow::Node source) { source instanceof RegexDefinitonSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof RegexDefinitionSink } - } - - /** A regex compilation. */ - class RegexDefinitonSource extends DataFlow::CallCfgNode { - DataFlow::Node regexNode; - - RegexDefinitonSource() { - this = API::moduleImport("re").getMember("compile").getACall() and - regexNode in [this.getArg(0), this.getArgByName("pattern")] - } - - /** Gets the regex that is being compiled by this node. */ - RegExpTerm getRegExp() { result.getRegex() = regexNode.asExpr() and result.isRootTerm() } - - /** Gets the data flow node for the regex being compiled by this node. */ - DataFlow::Node getRegexNode() { result = regexNode } - } - - /** A use of a compiled regex. */ - class RegexDefinitionSink extends DataFlow::Node { - RegexExecutionMethod method; - DataFlow::CallCfgNode executingCall; - - RegexDefinitionSink() { - exists(DataFlow::AttrRead reMethod | - executingCall.getFunction() = reMethod and - reMethod.getAttributeName() = method and - this = reMethod.getObject() - ) - } - - /** Gets the method used to execute the regex. */ - RegexExecutionMethod getMethod() { result = method } - - /** Gets the data flow node for the executing call. */ - DataFlow::CallCfgNode getExecutingCall() { result = executingCall } - } - - /** A data flow node executing a regex. */ - abstract class RegexExecution extends DataFlow::Node { - /** Gets the data flow node for the regex being compiled by this node. */ - abstract DataFlow::Node getRegexNode(); - - /** Gets a dataflow node for the string to be searched or matched against. */ - abstract DataFlow::Node getString(); - } - - private class RegexExecutionMethod extends string { - RegexExecutionMethod() { - this in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"] - } - } - - /** Gets the index of the argument representing the string to be searched by a regex. */ - int stringArg(RegexExecutionMethod method) { - method in ["match", "fullmatch", "search", "split", "findall", "finditer"] and - result = 1 - or - method in ["sub", "subn"] and - result = 2 - } - - /** - * A class to find `re` methods immediately executing an expression. - * - * See `RegexExecutionMethods` - */ - class DirectRegex extends DataFlow::CallCfgNode, RegexExecution { - RegexExecutionMethod method; - - DirectRegex() { this = API::moduleImport("re").getMember(method).getACall() } - - override DataFlow::Node getRegexNode() { - result in [this.getArg(0), this.getArgByName("pattern")] - } - - override DataFlow::Node getString() { - result in [this.getArg(stringArg(method)), this.getArgByName("string")] - } - } - - /** - * A class to find `re` methods immediately executing a compiled expression by `re.compile`. - * - * Given the following example: - * - * ```py - * pattern = re.compile(input) - * pattern.match(s) - * ``` - * - * This class will identify that `re.compile` compiles `input` and afterwards - * executes `re`'s `match`. As a result, `this` will refer to `pattern.match(s)` - * and `this.getRegexNode()` will return the node for `input` (`re.compile`'s first argument) - * - * - * See `RegexExecutionMethods` - * - * See https://docs.python.org/3/library/re.html#regular-expression-objects - */ - private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution { - DataFlow::Node regexNode; - RegexExecutionMethod method; - - CompiledRegex() { - exists( - RegexDefinitionConfiguration conf, RegexDefinitonSource source, RegexDefinitionSink sink - | - conf.hasFlow(source, sink) and - regexNode = source.getRegexNode() and - method = sink.getMethod() and - this = sink.getExecutingCall() - ) - } - - override DataFlow::Node getRegexNode() { result = regexNode } - - override DataFlow::Node getString() { - result in [this.getArg(stringArg(method) - 1), this.getArgByName("string")] - } - } -} From a30f697537ad96945d75581a3d0fee3fcc9e5fdc Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 14 Sep 2021 11:53:40 +0200 Subject: [PATCH 037/361] Python: Add `getName` to `RegexExecution` concept --- python/ql/lib/semmle/python/Concepts.qll | 12 ++++++++++++ python/ql/lib/semmle/python/frameworks/Stdlib.qll | 13 +++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index 95bf56d11df..66caaa3c877 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -371,6 +371,12 @@ class RegexExecution extends DataFlow::Node { /** Gets a dataflow node for the string to be searched or matched against. */ DataFlow::Node getString() { result = range.getString() } + + /** + * Gets the name of this regex execution, typically the name of an executing method. + * This is used for nice alert messages and should include the module if possible. + */ + string getName() { result = range.getName() } } /** Provides classes for modeling new regular-expression execution APIs. */ @@ -387,6 +393,12 @@ module RegexExecution { /** Gets a dataflow node for the string to be searched or matched against. */ abstract DataFlow::Node getString(); + + /** + * Gets the name of this regex execution, typically the name of an executing method. + * This is used for nice alert messages and should include the module if possible. + */ + abstract string getName(); } } diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index d85e2408453..76c2f144e09 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1537,16 +1537,19 @@ private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range { override DataFlow::Node getString() { result in [this.getArg(stringArg(method)), this.getArgByName("string")] } + + override string getName() { result = "re." + method } } /** Helper module for tracking compiled regexes. */ private module CompiledRegexes { - private import semmle.python.dataflow.new.DataFlow2 + private import semmle.python.dataflow.new.DataFlow4 private import semmle.python.RegexTreeView - // TODO: This module should be refactored once API graphs are more expressinve. + // TODO: This module should be refactored once API graphs are more expressive. + // For now it uses data flow, so we pick the verion with least change of collision (4) . /** A configuration for finding uses of compiled regexes. */ - class RegexDefinitionConfiguration extends DataFlow2::Configuration { + class RegexDefinitionConfiguration extends DataFlow4::Configuration { RegexDefinitionConfiguration() { this = "RegexDefinitionConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof RegexDefinitonSource } @@ -1608,7 +1611,7 @@ private import CompiledRegexes * * See https://docs.python.org/3/library/re.html#regular-expression-objects */ -private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution { +private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range { DataFlow::Node regexNode; RegexExecutionMethod method; @@ -1628,6 +1631,8 @@ private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution { override DataFlow::Node getString() { result in [this.getArg(stringArg(method) - 1), this.getArgByName("string")] } + + override string getName() { result = "re." + method } } /** From 3d5192d6d3048fc2e25ef444820fe9eae36207c8 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 14 Sep 2021 11:54:11 +0200 Subject: [PATCH 038/361] Python: Fix typos --- .../python/security/dataflow/ReflectedXSSCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll index 0e5410a8be2..93363d3409a 100644 --- a/python/ql/lib/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll @@ -59,7 +59,7 @@ module ReflectedXSS { class HtmlEscapingAsSanitizer extends Sanitizer { HtmlEscapingAsSanitizer() { // TODO: For now, since there is not an `isSanitizingStep` member-predicate part of a - // `TaintTracking::Configuration`, we use treat the output is a taint-sanitizer. This + // `TaintTracking::Configuration`, we treat the output as a taint-sanitizer. This // is slightly imprecise, which you can see in the `m_unsafe + SAFE` test-case in // python/ql/test/library-tests/frameworks/markupsafe/taint_test.py // From 6c82daef3d48c57fdc06ae9f1cea0563e9db3109 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 14 Sep 2021 11:54:59 +0200 Subject: [PATCH 039/361] Python: Move Regexinjection out of experimental and fix up structure --- .../security/injection/RegexInjection.qll | 37 +++++++++++++ .../RegexInjectionCustomizations.qll | 55 +++++++++++++++++++ .../src/Security/CWE-730/RegexInjection.qhelp | 45 +++++++++++++++ .../ql/src/Security/CWE-730/RegexInjection.ql | 28 ++++++++++ python/ql/src/Security/CWE-730/re_bad.py | 15 +++++ python/ql/src/Security/CWE-730/re_good.py | 17 ++++++ 6 files changed, 197 insertions(+) create mode 100644 python/ql/lib/semmle/python/security/injection/RegexInjection.qll create mode 100644 python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll create mode 100644 python/ql/src/Security/CWE-730/RegexInjection.qhelp create mode 100644 python/ql/src/Security/CWE-730/RegexInjection.ql create mode 100644 python/ql/src/Security/CWE-730/re_bad.py create mode 100644 python/ql/src/Security/CWE-730/re_good.py diff --git a/python/ql/lib/semmle/python/security/injection/RegexInjection.qll b/python/ql/lib/semmle/python/security/injection/RegexInjection.qll new file mode 100644 index 00000000000..80601bd638f --- /dev/null +++ b/python/ql/lib/semmle/python/security/injection/RegexInjection.qll @@ -0,0 +1,37 @@ +/** + * Provides a taint-tracking configuration for detecting regular expression injection + * vulnerabilities. + * + * Note, for performance reasons: only import this file if + * `RegexInjection::Configuration` is needed, otherwise + * `RegexInjectionCustomizations` should be imported instead. + */ + +private import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking + +/** + * Provides a taint-tracking configuration for detecting regular expression injection + * vulnerabilities. + */ +module RegexInjection { + import RegexInjectionCustomizations::RegexInjection + + /** + * A taint-tracking configuration for detecting "reflected server-side cross-site scripting" vulnerabilities. + */ + class Configuration extends TaintTracking::Configuration { + Configuration() { this = "RegexInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } + + override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { + guard instanceof SanitizerGuard + } + } +} diff --git a/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll new file mode 100644 index 00000000000..824ec4e7151 --- /dev/null +++ b/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll @@ -0,0 +1,55 @@ +/** + * Provides default sources, sinks and sanitizers for detecting + * "regular expression injection" + * vulnerabilities, as well as extension points for adding your own. + */ + +private import python +private import semmle.python.Concepts +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.dataflow.new.RemoteFlowSources + +/** + * Provides default sources, sinks and sanitizers for detecting + * "regular expression injection" + * vulnerabilities, as well as extension points for adding your own. + */ +module RegexInjection { + /** + * A data flow source for "regular expression injection" vulnerabilities. + */ + abstract class Source extends DataFlow::Node { } + + /** + * A sink for "regular expression injection" vulnerabilities is the execution of a regular expression. + * If you have a custom way to execute regular expressions, you can extend `RegexExecution::Range`. + */ + class Sink extends RegexExecution { } + + /** + * A sanitizer for "regular expression injection" vulnerabilities. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** + * A sanitizer guard for "regular expression injection" vulnerabilities. + */ + abstract class SanitizerGuard extends DataFlow::BarrierGuard { } + + /** + * A source of remote user input, considered as a flow source. + */ + class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { } + + /** + * A regex escaping, considered as a sanitizer. + */ + class RegexEscapingAsSanitizer extends Sanitizer { + RegexEscapingAsSanitizer() { + // Due to use-use flow, we want the output rather than an input + // (so the input can still flow to other sinks). + this = any(RegexEscaping esc).getOutput() + } + } +} diff --git a/python/ql/src/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/Security/CWE-730/RegexInjection.qhelp new file mode 100644 index 00000000000..f19f0744469 --- /dev/null +++ b/python/ql/src/Security/CWE-730/RegexInjection.qhelp @@ -0,0 +1,45 @@ + + + +

    +Constructing a regular expression with unsanitized user input is dangerous as a malicious user may +be able to modify the meaning of the expression. In particular, such a user may be able to provide +a regular expression fragment that takes exponential time in the worst case, and use that to +perform a Denial of Service attack. +

    + + + +

    +Before embedding user input into a regular expression, use a sanitization function such as +re.escape to escape meta-characters that have a special meaning regarding +regular expressions' syntax. +

    +
    + + +

    +The following examples are based on a simple Flask web server environment. +

    +

    +The following example shows a HTTP request parameter that is used to construct a regular expression +without sanitizing it first: +

    + +

    +Instead, the request parameter should be sanitized first, for example using the function +re.escape. This ensures that the user cannot insert characters which have a +special meaning in regular expressions. +

    + +
    + + +
  • OWASP: Regular expression Denial of Service - ReDoS.
  • +
  • Wikipedia: ReDoS.
  • +
  • Python docs: re.
  • +
  • SonarSource: RSPEC-2631.
  • +
    + diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql new file mode 100644 index 00000000000..363740fe121 --- /dev/null +++ b/python/ql/src/Security/CWE-730/RegexInjection.ql @@ -0,0 +1,28 @@ +/** + * @name Regular expression injection + * @description User input should not be used in regular expressions without first being escaped, + * otherwise a malicious user may be able to inject an expression that could require + * exponential time on certain inputs. + * @kind path-problem + * @problem.severity error + * @id py/regex-injection + * @tags security + * external/cwe/cwe-730 + * external/cwe/cwe-400 + */ + +// determine precision above +import python +import semmle.python.security.injection.RegexInjection +import DataFlow::PathGraph + +from + RegexInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, + RegexInjection::Sink regexInjectionSink +where + config.hasFlowPath(source, sink) and + regexInjectionSink = sink.getNode() +select sink.getNode(), source, sink, + "$@ regular expression is constructed from a $@ and executed by $@.", + regexInjectionSink.getRegexNode(), "This", source.getNode(), "user-provided value", + regexInjectionSink, regexInjectionSink.getName() diff --git a/python/ql/src/Security/CWE-730/re_bad.py b/python/ql/src/Security/CWE-730/re_bad.py new file mode 100644 index 00000000000..3befaba9a01 --- /dev/null +++ b/python/ql/src/Security/CWE-730/re_bad.py @@ -0,0 +1,15 @@ +from flask import request, Flask +import re + + +@app.route("/direct") +def direct(): + unsafe_pattern = request.args["pattern"] + re.search(unsafe_pattern, "") + + +@app.route("/compile") +def compile(): + unsafe_pattern = request.args["pattern"] + compiled_pattern = re.compile(unsafe_pattern) + compiled_pattern.search("") diff --git a/python/ql/src/Security/CWE-730/re_good.py b/python/ql/src/Security/CWE-730/re_good.py new file mode 100644 index 00000000000..cdc9a7ac158 --- /dev/null +++ b/python/ql/src/Security/CWE-730/re_good.py @@ -0,0 +1,17 @@ +from flask import request, Flask +import re + + +@app.route("/direct") +def direct(): + unsafe_pattern = request.args['pattern'] + safe_pattern = re.escape(unsafe_pattern) + re.search(safe_pattern, "") + + +@app.route("/compile") +def compile(): + unsafe_pattern = request.args['pattern'] + safe_pattern = re.escape(unsafe_pattern) + compiled_pattern = re.compile(safe_pattern) + compiled_pattern.search("") From abbd1d1dc568d7ed52b0172344466b07d7440df3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 14 Sep 2021 13:08:21 +0200 Subject: [PATCH 040/361] Python: Fix errors introduced during port testing on a database helps.. --- .../injection/RegexInjectionCustomizations.qll | 9 ++++++++- python/ql/src/Security/CWE-730/RegexInjection.ql | 10 +++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll index 824ec4e7151..a44b4c5c19e 100644 --- a/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll @@ -25,7 +25,14 @@ module RegexInjection { * A sink for "regular expression injection" vulnerabilities is the execution of a regular expression. * If you have a custom way to execute regular expressions, you can extend `RegexExecution::Range`. */ - class Sink extends RegexExecution { } + class Sink extends DataFlow::Node { + RegexExecution regexExecution; + + Sink() { this = regexExecution.getRegexNode() } + + /** Gets the call that executes the regular expression marked by this sink. */ + RegexExecution getRegexExecution() { result = regexExecution } + } /** * A sanitizer for "regular expression injection" vulnerabilities. diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql index 363740fe121..8e0f530973f 100644 --- a/python/ql/src/Security/CWE-730/RegexInjection.ql +++ b/python/ql/src/Security/CWE-730/RegexInjection.ql @@ -13,16 +13,16 @@ // determine precision above import python +private import semmle.python.Concepts import semmle.python.security.injection.RegexInjection import DataFlow::PathGraph from RegexInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, - RegexInjection::Sink regexInjectionSink + RegexExecution regexExecution where config.hasFlowPath(source, sink) and - regexInjectionSink = sink.getNode() + regexExecution = sink.getNode().(RegexInjection::Sink).getRegexExecution() select sink.getNode(), source, sink, - "$@ regular expression is constructed from a $@ and executed by $@.", - regexInjectionSink.getRegexNode(), "This", source.getNode(), "user-provided value", - regexInjectionSink, regexInjectionSink.getName() + "$@ regular expression is constructed from a $@ and executed by $@.", sink.getNode(), "This", + source.getNode(), "user-provided value", regexExecution, regexExecution.getName() From 36e27f2aa445899d15e62dfa65b0899809b9b51d Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 14 Sep 2021 13:14:16 +0200 Subject: [PATCH 041/361] Python: Remove promoted code: - queries (`py/regex-injection`) - concepts (RegexExecution, RegexEscape) - library models (Stdlib::Re) --- .../Security/CWE-730/RegexInjection.qhelp | 45 ---------- .../Security/CWE-730/RegexInjection.ql | 29 ------ .../experimental/Security/CWE-730/re_bad.py | 15 ---- .../experimental/Security/CWE-730/re_good.py | 17 ---- .../experimental/semmle/python/Concepts.qll | 67 -------------- .../semmle/python/frameworks/Stdlib.qll | 88 ------------------- .../security/injection/RegexInjection.qll | 53 ----------- 7 files changed, 314 deletions(-) delete mode 100644 python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp delete mode 100644 python/ql/src/experimental/Security/CWE-730/RegexInjection.ql delete mode 100644 python/ql/src/experimental/Security/CWE-730/re_bad.py delete mode 100644 python/ql/src/experimental/Security/CWE-730/re_good.py delete mode 100644 python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp deleted file mode 100644 index f19f0744469..00000000000 --- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp +++ /dev/null @@ -1,45 +0,0 @@ - - - -

    -Constructing a regular expression with unsanitized user input is dangerous as a malicious user may -be able to modify the meaning of the expression. In particular, such a user may be able to provide -a regular expression fragment that takes exponential time in the worst case, and use that to -perform a Denial of Service attack. -

    -
    - - -

    -Before embedding user input into a regular expression, use a sanitization function such as -re.escape to escape meta-characters that have a special meaning regarding -regular expressions' syntax. -

    -
    - - -

    -The following examples are based on a simple Flask web server environment. -

    -

    -The following example shows a HTTP request parameter that is used to construct a regular expression -without sanitizing it first: -

    - -

    -Instead, the request parameter should be sanitized first, for example using the function -re.escape. This ensures that the user cannot insert characters which have a -special meaning in regular expressions. -

    - -
    - - -
  • OWASP: Regular expression Denial of Service - ReDoS.
  • -
  • Wikipedia: ReDoS.
  • -
  • Python docs: re.
  • -
  • SonarSource: RSPEC-2631.
  • -
    -
    diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql deleted file mode 100644 index 7725f636eb0..00000000000 --- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @name Regular expression injection - * @description User input should not be used in regular expressions without first being escaped, - * otherwise a malicious user may be able to inject an expression that could require - * exponential time on certain inputs. - * @kind path-problem - * @problem.severity error - * @id py/regex-injection - * @tags security - * external/cwe/cwe-730 - * external/cwe/cwe-400 - */ - -// determine precision above -import python -import experimental.semmle.python.security.injection.RegexInjection -import DataFlow::PathGraph - -from - RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink, - RegexInjectionSink regexInjectionSink, Attribute methodAttribute -where - config.hasFlowPath(source, sink) and - regexInjectionSink = sink.getNode() and - methodAttribute = regexInjectionSink.getRegexMethod() -select sink.getNode(), source, sink, - "$@ regular expression is constructed from a $@ and executed by $@.", sink.getNode(), "This", - source.getNode(), "user-provided value", methodAttribute, - regexInjectionSink.getRegexModule() + "." + methodAttribute.getName() diff --git a/python/ql/src/experimental/Security/CWE-730/re_bad.py b/python/ql/src/experimental/Security/CWE-730/re_bad.py deleted file mode 100644 index 3befaba9a01..00000000000 --- a/python/ql/src/experimental/Security/CWE-730/re_bad.py +++ /dev/null @@ -1,15 +0,0 @@ -from flask import request, Flask -import re - - -@app.route("/direct") -def direct(): - unsafe_pattern = request.args["pattern"] - re.search(unsafe_pattern, "") - - -@app.route("/compile") -def compile(): - unsafe_pattern = request.args["pattern"] - compiled_pattern = re.compile(unsafe_pattern) - compiled_pattern.search("") diff --git a/python/ql/src/experimental/Security/CWE-730/re_good.py b/python/ql/src/experimental/Security/CWE-730/re_good.py deleted file mode 100644 index cdc9a7ac158..00000000000 --- a/python/ql/src/experimental/Security/CWE-730/re_good.py +++ /dev/null @@ -1,17 +0,0 @@ -from flask import request, Flask -import re - - -@app.route("/direct") -def direct(): - unsafe_pattern = request.args['pattern'] - safe_pattern = re.escape(unsafe_pattern) - re.search(safe_pattern, "") - - -@app.route("/compile") -def compile(): - unsafe_pattern = request.args['pattern'] - safe_pattern = re.escape(unsafe_pattern) - compiled_pattern = re.compile(safe_pattern) - compiled_pattern.search("") diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index f87caa88497..cff74235f24 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -14,73 +14,6 @@ private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.TaintTracking private import experimental.semmle.python.Frameworks -/** Provides classes for modeling Regular Expression-related APIs. */ -module RegexExecution { - /** - * A data-flow node that executes a regular expression. - * - * Extend this class to model new APIs. If you want to refine existing API models, - * extend `RegexExecution` instead. - */ - abstract class Range extends DataFlow::Node { - /** - * Gets the argument containing the executed expression. - */ - abstract DataFlow::Node getRegexNode(); - - /** - * Gets the library used to execute the regular expression. - */ - abstract string getRegexModule(); - } -} - -/** - * A data-flow node that executes a regular expression. - * - * Extend this class to refine existing API models. If you want to model new APIs, - * extend `RegexExecution::Range` instead. - */ -class RegexExecution extends DataFlow::Node { - RegexExecution::Range range; - - RegexExecution() { this = range } - - DataFlow::Node getRegexNode() { result = range.getRegexNode() } - - string getRegexModule() { result = range.getRegexModule() } -} - -/** Provides classes for modeling Regular Expression escape-related APIs. */ -module RegexEscape { - /** - * A data-flow node that escapes a regular expression. - * - * Extend this class to model new APIs. If you want to refine existing API models, - * extend `RegexEscape` instead. - */ - abstract class Range extends DataFlow::Node { - /** - * Gets the argument containing the escaped expression. - */ - abstract DataFlow::Node getRegexNode(); - } -} - -/** - * A data-flow node that escapes a regular expression. - * - * Extend this class to refine existing API models. If you want to model new APIs, - * extend `RegexEscape::Range` instead. - */ -class RegexEscape extends DataFlow::Node { - RegexEscape::Range range; - - RegexEscape() { this = range } - - DataFlow::Node getRegexNode() { result = range.getRegexNode() } -} - /** Provides classes for modeling LDAP query execution-related APIs. */ module LDAPQuery { /** diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index b3b70f43394..420caf0d73b 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -9,91 +9,3 @@ private import semmle.python.dataflow.new.TaintTracking private import semmle.python.dataflow.new.RemoteFlowSources private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs - -/** - * Provides models for Python's `re` library. - * - * See https://docs.python.org/3/library/re.html - */ -private module Re { - /** - * List of `re` methods immediately executing an expression. - * - * See https://docs.python.org/3/library/re.html#module-contents - */ - private class RegexExecutionMethods extends string { - RegexExecutionMethods() { - this in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"] - } - } - - /** - * A class to find `re` methods immediately executing an expression. - * - * See `RegexExecutionMethods` - */ - private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range { - DataFlow::Node regexNode; - - DirectRegex() { - this = API::moduleImport("re").getMember(any(RegexExecutionMethods m)).getACall() and - regexNode = this.getArg(0) - } - - override DataFlow::Node getRegexNode() { result = regexNode } - - override string getRegexModule() { result = "re" } - } - - /** - * A class to find `re` methods immediately executing a compiled expression by `re.compile`. - * - * Given the following example: - * - * ```py - * pattern = re.compile(input) - * pattern.match(s) - * ``` - * - * This class will identify that `re.compile` compiles `input` and afterwards - * executes `re`'s `match`. As a result, `this` will refer to `pattern.match(s)` - * and `this.getRegexNode()` will return the node for `input` (`re.compile`'s first argument) - * - * - * See `RegexExecutionMethods` - * - * See https://docs.python.org/3/library/re.html#regular-expression-objects - */ - private class CompiledRegex extends DataFlow::MethodCallNode, RegexExecution::Range { - DataFlow::Node regexNode; - - CompiledRegex() { - exists(DataFlow::MethodCallNode patternCall | - patternCall = API::moduleImport("re").getMember("compile").getACall() and - patternCall.flowsTo(this.getObject()) and - this.getMethodName() instanceof RegexExecutionMethods and - regexNode = patternCall.getArg(0) - ) - } - - override DataFlow::Node getRegexNode() { result = regexNode } - - override string getRegexModule() { result = "re" } - } - - /** - * A class to find `re` methods escaping an expression. - * - * See https://docs.python.org/3/library/re.html#re.escape - */ - class ReEscape extends DataFlow::CallCfgNode, RegexEscape::Range { - DataFlow::Node regexNode; - - ReEscape() { - this = API::moduleImport("re").getMember("escape").getACall() and - regexNode = this.getArg(0) - } - - override DataFlow::Node getRegexNode() { result = regexNode } - } -} diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll deleted file mode 100644 index 7b7b08cacab..00000000000 --- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Provides a taint-tracking configuration for detecting regular expression injection - * vulnerabilities. - */ - -import python -import experimental.semmle.python.Concepts -import semmle.python.dataflow.new.DataFlow -import semmle.python.dataflow.new.TaintTracking -import semmle.python.dataflow.new.RemoteFlowSources - -/** - * A class to find methods executing regular expressions. - * - * See `RegexExecution` - */ -class RegexInjectionSink extends DataFlow::Node { - string regexModule; - Attribute regexMethod; - - RegexInjectionSink() { - exists(RegexExecution reExec | - this = reExec.getRegexNode() and - regexModule = reExec.getRegexModule() and - regexMethod = reExec.(DataFlow::CallCfgNode).getFunction().asExpr().(Attribute) - ) - } - - /** - * Gets the argument containing the executed expression. - */ - string getRegexModule() { result = regexModule } - - /** - * Gets the method used to execute the regular expression. - */ - Attribute getRegexMethod() { result = regexMethod } -} - -/** - * A taint-tracking configuration for detecting regular expression injections. - */ -class RegexInjectionFlowConfig extends TaintTracking::Configuration { - RegexInjectionFlowConfig() { this = "RegexInjectionFlowConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof RegexInjectionSink } - - override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer = any(RegexEscape reEscape).getRegexNode() - } -} From 1c7982b3199f769b19a4085ee4e0efa5442ff28f Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 14 Sep 2021 13:29:21 +0200 Subject: [PATCH 042/361] Python: Move query tests over --- .../query-tests/Security/CWE-730/RegexInjection.qlref | 1 - .../CWE-730-RegexInjection}/RegexInjection.expected | 6 +++--- .../Security/CWE-730-RegexInjection/RegexInjection.qlref | 1 + .../Security/CWE-730-RegexInjection}/re_bad.py | 0 .../Security/CWE-730-RegexInjection}/re_good.py | 0 5 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.qlref rename python/ql/test/{experimental/query-tests/Security/CWE-730 => query-tests/Security/CWE-730-RegexInjection}/RegexInjection.expected (93%) create mode 100644 python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.qlref rename python/ql/test/{experimental/query-tests/Security/CWE-730 => query-tests/Security/CWE-730-RegexInjection}/re_bad.py (100%) rename python/ql/test/{experimental/query-tests/Security/CWE-730 => query-tests/Security/CWE-730-RegexInjection}/re_good.py (100%) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.qlref deleted file mode 100644 index c0c506c4707..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE-730/RegexInjection.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected similarity index 93% rename from python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected rename to python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected index 07a01b5f9dc..598b60ae38a 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected @@ -23,6 +23,6 @@ nodes | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern | subpaths #select -| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This | re_bad.py:13:22:13:28 | ControlFlowNode for request | user-provided value | re_bad.py:14:5:14:13 | Attribute | re.search | -| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This | re_bad.py:24:22:24:28 | ControlFlowNode for request | user-provided value | re_bad.py:26:5:26:27 | Attribute | re.search | -| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This | re_bad.py:36:22:36:28 | ControlFlowNode for request | user-provided value | re_bad.py:37:5:37:37 | Attribute | re.search | +| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This | re_bad.py:13:22:13:28 | ControlFlowNode for request | user-provided value | re_bad.py:14:5:14:33 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This | re_bad.py:24:22:24:28 | ControlFlowNode for request | user-provided value | re_bad.py:26:5:26:31 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This | re_bad.py:36:22:36:28 | ControlFlowNode for request | user-provided value | re_bad.py:37:5:37:41 | ControlFlowNode for Attribute() | re.search | diff --git a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.qlref b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.qlref new file mode 100644 index 00000000000..53f8be2a625 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.qlref @@ -0,0 +1 @@ +Security/CWE-730/RegexInjection.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-730/re_bad.py b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/re_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-730/re_bad.py rename to python/ql/test/query-tests/Security/CWE-730-RegexInjection/re_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-730/re_good.py b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/re_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-730/re_good.py rename to python/ql/test/query-tests/Security/CWE-730-RegexInjection/re_good.py From c2d203772628a86c23e516aff02e6000eab8fa2a Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 14 Sep 2021 13:45:51 +0200 Subject: [PATCH 043/361] Python: Add change note and set precision --- python/change-notes/2021-09-14-promote-regex-injection.md | 2 ++ python/ql/src/Security/CWE-730/RegexInjection.ql | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 python/change-notes/2021-09-14-promote-regex-injection.md diff --git a/python/change-notes/2021-09-14-promote-regex-injection.md b/python/change-notes/2021-09-14-promote-regex-injection.md new file mode 100644 index 00000000000..5443f2f03ad --- /dev/null +++ b/python/change-notes/2021-09-14-promote-regex-injection.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The externally contributed query `py/regex-injection` has been promoted out of the experimental area. Results from this query are now available by default. diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql index 8e0f530973f..0dfb5b00d52 100644 --- a/python/ql/src/Security/CWE-730/RegexInjection.ql +++ b/python/ql/src/Security/CWE-730/RegexInjection.ql @@ -5,13 +5,13 @@ * exponential time on certain inputs. * @kind path-problem * @problem.severity error + * @precision high * @id py/regex-injection * @tags security * external/cwe/cwe-730 * external/cwe/cwe-400 */ -// determine precision above import python private import semmle.python.Concepts import semmle.python.security.injection.RegexInjection From 9e63aa9d8430c214c5c8bb6f7080c291be18a814 Mon Sep 17 00:00:00 2001 From: haby0 Date: Tue, 14 Sep 2021 21:12:49 +0800 Subject: [PATCH 044/361] Update query --- .../CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql | 9 +++++++++ .../CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll | 8 ++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql index 7866fbd681c..1c96a10d531 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql @@ -13,6 +13,7 @@ import python import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking +import semmle.python.ApiGraphs import ClientSuppliedIpUsedInSecurityCheckLib import DataFlow::PathGraph @@ -30,6 +31,14 @@ class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configura sink instanceof ClientSuppliedIpUsedInSecurityCheckSink } + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(DataFlow::CallCfgNode ccn | + ccn = API::moduleImport("netaddr").getMember("IPAddress").getACall() and + ccn.getArg(0) = pred and + ccn = succ + ) + } + override predicate isSanitizer(DataFlow::Node node) { exists(Subscript ss | not ss.getIndex().(IntegerLiteral).getText() = "0" and diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll index 8113fd17c9d..b003a188b1a 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll @@ -123,14 +123,10 @@ private class CompareSink extends ClientSuppliedIpUsedInSecurityCheckSink { ( compare.getLeft() = this.asExpr() or - compare.getComparator(0) = this.asExpr() + compare.getComparator(0) = this.asExpr() and + not compare.getLeft().(StrConst).getText() in ["%", ","] ) ) - or - exists(Call call | - call.getFunc().(Attribute).getName() = "add" and - call.getArg(0) = this.asExpr() - ) } } From c60eded2de54ceb614feccb64be8db23d5065cce Mon Sep 17 00:00:00 2001 From: haby0 Date: Wed, 15 Sep 2021 11:07:43 +0800 Subject: [PATCH 045/361] Fix conflicting --- .../Security/CWE-117/LogInjection.qhelp | 49 ++++++++++ .../Security/CWE-117/LogInjection.ql | 20 ++++ .../Security/CWE-117/LogInjectionBad.py | 44 +++++++++ .../Security/CWE-117/LogInjectionGood.py | 25 +++++ .../experimental/semmle/python/Concepts.qll | 30 ++++++ .../experimental/semmle/python/Frameworks.qll | 2 +- .../semmle/python/frameworks/Log.qll | 92 +++++++++++++++++++ .../security/injection/LogInjection.qll | 24 +++++ .../Security/CWE-117/LogInjection.expected | 27 ++++++ .../Security/CWE-117/LogInjection.qlref | 1 + .../Security/CWE-117/LogInjectionBad.py | 44 +++++++++ .../Security/CWE-117/LogInjectionGood.py | 25 +++++ 12 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 python/ql/src/experimental/Security/CWE-117/LogInjection.qhelp create mode 100644 python/ql/src/experimental/Security/CWE-117/LogInjection.ql create mode 100644 python/ql/src/experimental/Security/CWE-117/LogInjectionBad.py create mode 100644 python/ql/src/experimental/Security/CWE-117/LogInjectionGood.py create mode 100644 python/ql/src/experimental/semmle/python/frameworks/Log.qll create mode 100644 python/ql/src/experimental/semmle/python/security/injection/LogInjection.qll create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.qlref create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-117/LogInjectionBad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-117/LogInjectionGood.py diff --git a/python/ql/src/experimental/Security/CWE-117/LogInjection.qhelp b/python/ql/src/experimental/Security/CWE-117/LogInjection.qhelp new file mode 100644 index 00000000000..e5305220997 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-117/LogInjection.qhelp @@ -0,0 +1,49 @@ + + + + + + +

    If unsanitized user input is written to a log entry, a malicious user may be able to forge new log entries.

    + +

    Forgery can occur if a user provides some input creating the appearance of multiple + log entries. This can include unescaped new-line characters, or HTML or other markup.

    +
    + + +

    +User input should be suitably sanitized before it is logged. +

    +

    +If the log entries are plain text then line breaks should be removed from user input, using for example +replace(old, new) or similar. Care should also be taken that user input is clearly marked +in log entries, and that a malicious user cannot cause confusion in other ways. +

    +

    +For log entries that will be displayed in HTML, user input should be HTML encoded before being logged, to prevent forgery and +other forms of HTML injection. +

    +
    + + +

    +In the example, the name provided by the user is recorded using the log output function (logging.info or app.logger.info, etc.). +In these four cases, the name provided by the user is not provided The processing is recorded. If a malicious user provides Guest%0D%0AUser name: Admin +as a parameter, the log entry will be divided into two lines, the first line is User name: Guest code>, the second line is User name: Admin. +

    + + +

    +In a good example, the program uses the replace function to provide parameter processing to the user, and replace \r\n and \n +with empty characters. To a certain extent, the occurrence of log injection vulnerabilities is reduced. +

    + + +
    + + +
  • OWASP: Log Injection.
  • +
    +
    diff --git a/python/ql/src/experimental/Security/CWE-117/LogInjection.ql b/python/ql/src/experimental/Security/CWE-117/LogInjection.ql new file mode 100644 index 00000000000..452ef944825 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-117/LogInjection.ql @@ -0,0 +1,20 @@ +/** + * @name Log Injection + * @description Building log entries from user-controlled data is vulnerable to + * insertion of forged log entries by a malicious user. + * @kind path-problem + * @problem.severity error + * @precision high + * @id py/log-injection + * @tags security + * external/cwe/cwe-117 + */ + +import python +import experimental.semmle.python.security.injection.LogInjection +import DataFlow::PathGraph + +from LogInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "$@ flows to log entry.", source.getNode(), + "User-provided value" diff --git a/python/ql/src/experimental/Security/CWE-117/LogInjectionBad.py b/python/ql/src/experimental/Security/CWE-117/LogInjectionBad.py new file mode 100644 index 00000000000..0c0cbe1a8fe --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-117/LogInjectionBad.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :Log Injection +""" +from flask import Flask +from flask import request +from django.utils.log import request_logger +import logging + +logging.basicConfig(level=logging.DEBUG) + +app = Flask(__name__) + +@app.route('/bad1') +def bad1(): + name = request.args.get('name') + app.logger.info('User name: ' + name) # Bad + return 'bad1' + +@app.route('/bad2') +def bad2(): + name = request.args.get('name') + logging.info('User name: ' + name) # Bad + return 'bad2' + +@app.route('/bad3') +def bad3(): + name = request.args.get('name') + request_logger.warn('User name: ' + name) # Bad + return 'bad3' + +@app.route('/bad4') +def bad4(): + name = request.args.get('name') + logtest = logging.getLogger('test') + logtest.debug('User name: ' + name) # Bad + return 'bad4' + +if __name__ == '__main__': + app.debug = True + handler = logging.FileHandler('log') + app.logger.addHandler(handler) + app.run() diff --git a/python/ql/src/experimental/Security/CWE-117/LogInjectionGood.py b/python/ql/src/experimental/Security/CWE-117/LogInjectionGood.py new file mode 100644 index 00000000000..d9279f2e482 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-117/LogInjectionGood.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :Log Injection +""" +from flask import Flask +from flask import request +import logging + +logging.basicConfig(level=logging.DEBUG) + +app = Flask(__name__) + +@app.route('/good1') +def good1(): + name = request.args.get('name') + name = name.replace('\r\n','').replace('\n','') + logging.info('User name: ' + name) # Good + return 'good1' + +if __name__ == '__main__': + app.debug = True + handler = logging.FileHandler('log') + app.logger.addHandler(handler) + app.run() diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index f87caa88497..60f12f8c02b 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -14,6 +14,36 @@ private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.TaintTracking private import experimental.semmle.python.Frameworks +/** Provides classes for modeling log related APIs. */ +module LogOutput { + /** + * A data flow node for log output. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `LogOutput` instead. + */ + abstract class Range extends DataFlow::Node { + /** + * Get the parameter value of the log output function. + */ + abstract DataFlow::Node getAnInput(); + } +} + +/** + * A data flow node for log output. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `LogOutput::Range` instead. + */ +class LogOutput extends DataFlow::Node { + LogOutput::Range range; + + LogOutput() { this = range } + + DataFlow::Node getAnInput() { result = range.getAnInput() } +} + /** Provides classes for modeling Regular Expression-related APIs. */ module RegexExecution { /** diff --git a/python/ql/src/experimental/semmle/python/Frameworks.qll b/python/ql/src/experimental/semmle/python/Frameworks.qll index e8467383824..5b5161499ff 100644 --- a/python/ql/src/experimental/semmle/python/Frameworks.qll +++ b/python/ql/src/experimental/semmle/python/Frameworks.qll @@ -1,7 +1,7 @@ /** * Helper file that imports all framework modeling. */ - private import experimental.semmle.python.frameworks.Stdlib private import experimental.semmle.python.frameworks.LDAP private import experimental.semmle.python.frameworks.NoSQL +private import experimental.semmle.python.frameworks.Log diff --git a/python/ql/src/experimental/semmle/python/frameworks/Log.qll b/python/ql/src/experimental/semmle/python/frameworks/Log.qll new file mode 100644 index 00000000000..b05d9e52118 --- /dev/null +++ b/python/ql/src/experimental/semmle/python/frameworks/Log.qll @@ -0,0 +1,92 @@ +/** + * Provides classes modeling security-relevant aspects of the log libraries. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.dataflow.new.RemoteFlowSources +private import experimental.semmle.python.Concepts +private import semmle.python.frameworks.Flask +private import semmle.python.ApiGraphs + +/** + * Provides models for Python's log-related libraries. + */ +private module log { + /** + * Log output method list. + * + * See https://docs.python.org/3/library/logging.html#logger-objects + */ + private class LogOutputMethods extends string { + LogOutputMethods() { this in ["info", "error", "warn", "warning", "debug", "critical"] } + } + + /** + * The class used to find the log output method of the `logging` module. + * + * See `LogOutputMethods` + */ + private class LoggingCall extends DataFlow::CallCfgNode, LogOutput::Range { + LoggingCall() { + this = API::moduleImport("logging").getMember(any(LogOutputMethods m)).getACall() + } + + override DataFlow::Node getAnInput() { result = this.getArg(_) } + } + + /** + * The class used to find log output methods related to the `logging.getLogger` instance. + * + * See `LogOutputMethods` + */ + private class LoggerCall extends DataFlow::CallCfgNode, LogOutput::Range { + LoggerCall() { + this = + API::moduleImport("logging") + .getMember("getLogger") + .getReturn() + .getMember(any(LogOutputMethods m)) + .getACall() + } + + override DataFlow::Node getAnInput() { result = this.getArg(_) } + } + + /** + * The class used to find the relevant log output method of the `flask.Flask.logger` instance (flask application). + * + * See `LogOutputMethods` + */ + private class FlaskLoggingCall extends DataFlow::CallCfgNode, LogOutput::Range { + FlaskLoggingCall() { + this = + Flask::FlaskApp::instance() + .getMember("logger") + .getMember(any(LogOutputMethods m)) + .getACall() + } + + override DataFlow::Node getAnInput() { result = this.getArg(_) } + } + + /** + * The class used to find the relevant log output method of the `django.utils.log.request_logger` instance (django application). + * + * See `LogOutputMethods` + */ + private class DjangoLoggingCall extends DataFlow::CallCfgNode, LogOutput::Range { + DjangoLoggingCall() { + this = + API::moduleImport("django") + .getMember("utils") + .getMember("log") + .getMember("request_logger") + .getMember(any(LogOutputMethods m)) + .getACall() + } + + override DataFlow::Node getAnInput() { result = this.getArg(_) } + } +} diff --git a/python/ql/src/experimental/semmle/python/security/injection/LogInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/LogInjection.qll new file mode 100644 index 00000000000..4ee9c69a4a9 --- /dev/null +++ b/python/ql/src/experimental/semmle/python/security/injection/LogInjection.qll @@ -0,0 +1,24 @@ +import python +import semmle.python.Concepts +import experimental.semmle.python.Concepts +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.dataflow.new.RemoteFlowSources + +/** + * A taint-tracking configuration for tracking untrusted user input used in log entries. + */ +class LogInjectionFlowConfig extends TaintTracking::Configuration { + LogInjectionFlowConfig() { this = "LogInjectionFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink = any(LogOutput logoutput).getAnInput() } + + override predicate isSanitizer(DataFlow::Node node) { + exists(CallNode call | + node.asCfgNode() = call.getFunction().(AttrNode).getObject("replace") and + call.getArg(0).getNode().(StrConst).getText() in ["\r\n", "\n"] + ) + } +} diff --git a/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected new file mode 100644 index 00000000000..14774193ce5 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected @@ -0,0 +1,27 @@ +edges +| LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | LogInjectionBad.py:17:12:17:23 | ControlFlowNode for Attribute | +| LogInjectionBad.py:17:12:17:23 | ControlFlowNode for Attribute | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | +| LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | LogInjectionBad.py:23:12:23:23 | ControlFlowNode for Attribute | +| LogInjectionBad.py:23:12:23:23 | ControlFlowNode for Attribute | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | +| LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | LogInjectionBad.py:29:12:29:23 | ControlFlowNode for Attribute | +| LogInjectionBad.py:29:12:29:23 | ControlFlowNode for Attribute | LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | +| LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | LogInjectionBad.py:35:12:35:23 | ControlFlowNode for Attribute | +| LogInjectionBad.py:35:12:35:23 | ControlFlowNode for Attribute | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | +nodes +| LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| LogInjectionBad.py:17:12:17:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| LogInjectionBad.py:23:12:23:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| LogInjectionBad.py:29:12:29:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| LogInjectionBad.py:35:12:35:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +#select +| LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | $@ flows to log entry. | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | User-provided value | +| LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | $@ flows to log entry. | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | User-provided value | +| LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | $@ flows to log entry. | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | User-provided value | +| LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | $@ flows to log entry. | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | User-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.qlref new file mode 100644 index 00000000000..021cc357ac2 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-117/LogInjection.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjectionBad.py b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjectionBad.py new file mode 100644 index 00000000000..0c0cbe1a8fe --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjectionBad.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :Log Injection +""" +from flask import Flask +from flask import request +from django.utils.log import request_logger +import logging + +logging.basicConfig(level=logging.DEBUG) + +app = Flask(__name__) + +@app.route('/bad1') +def bad1(): + name = request.args.get('name') + app.logger.info('User name: ' + name) # Bad + return 'bad1' + +@app.route('/bad2') +def bad2(): + name = request.args.get('name') + logging.info('User name: ' + name) # Bad + return 'bad2' + +@app.route('/bad3') +def bad3(): + name = request.args.get('name') + request_logger.warn('User name: ' + name) # Bad + return 'bad3' + +@app.route('/bad4') +def bad4(): + name = request.args.get('name') + logtest = logging.getLogger('test') + logtest.debug('User name: ' + name) # Bad + return 'bad4' + +if __name__ == '__main__': + app.debug = True + handler = logging.FileHandler('log') + app.logger.addHandler(handler) + app.run() diff --git a/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjectionGood.py b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjectionGood.py new file mode 100644 index 00000000000..d9279f2e482 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjectionGood.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :Log Injection +""" +from flask import Flask +from flask import request +import logging + +logging.basicConfig(level=logging.DEBUG) + +app = Flask(__name__) + +@app.route('/good1') +def good1(): + name = request.args.get('name') + name = name.replace('\r\n','').replace('\n','') + logging.info('User name: ' + name) # Good + return 'good1' + +if __name__ == '__main__': + app.debug = True + handler = logging.FileHandler('log') + app.logger.addHandler(handler) + app.run() From 02776017055491f0e81143e1f2907991689882ea Mon Sep 17 00:00:00 2001 From: haby0 Date: Thu, 16 Sep 2021 20:59:34 +0800 Subject: [PATCH 046/361] Eliminate false positives caused by `.` --- .../Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll index b003a188b1a..82da4f5b46f 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll @@ -124,7 +124,7 @@ private class CompareSink extends ClientSuppliedIpUsedInSecurityCheckSink { compare.getLeft() = this.asExpr() or compare.getComparator(0) = this.asExpr() and - not compare.getLeft().(StrConst).getText() in ["%", ","] + not compare.getLeft().(StrConst).getText() in ["%", ",", "."] ) ) } From 64685f31dc804e9c34d2693001010358614c308c Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 16 Sep 2021 16:51:43 +0200 Subject: [PATCH 047/361] Python: Add missing qldoc Also do some general cleanup How was this allowed comitted in the first place? --- python/ql/lib/semmle/python/RegexTreeView.qll | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/python/ql/lib/semmle/python/RegexTreeView.qll b/python/ql/lib/semmle/python/RegexTreeView.qll index ad1949e4bc4..3884bed9763 100644 --- a/python/ql/lib/semmle/python/RegexTreeView.qll +++ b/python/ql/lib/semmle/python/RegexTreeView.qll @@ -49,6 +49,7 @@ newtype TRegExpParent = * or another regular expression term. */ class RegExpParent extends TRegExpParent { + /** Gets a textual representation of this element. */ string toString() { result = "RegExpParent" } /** Gets the `i`th child term. */ @@ -72,14 +73,18 @@ class RegExpLiteral extends TRegExpLiteral, RegExpParent { override RegExpTerm getChild(int i) { i = 0 and result.getRegex() = re and result.isRootTerm() } + /** Holds if dot, `.`, matches all characters, including newlines. */ predicate isDotAll() { re.getAMode() = "DOTALL" } + /** Holds if this regex matching is case-insensitive for this regex. */ predicate isIgnoreCase() { re.getAMode() = "IGNORECASE" } + /** Get a string representing all modes for this regex. */ string getFlags() { result = concat(string mode | mode = re.getAMode() | mode, " | ") } override Regex getRegex() { result = re } + /** Gets the primary QL class for this regex. */ string getPrimaryQLClass() { result = "RegExpLiteral" } } @@ -246,8 +251,10 @@ class RegExpQuantifier extends RegExpTerm, TRegExpQuantifier { result.getEnd() = part_end } + /** Hols if this term may match an unlimited number of times. */ predicate mayRepeatForever() { may_repeat_forever = true } + /** Gets the qualifier for this term. That is e.g "?" for "a?". */ string getQualifier() { result = re.getText().substring(part_end, end) } override string getPrimaryQLClass() { result = "RegExpQuantifier" } @@ -322,8 +329,10 @@ class RegExpRange extends RegExpQuantifier { RegExpRange() { re.multiples(part_end, end, lower, upper) } + /** Gets the string defining the upper bound of this range, if any. */ string getUpper() { result = upper } + /** Gets the string defining the lower bound of this range, if any. */ string getLower() { result = lower } /** @@ -465,11 +474,13 @@ class RegExpEscape extends RegExpNormalChar { result = getUnicode() } + /** Holds if this terms name is given by the part following the escape character. */ predicate isIdentityEscape() { not this.getUnescaped() in ["n", "r", "t", "f"] } override string getPrimaryQLClass() { result = "RegExpEscape" } - string getUnescaped() { result = this.getText().suffix(1) } + /** Gets the part of the term following the escape character. That is e.g. "w" if the term is "\w". */ + private string getUnescaped() { result = this.getText().suffix(1) } /** * Gets the text for this escape. That is e.g. "\w". @@ -536,15 +547,8 @@ private int toHex(string hex) { * ``` */ class RegExpCharacterClassEscape extends RegExpEscape { - // string value; - RegExpCharacterClassEscape() { - // value = re.getText().substring(start + 1, end) and - // value in ["d", "D", "s", "S", "w", "W"] - this.getValue() in ["d", "D", "s", "S", "w", "W"] - } + RegExpCharacterClassEscape() { this.getValue() in ["d", "D", "s", "S", "w", "W"] } - /** Gets the name of the character class; for example, `w` for `\w`. */ - // override string getValue() { result = value } override RegExpTerm getChild(int i) { none() } override string getPrimaryQLClass() { result = "RegExpCharacterClassEscape" } @@ -563,10 +567,13 @@ class RegExpCharacterClassEscape extends RegExpEscape { class RegExpCharacterClass extends RegExpTerm, TRegExpCharacterClass { RegExpCharacterClass() { this = TRegExpCharacterClass(re, start, end) } + /** Holds if this character class is inverted, matching the opposite of its content. */ predicate isInverted() { re.getChar(start + 1) = "^" } + /** Gets the `i`th char inside this charater class. */ string getCharThing(int i) { result = re.getChar(i + start) } + /** Holds if this character class can match anything. */ predicate isUniversalClass() { // [^] isInverted() and not exists(getAChild()) @@ -620,6 +627,7 @@ class RegExpCharacterRange extends RegExpTerm, TRegExpCharacterRange { re.charRange(_, start, lower_end, upper_start, end) } + /** Holds if this range goes from `lo` to `hi`, in effect is `lo-hi`. */ predicate isRange(string lo, string hi) { lo = re.getText().substring(start, lower_end) and hi = re.getText().substring(upper_start, end) @@ -653,8 +661,13 @@ class RegExpCharacterRange extends RegExpTerm, TRegExpCharacterRange { class RegExpNormalChar extends RegExpTerm, TRegExpNormalChar { RegExpNormalChar() { this = TRegExpNormalChar(re, start, end) } + /** + * Holds if this constant represents a valid Unicode character (as opposed + * to a surrogate code point that does not correspond to a character by itself.) + */ predicate isCharacter() { any() } + /** Gets the string representation of the char matched by this term. */ string getValue() { result = re.getText().substring(start, end) } override RegExpTerm getChild(int i) { none() } @@ -684,15 +697,15 @@ class RegExpConstant extends RegExpTerm { qstart <= start and end <= qend ) and value = this.(RegExpNormalChar).getValue() - // This will never hold - // or - // this = TRegExpSpecialChar(re, start, end) and - // re.inCharSet(start) and - // value = this.(RegExpSpecialChar).getChar() } + /** + * Holds if this constant represents a valid Unicode character (as opposed + * to a surrogate code point that does not correspond to a character by itself.) + */ predicate isCharacter() { any() } + /** Gets the string matched by this constant term. */ string getValue() { result = value } override RegExpTerm getChild(int i) { none() } @@ -731,10 +744,6 @@ class RegExpGroup extends RegExpTerm, TRegExpGroup { /** Gets the name of this capture group, if any. */ string getName() { result = re.getGroupName(start, end) } - predicate isCharacter() { any() } - - string getValue() { result = re.getText().substring(start, end) } - override RegExpTerm getChild(int i) { result.getRegex() = re and i = 0 and @@ -762,8 +771,13 @@ class RegExpSpecialChar extends RegExpTerm, TRegExpSpecialChar { re.specialCharacter(start, end, char) } + /** + * Holds if this constant represents a valid Unicode character (as opposed + * to a surrogate code point that does not correspond to a character by itself.) + */ predicate isCharacter() { any() } + /** Gets the char for this term. */ string getChar() { result = char } override RegExpTerm getChild(int i) { none() } @@ -828,8 +842,6 @@ class RegExpCaret extends RegExpSpecialChar { class RegExpZeroWidthMatch extends RegExpGroup { RegExpZeroWidthMatch() { re.zeroWidthMatch(start, end) } - override predicate isCharacter() { any() } - override RegExpTerm getChild(int i) { none() } override string getPrimaryQLClass() { result = "RegExpZeroWidthMatch" } From b393c6a285f9ff3ffc81c843fb301b4509b93af4 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 16 Sep 2021 19:16:54 +0300 Subject: [PATCH 048/361] Add files via upload --- .../CWE/CWE-1041/FindWrapperFunctions.cpp | 18 +++ .../CWE/CWE-1041/FindWrapperFunctions.qhelp | 18 +++ .../CWE/CWE-1041/FindWrapperFunctions.ql | 140 ++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.cpp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.cpp new file mode 100644 index 00000000000..a04107bbadf --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.cpp @@ -0,0 +1,18 @@ +... +int myFclose(FILE * fmy) +{ + if(!fclose(fmy)) { + fmy = NULL; + return 0; + } + return -1; +} +... + fe = fopen("myFile.txt", "wt"); + ... + fclose(fe); // BAD +... + fe = fopen("myFile.txt", "wt"); + ... + myFclose(fe); // GOOD +... diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp new file mode 100644 index 00000000000..1eb5b3e5e5c --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp @@ -0,0 +1,18 @@ + + + +

    Finding for function calls for which wrapper functions exist.

    + +
    + + +

    The following example demonstrates fallacious and fixed methods of using wrapper functions.

    + + +
    + + + +
    diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql new file mode 100644 index 00000000000..1baafd4a171 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql @@ -0,0 +1,140 @@ +/** + * @name Find Wrapper Functions + * @description --Finding for function calls for which wrapper functions exist. + * @kind problem + * @id cpp/find-wrapper-functions + * @problem.severity warning + * @precision medium + * @tags correctness + * security + * external/cwe/cwe-1041 + */ + +import cpp +import semmle.code.cpp.valuenumbering.GlobalValueNumbering +import semmle.code.cpp.commons.Assertions + +/** + * A function call that is used in error situations (logging, throwing an exception, abnormal termination). + */ +class CallUsedToHandleErrors extends FunctionCall { + CallUsedToHandleErrors() { + // call that is known to not return + not exists(this.(ControlFlowNode).getASuccessor()) + or + // call throwing an exception + exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor()) + or + // call logging a message, possibly an error + exists(FormattingFunction ff | ff = this.(ControlFlowNode).getASuccessor()) + or + // enabling recursive search + exists(CallUsedToHandleErrors fr | getTarget() = fr.getEnclosingFunction()) + } +} + +/** Holds if the conditions for a call outside the wrapper function are met. */ +predicate conditionsOutsideWrapper(FunctionCall fcp) { + fcp.getNumberOfArguments() > 0 and + not exists(ConditionalStmt cdtmp | fcp.getEnclosingStmt().getParentStmt*() = cdtmp) and + not exists(Loop lptmp | fcp.getEnclosingStmt().getParentStmt*() = lptmp) and + not exists(ReturnStmt rttmp | fcp.getEnclosingStmt().getParentStmt*() = rttmp) and + not exists(FunctionCall fctmp2 | fcp = fctmp2.getAnArgument().getAChild*()) and + not exists(Assignment astmp | fcp = astmp.getRValue().getAChild*()) and + not exists(Initializer intmp | fcp = intmp.getExpr().getAChild*()) and + not exists(Assertion astmp | fcp = astmp.getAsserted().getAChild*()) and + not exists(Operation optmp | fcp = optmp.getAChild*()) and + not exists(ArrayExpr aetmp | fcp = aetmp.getAChild*()) and + not exists(ExprCall ectmp | fcp = ectmp.getAnArgument().getAChild*()) +} + +/** Holds if the conditions for a call within the wrapper function are met. */ +pragma[inline] +predicate conditionsInsideWrapper(FunctionCall fcp, Function fnp) { + not exists(FunctionCall fctmp2 | + fctmp2.getEnclosingFunction() = fnp and fcp = fctmp2.getAnArgument().getAChild*() + ) and + not fcp instanceof CallUsedToHandleErrors and + not fcp.getAnArgument().isConstant() and + fcp.getEnclosingFunction() = fnp and + fnp.getNumberOfParameters() > 0 and + // the call arguments must be passed through the arguments of the wrapper function + forall(int i | i in [0 .. fcp.getNumberOfArguments() - 1] | + fcp.getArgument(i).(VariableAccess).getTarget() = fnp.getAParameter().getAnAccess().getTarget() + ) and + // there should be no more than one required call inside the wrapper function + not exists(FunctionCall fctmp | + fctmp.getTarget() = fcp.getTarget() and + fctmp.getFile() = fcp.getFile() and + fctmp != fcp and + fctmp.getEnclosingFunction() = fnp + ) and + // inside the wrapper function there should be no calls without paths to the desired function + not exists(FunctionCall fctmp | + fctmp.getEnclosingFunction() = fnp and + fctmp.getFile() = fcp.getFile() and + fctmp != fcp and + ( + fctmp = fcp.getAPredecessor+() + or + not exists(FunctionCall fctmp1 | + fctmp1 = fcp and + ( + fctmp.getASuccessor+() = fctmp1 or + fctmp.getAPredecessor+() = fctmp1 + ) + ) + ) + ) +} + +/** Holds if the conditions for the wrapper function are met. */ +pragma[inline] +predicate conditionsForWrapper(FunctionCall fcp, Function fnp) { + not exists(ExprCall ectmp | fnp = ectmp.getEnclosingFunction()) and + not exists(Loop lp | lp.getEnclosingFunction() = fnp) and + not exists(SwitchStmt sw | sw.getEnclosingFunction() = fnp) and + not fnp instanceof Operator and + // inside the wrapper function there should be checks of arguments or the result, + // perhaps by means of passing the latter as an argument to some function + ( + exists(IfStmt ifs | + ifs.getEnclosingFunction() = fnp and + ( + globalValueNumber(ifs.getCondition().getAChild*()) = globalValueNumber(fcp.getAnArgument()) and + ifs.getASuccessor*() = fcp + or + ifs.getCondition().getAChild() = fcp + ) + ) + or + exists(FunctionCall fctmp | + fctmp.getEnclosingFunction() = fnp and + globalValueNumber(fctmp.getAnArgument().getAChild*()) = globalValueNumber(fcp) + ) + ) and + // inside the wrapper function there must be a function call to handle the error + exists(CallUsedToHandleErrors fctmp | + fctmp.getEnclosingFunction() = fnp and + forall(int i | i in [0 .. fnp.getNumberOfParameters() - 1] | + fnp.getParameter(i).getAnAccess().getTarget() = + fcp.getAnArgument().(VariableAccess).getTarget() or + fnp.getParameter(i).getType() instanceof Class or + fnp.getParameter(i).getType().(ReferenceType).getBaseType() instanceof Class or + fnp.getParameter(i).getAnAccess().getTarget() = + fctmp.getAnArgument().(VariableAccess).getTarget() + ) + ) +} + +from FunctionCall fc, Function fn +where + exists(FunctionCall fctmp | + conditionsInsideWrapper(fctmp, fn) and + conditionsForWrapper(fctmp, fn) and + conditionsOutsideWrapper(fc) and + fctmp.getTarget() = fc.getTarget() and + fc.getEnclosingFunction() != fn and + fc.getEnclosingFunction().getMetrics().getNumberOfCalls() > fn.getMetrics().getNumberOfCalls() + ) +select fc, "consider changing the call to $@", fn, fn.getName() From b6bcf9fa44957c5c09073e75db87eae7cfcc8733 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 16 Sep 2021 19:18:19 +0300 Subject: [PATCH 049/361] Add files via upload --- .../tests/FindWrapperFunctions.expected | 1 + .../semmle/tests/FindWrapperFunctions.qlref | 1 + .../CWE/CWE-1041/semmle/tests/test.cpp | 27 +++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/test.cpp diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected new file mode 100644 index 00000000000..ab377e4b3b0 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected @@ -0,0 +1 @@ +| test.cpp:23:3:23:8 | call to fclose | consider changing the call to $@ | test.cpp:9:6:9:13 | myFclose | myFclose | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.qlref new file mode 100644 index 00000000000..22dae13892f --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/test.cpp new file mode 100644 index 00000000000..4f862a324e5 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/test.cpp @@ -0,0 +1,27 @@ +#define NULL (0) +typedef int FILE; +FILE *fopen(const char *filename, const char *mode); +int fclose(FILE *stream); +extern FILE * fe; +extern int printf(const char *fmt, ...); +void exit(int status); + +void myFclose(FILE * fmy) +{ + int i; + if(fmy) { + i = fclose(fmy); + fmy = NULL; + printf("close end is code %d",i); + if(i!=0) exit(1); + } +} + +int main(int argc, char *argv[]) +{ + fe = fopen("myFile.txt", "wt"); + fclose(fe); // BAD + fe = fopen("myFile.txt", "wt"); + myFclose(fe); // GOOD + return 0; +} From a3de94e868aa89c16ef36809f6b1a3446bc50eec Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 13 Sep 2021 15:50:10 +0100 Subject: [PATCH 050/361] C++: Assign precision and severity; medium for now, since there are FPs in SAMATE Juliet. --- cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 123c7437990..26cd2d89e11 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -4,8 +4,8 @@ * cleartext can expose it to an attacker. * @kind path-problem * @problem.severity warning - * @security-severity 7.5 TODO - * @precision high TODO + * @security-severity 7.5 + * @precision medium * @id cpp/cleartext-transmission * @tags security * external/cwe/cwe-319 From 99167539fb0291805b26ec2f9daefe99a1944992 Mon Sep 17 00:00:00 2001 From: haby0 Date: Fri, 17 Sep 2021 17:29:40 +0800 Subject: [PATCH 051/361] Modify sinks --- .../semmle/python/frameworks/Log.qll | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Log.qll b/python/ql/src/experimental/semmle/python/frameworks/Log.qll index b05d9e52118..6ffc3529daa 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Log.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Log.qll @@ -20,7 +20,9 @@ private module log { * See https://docs.python.org/3/library/logging.html#logger-objects */ private class LogOutputMethods extends string { - LogOutputMethods() { this in ["info", "error", "warn", "warning", "debug", "critical"] } + LogOutputMethods() { + this in ["info", "error", "warn", "warning", "debug", "critical", "exception", "log"] + } } /** @@ -33,7 +35,13 @@ private module log { this = API::moduleImport("logging").getMember(any(LogOutputMethods m)).getACall() } - override DataFlow::Node getAnInput() { result = this.getArg(_) } + override DataFlow::Node getAnInput() { + this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and + result = this.getArg(0) + or + this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and + result = this.getArg(1) + } } /** @@ -51,7 +59,13 @@ private module log { .getACall() } - override DataFlow::Node getAnInput() { result = this.getArg(_) } + override DataFlow::Node getAnInput() { + this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and + result = this.getArg(0) + or + this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and + result = this.getArg(1) + } } /** @@ -68,7 +82,13 @@ private module log { .getACall() } - override DataFlow::Node getAnInput() { result = this.getArg(_) } + override DataFlow::Node getAnInput() { + this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and + result = this.getArg(0) + or + this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and + result = this.getArg(1) + } } /** @@ -87,6 +107,12 @@ private module log { .getACall() } - override DataFlow::Node getAnInput() { result = this.getArg(_) } + override DataFlow::Node getAnInput() { + this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and + result = this.getArg(0) + or + this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and + result = this.getArg(1) + } } } From 90bc138049d1717cab61899cc9d23fdddad1e8a6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 17 Sep 2021 14:08:34 +0100 Subject: [PATCH 052/361] CPP: Fix QLDoc comments. --- cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 26cd2d89e11..c130c9a49b6 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -35,7 +35,7 @@ abstract class NetworkSendRecv extends FunctionCall { /** * A function call that sends data over a network. * - * note: functions such as `read` may be reading from a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it probably isn't very important which query reports a result as long as its reported exactly once. + * note: functions such as `write` may be writing to a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it usually isn't very important which query reports a result as long as its reported exactly once. */ class NetworkSend extends NetworkSendRecv { NetworkSend() { @@ -76,6 +76,8 @@ class SensitiveSendRecvConfiguration extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { exists(NetworkSendRecv transmission | sink.asExpr() = transmission.getDataExpr() and + + // a zero file descriptor is standard input, which is not interesting for this query. not exists(Zero zero | DataFlow::localFlow(DataFlow::exprNode(zero), DataFlow::exprNode(transmission.getSocketExpr())) From 51243454c890c3c58c0d9ba767dfec8a030ba2ed Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 17 Sep 2021 15:10:55 +0100 Subject: [PATCH 053/361] C++: Change note. --- cpp/change-notes/2021-06-10-cleartext-transmission.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 cpp/change-notes/2021-06-10-cleartext-transmission.md diff --git a/cpp/change-notes/2021-06-10-cleartext-transmission.md b/cpp/change-notes/2021-06-10-cleartext-transmission.md new file mode 100644 index 00000000000..ce6debf1407 --- /dev/null +++ b/cpp/change-notes/2021-06-10-cleartext-transmission.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* A new query (`cpp/cleartext-transmission`) has been added. This is similar to the `cpp/cleartext-storage-file`, `cpp/cleartext-storage-buffer` and `cpp/cleartext-storage-database` queries but looks for cases where sensitive information is most likely transmitted over a network. From e7c82d7370e7a6b7d6d5981a306b87d609373cdc Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 17 Sep 2021 16:14:24 +0100 Subject: [PATCH 054/361] C++: Accept subpaths in tests. --- .../CWE/CWE-311/semmle/tests/CleartextTransmission.expected | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index ae2333ba8c9..3534c2c7cad 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -2,9 +2,11 @@ edges | test3.cpp:68:21:68:29 | password1 | test3.cpp:70:15:70:17 | ptr | | test3.cpp:75:15:75:22 | password | test3.cpp:77:15:77:17 | ptr | | test3.cpp:106:20:106:25 | buffer | test3.cpp:108:14:108:19 | buffer | +| test3.cpp:111:28:111:33 | buffer | test3.cpp:113:9:113:14 | buffer | | test3.cpp:120:9:120:23 | global_password | test3.cpp:138:16:138:29 | call to get_global_str | | test3.cpp:128:11:128:18 | password | test3.cpp:106:20:106:25 | buffer | | test3.cpp:132:21:132:22 | call to id | test3.cpp:134:15:134:17 | ptr | +| test3.cpp:132:24:132:32 | password1 | test3.cpp:111:28:111:33 | buffer | | test3.cpp:132:24:132:32 | password1 | test3.cpp:132:21:132:22 | call to id | | test3.cpp:138:16:138:29 | call to get_global_str | test3.cpp:140:15:140:18 | data | | test3.cpp:151:19:151:26 | password | test3.cpp:153:15:153:20 | buffer | @@ -20,6 +22,8 @@ nodes | test3.cpp:95:12:95:19 | password | semmle.label | password | | test3.cpp:106:20:106:25 | buffer | semmle.label | buffer | | test3.cpp:108:14:108:19 | buffer | semmle.label | buffer | +| test3.cpp:111:28:111:33 | buffer | semmle.label | buffer | +| test3.cpp:113:9:113:14 | buffer | semmle.label | buffer | | test3.cpp:120:9:120:23 | global_password | semmle.label | global_password | | test3.cpp:128:11:128:18 | password | semmle.label | password | | test3.cpp:132:21:132:22 | call to id | semmle.label | call to id | @@ -29,6 +33,8 @@ nodes | test3.cpp:140:15:140:18 | data | semmle.label | data | | test3.cpp:151:19:151:26 | password | semmle.label | password | | test3.cpp:153:15:153:20 | buffer | semmle.label | buffer | +subpaths +| test3.cpp:132:24:132:32 | password1 | test3.cpp:111:28:111:33 | buffer | test3.cpp:113:9:113:14 | buffer | test3.cpp:132:21:132:22 | call to id | #select | test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@ | test3.cpp:20:15:20:23 | password1 | password1 | | test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@ | test3.cpp:24:15:24:23 | password2 | password2 | From 237a7d34b8c45965d5c8c819b88be3bfdd1e3177 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 21 Sep 2021 11:31:13 +0200 Subject: [PATCH 055/361] C++: Exclusion rules for system macros Unwanted results were reported for our JPL Rule 24 queries. Including system headers with complex macros could lead to unpredictable alerts from these rules. --- .../semmle/code/cpp/commons/Exclusions.qll | 44 +++++++++++++++++-- .../LOC-4/Rule 24/MultipleStmtsPerLine.ql | 6 ++- .../LOC-4/Rule 24/MultipleVarDeclsPerLine.ql | 6 ++- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Exclusions.qll b/cpp/ql/lib/semmle/code/cpp/commons/Exclusions.qll index a0dfea20046..6ace4aa49e6 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Exclusions.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Exclusions.qll @@ -81,8 +81,8 @@ predicate functionContainsPreprocCode(Function f) { } /** - * Holds if `e` is completely or partially from a macro definition, as opposed - * to being passed in as an argument. + * Holds if `e` is completely or partially from a macro invocation `mi`, as + * opposed to being passed in as an argument. * * In the following example, the call to `f` is from a macro definition, * while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart @@ -93,8 +93,8 @@ predicate functionContainsPreprocCode(Function f) { * M(y + 1); * ``` */ -predicate isFromMacroDefinition(Element e) { - exists(MacroInvocation mi, Location eLocation, Location miLocation | +private predicate isFromMacroInvocation(Element e, MacroInvocation mi) { + exists(Location eLocation, Location miLocation | mi.getAnExpandedElement() = e and eLocation = e.getLocation() and miLocation = mi.getLocation() and @@ -109,3 +109,39 @@ predicate isFromMacroDefinition(Element e) { eLocation.getEndColumn() >= miLocation.getEndColumn() ) } + +/** + * Holds if `e` is completely or partially from a macro definition, as opposed + * to being passed in as an argument. + * + * In the following example, the call to `f` is from a macro definition, + * while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart + * from `M` refers to a macro. + * ``` + * #define M(x) f(x) + * ... + * M(y + 1); + * ``` + */ +predicate isFromMacroDefinition(Element e) { + isFromMacroInvocation(e, _) +} + +/** + * Holds if `e` is completely or partially from a _system macro_ definition, as + * opposed to being passed in as an argument. A system macro is a macro whose + * definition is outside the source directory of the database. + * + * If the system macro is invoked through a non-system macro, then this + * predicate does not hold. That's a limitation of how macros are represented + * in the database. + * + * See also `isFromMacroDefinition`. + */ +predicate isFromSystemMacroDefinition(Element e) { + exists(MacroInvocation mi | + isFromMacroInvocation(e, mi) and + // Has no relative path in the database, meaning it's a system file. + not exists(mi.getMacro().getFile().getRelativePath()) + ) +} diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql index 5eccd2c5cad..c99c3de470e 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql @@ -10,6 +10,7 @@ */ import cpp +import semmle.code.cpp.commons.Exclusions class OneLineStmt extends Stmt { OneLineStmt() { @@ -34,5 +35,8 @@ where other.onLine(f, line) and toMin = other.getLocation().getStartColumn() | toMin - ) + ) and + // Exclude statements that are from invocations of system-header macros. + // Example: FD_ISSET from glibc. + not isFromSystemMacroDefinition(o) select o, "This line contains " + cnt + " statements; only one is allowed." diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql index fcdb2471b76..41413353346 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql @@ -10,11 +10,15 @@ */ import cpp +import semmle.code.cpp.commons.Exclusions from DeclStmt d where exists(Variable v1, Variable v2 | v1 = d.getADeclaration() and v2 = d.getADeclaration() | v1 != v2 and v1.getLocation().getStartLine() = v2.getLocation().getStartLine() - ) + ) and + // Exclude declarations that are from invocations of system-header macros. + // Example: FD_ZERO from glibc. + not isFromSystemMacroDefinition(d) select d, "Multiple variable declarations on the same line." From a055c86c4f9618fc6a368696a1f3562e18c18db7 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 21 Sep 2021 11:58:04 +0200 Subject: [PATCH 056/361] C++: change note --- cpp/change-notes/2021-09-21-jpl24.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 cpp/change-notes/2021-09-21-jpl24.md diff --git a/cpp/change-notes/2021-09-21-jpl24.md b/cpp/change-notes/2021-09-21-jpl24.md new file mode 100644 index 00000000000..51af4db8b31 --- /dev/null +++ b/cpp/change-notes/2021-09-21-jpl24.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* The opt-in queries for JPL C coding standards Rule 24 now exclude macros from + system headers. From 88a257fcdc63c2504f3fbd697f401beade8f28d7 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Tue, 21 Sep 2021 20:32:08 +0300 Subject: [PATCH 057/361] Apply suggestions from code review Co-authored-by: Mathias Vorreiter Pedersen --- .../Security/CWE/CWE-1041/FindWrapperFunctions.ql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql index 1baafd4a171..1df7babc862 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql @@ -1,8 +1,8 @@ /** - * @name Find Wrapper Functions - * @description --Finding for function calls for which wrapper functions exist. + * @name Missed opportunity to call wrapper function + * @description If a wrapper function is defined for a given function, any call to the given function should be via the wrapper function. * @kind problem - * @id cpp/find-wrapper-functions + * @id cpp/call-to-function-without-wrapper * @problem.severity warning * @precision medium * @tags correctness @@ -137,4 +137,4 @@ where fc.getEnclosingFunction() != fn and fc.getEnclosingFunction().getMetrics().getNumberOfCalls() > fn.getMetrics().getNumberOfCalls() ) -select fc, "consider changing the call to $@", fn, fn.getName() +select fc, "Consider changing the call to $@", fn, fn.getName() From 6c07a3e260724df620467f3e05045fab56e9441b Mon Sep 17 00:00:00 2001 From: haby0 Date: Wed, 22 Sep 2021 18:50:58 +0800 Subject: [PATCH 058/361] Apply @yoff's suggestion --- .../semmle/python/frameworks/Log.qll | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Log.qll b/python/ql/src/experimental/semmle/python/frameworks/Log.qll index 6ffc3529daa..489bb859b1c 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Log.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Log.qll @@ -37,10 +37,10 @@ private module log { override DataFlow::Node getAnInput() { this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and - result = this.getArg(0) + result in [this.getArg(_), this.getArgByName(_) ] // this includes the arg named "msg" or this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and - result = this.getArg(1) + result in [this.getArg(any(int i | i > 0)), this.getArgByName(any(string s | s != "level"))] } } @@ -61,10 +61,10 @@ private module log { override DataFlow::Node getAnInput() { this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and - result = this.getArg(0) + result in [this.getArg(_), this.getArgByName(_) ] // this includes the arg named "msg" or this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and - result = this.getArg(1) + result in [this.getArg(any(int i | i > 0)), this.getArgByName(any(string s | s != "level"))] } } @@ -84,10 +84,10 @@ private module log { override DataFlow::Node getAnInput() { this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and - result = this.getArg(0) + result in [this.getArg(_), this.getArgByName(_) ] // this includes the arg named "msg" or this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and - result = this.getArg(1) + result in [this.getArg(any(int i | i > 0)), this.getArgByName(any(string s | s != "level"))] } } @@ -109,10 +109,10 @@ private module log { override DataFlow::Node getAnInput() { this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and - result = this.getArg(0) + result in [this.getArg(_), this.getArgByName(_) ] // this includes the arg named "msg" or this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and - result = this.getArg(1) + result in [this.getArg(any(int i | i > 0)), this.getArgByName(any(string s | s != "level"))] } } } From 805d1d170c196c4b989e3153638f364a8b3d34a1 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 22 Sep 2021 17:14:29 +0200 Subject: [PATCH 059/361] do not filter away regular expressions with lookbehinds --- .../lib/semmle/javascript/security/performance/ReDoSUtil.qll | 2 -- .../Performance/ReDoS/PolynomialBackTracking.expected | 5 +++++ .../ql/test/query-tests/Performance/ReDoS/ReDoS.expected | 3 +++ javascript/ql/test/query-tests/Performance/ReDoS/tst.js | 3 +++ .../ql/lib/semmle/python/security/performance/ReDoSUtil.qll | 2 -- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll index 65431d7179e..12b7559615d 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll @@ -139,8 +139,6 @@ class RegExpRoot extends RegExpTerm { predicate isRelevant() { // there is at least one repetition getRoot(any(InfiniteRepetitionQuantifier q)) = this and - // there are no lookbehinds - not exists(RegExpLookbehind lbh | getRoot(lbh) = this) and // is actually used as a RegExp isUsedAsRegExp() and // not excluded for library specific reasons diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index a38b8cb37fe..dbf74f78d8f 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -362,6 +362,7 @@ | regexplib/uri.js:29:2:29:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | Strings with many repetitions of 'wwwa' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+(([a-zA-Z0-9\\.-]+\\.[a-zA-Z]{2,4})\|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(\\/[a-zA-Z0-9%:/-_\\?\\.'~]*)? | | regexplib/uri.js:29:48:29:62 | [a-zA-Z0-9\\.-]+ | Strings starting with 'wwwa' and with many repetitions of 'www--' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | | regexplib/uri.js:31:65:31:69 | [^<]+ | Strings starting with 'href=! >' and with many repetitions of 'href=! >;' can start matching anywhere after the start of the preceeding href\\s*=\\s*(?:(?:\\"(?[^\\"]*)\\")\|(?[^\\s*] ))>(?[^<]+)<\\/\\w> | +| regexplib/uri.js:34:3:34:9 | [^\\=&]+ | Strings with many repetitions of '%' can start matching anywhere after the start of the preceeding ([^\\=&]+)(?<!param1\|param2\|param3)\\=([^\\=&]+)(&)? | | regexplib/uri.js:36:40:36:42 | \\d* | Strings starting with '$1' and with many repetitions of '1' can start matching anywhere after the start of the preceeding [1-9]+ | | regexplib/uri.js:38:20:38:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | | regexplib/uri.js:38:35:38:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding [a-z0-9]+ | @@ -369,8 +370,10 @@ | regexplib/uri.js:39:7:39:9 | .*? | Strings starting with '<a' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | | regexplib/uri.js:39:43:39:45 | .*? | Strings with many repetitions of '>a' can start matching anywhere after the start of the preceeding .*? | | regexplib/uri.js:41:16:41:31 | [a-zA-Z0-9\\-\\.]+ | Strings starting with '0' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [a-zA-Z0-9]+ | +| regexplib/uri.js:44:2:44:4 | .*? | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*?$(?<!\\.aspx) | | regexplib/uri.js:47:31:47:36 | [\\w-]+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding [\\w-\\s]* | | regexplib/uri.js:51:51:51:53 | \\S+ | Strings with many repetitions of '!@' can start matching anywhere after the start of the preceeding \\S+ | +| regexplib/uri.js:53:3:53:9 | [^\\=&]+ | Strings with many repetitions of '%' can start matching anywhere after the start of the preceeding ([^\\=&]+)(?<!param1\|param2\|param3)\\=([^\\=&]+)(&)? | | regexplib/uri.js:54:40:54:42 | \\d* | Strings starting with '$1' and with many repetitions of '1' can start matching anywhere after the start of the preceeding [1-9]+ | | regexplib/uri.js:55:20:55:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | | regexplib/uri.js:55:35:55:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding [a-z0-9]+ | @@ -380,6 +383,7 @@ | regexplib/uri.js:64:31:64:36 | [\\w-]+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding [\\w-\\s]* | | regexplib/uri.js:70:16:70:31 | [a-zA-Z0-9\\-\\.]+ | Strings starting with '0' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [a-zA-Z0-9]+ | | regexplib/uri.js:71:75:71:89 | [^\\/\\\\:*?"<>\|]+ | Strings starting with 'A:\\\\!.' and with many repetitions of '!.' can start matching anywhere after the start of the preceeding [^\\/\\\\:*?"<>\|]+ | +| regexplib/uri.js:73:2:73:4 | .*? | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*?$(?<!\\.aspx) | | tst.js:14:15:14:16 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (.*,)+ | | tst.js:23:21:23:28 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding [\\s\\S]*? | | tst.js:23:33:23:40 | [\\s\\S]*? | Strings starting with '(*(*' and with many repetitions of '(*' can start matching anywhere after the start of the preceeding [\\s\\S]*? | @@ -507,3 +511,4 @@ | tst.js:382:14:382:23 | (foo\|FOO)* | Strings with many repetitions of 'foo' can start matching anywhere after the start of the preceeding (foo\|FOO)*bar | | tst.js:384:15:384:26 | ([AB]\|[ab])* | Strings with many repetitions of 'A' can start matching anywhere after the start of the preceeding ([AB]\|[ab])*C | | tst.js:385:14:385:25 | ([DE]\|[de])* | Strings with many repetitions of 'd' can start matching anywhere after the start of the preceeding ([DE]\|[de])*F | +| tst.js:388:14:388:20 | (a\|aa)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a\|aa)*$ | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index fe23342eb02..d7155b3711f 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -24,6 +24,7 @@ | regexplib/address.js:75:220:75:222 | \\w+ | This part of the regular expression may cause exponential backtracking on strings starting with 'C/O ' and containing many repetitions of 'a'. | | regexplib/address.js:75:616:75:618 | \\w+ | This part of the regular expression may cause exponential backtracking on strings starting with '9 a C/O ' and containing many repetitions of 'a'. | | regexplib/address.js:75:803:75:811 | [A-Za-z]+ | This part of the regular expression may cause exponential backtracking on strings starting with '9 a ' and containing many repetitions of 'A'. | +| regexplib/dates.js:27:341:27:348 | [^\\(\\)]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '''. | | regexplib/email.js:1:16:1:22 | [-.\\w]* | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:5:24:5:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | @@ -180,3 +181,5 @@ | tst.js:379:16:379:22 | [\\s\\S]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:382:14:382:23 | (foo\|FOO)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'foo'. | | tst.js:385:14:385:25 | ([DE]\|[de])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'd'. | +| tst.js:387:27:387:33 | (a\|aa)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | +| tst.js:388:14:388:20 | (a\|aa)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 1ab557520cb..6f3f8b1cd22 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -383,3 +383,6 @@ var bad91 = /(foo|FOO)*bar/i; var good47 = /([AB]|[ab])*C/; var bad92 = /([DE]|[de])*F/i; + +var bad93 = /(?<=^v?|\sv?)(a|aa)*$/; +var bad94 = /(a|aa)*$/; \ No newline at end of file diff --git a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll index 65431d7179e..12b7559615d 100644 --- a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll +++ b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll @@ -139,8 +139,6 @@ class RegExpRoot extends RegExpTerm { predicate isRelevant() { // there is at least one repetition getRoot(any(InfiniteRepetitionQuantifier q)) = this and - // there are no lookbehinds - not exists(RegExpLookbehind lbh | getRoot(lbh) = this) and // is actually used as a RegExp isUsedAsRegExp() and // not excluded for library specific reasons From 18de9f0aa353035af8dcf80f4ae2397be4576ace Mon Sep 17 00:00:00 2001 From: ihsinme <ihsinme@gmail.com> Date: Thu, 23 Sep 2021 12:53:16 +0300 Subject: [PATCH 060/361] Update FindWrapperFunctions.expected --- .../CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected index ab377e4b3b0..b8152734e2d 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1041/semmle/tests/FindWrapperFunctions.expected @@ -1 +1 @@ -| test.cpp:23:3:23:8 | call to fclose | consider changing the call to $@ | test.cpp:9:6:9:13 | myFclose | myFclose | +| test.cpp:23:3:23:8 | call to fclose | Consider changing the call to $@ | test.cpp:9:6:9:13 | myFclose | myFclose | From 13741ba1374f13a033dcb233d184bf67b00a2bad Mon Sep 17 00:00:00 2001 From: ihsinme <ihsinme@gmail.com> Date: Thu, 23 Sep 2021 12:55:03 +0300 Subject: [PATCH 061/361] Update FindWrapperFunctions.ql --- .../Security/CWE/CWE-1041/FindWrapperFunctions.ql | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql index 1df7babc862..5b609697b73 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql @@ -6,6 +6,7 @@ * @problem.severity warning * @precision medium * @tags correctness + * maintainability * security * external/cwe/cwe-1041 */ @@ -48,7 +49,7 @@ predicate conditionsOutsideWrapper(FunctionCall fcp) { not exists(ExprCall ectmp | fcp = ectmp.getAnArgument().getAChild*()) } -/** Holds if the conditions for a call within the wrapper function are met. */ +/** Held if the conditions for calling `fcp` inside the `fnp` wrapper function are met. */ pragma[inline] predicate conditionsInsideWrapper(FunctionCall fcp, Function fnp) { not exists(FunctionCall fctmp2 | @@ -60,7 +61,7 @@ predicate conditionsInsideWrapper(FunctionCall fcp, Function fnp) { fnp.getNumberOfParameters() > 0 and // the call arguments must be passed through the arguments of the wrapper function forall(int i | i in [0 .. fcp.getNumberOfArguments() - 1] | - fcp.getArgument(i).(VariableAccess).getTarget() = fnp.getAParameter().getAnAccess().getTarget() + globalValueNumber(fcp.getArgument(i)) = globalValueNumber(fnp.getAParameter().getAnAccess()) ) and // there should be no more than one required call inside the wrapper function not exists(FunctionCall fctmp | @@ -119,8 +120,8 @@ predicate conditionsForWrapper(FunctionCall fcp, Function fnp) { forall(int i | i in [0 .. fnp.getNumberOfParameters() - 1] | fnp.getParameter(i).getAnAccess().getTarget() = fcp.getAnArgument().(VariableAccess).getTarget() or - fnp.getParameter(i).getType() instanceof Class or - fnp.getParameter(i).getType().(ReferenceType).getBaseType() instanceof Class or + fnp.getParameter(i).getUnspecifiedType() instanceof Class or + fnp.getParameter(i).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Class or fnp.getParameter(i).getAnAccess().getTarget() = fctmp.getAnArgument().(VariableAccess).getTarget() ) From 0919042692707a2a56d180d3f2bb6eea984434fc Mon Sep 17 00:00:00 2001 From: Joe Farebrother <joefarebrother@github.com> Date: Thu, 23 Sep 2021 12:03:45 +0100 Subject: [PATCH 062/361] Model Bundle and Intent extra methods --- .../code/java/dataflow/ExternalFlow.qll | 1 + .../code/java/frameworks/android/Intent.qll | 124 ++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index bce80a3ee08..679f8704bc9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -78,6 +78,7 @@ private import FlowSummary private module Frameworks { private import internal.ContainerFlow private import semmle.code.java.frameworks.android.XssSinks + private import semmle.code.java.frameworks.android.Intent private import semmle.code.java.frameworks.ApacheHttp private import semmle.code.java.frameworks.apache.Collections private import semmle.code.java.frameworks.apache.Lang diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 92c49f3101a..edb981cff8e 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -1,5 +1,6 @@ import java import semmle.code.java.dataflow.FlowSteps +import semmle.code.java.dataflow.ExternalFlow class TypeIntent extends Class { TypeIntent() { hasQualifiedName("android.content", "Intent") } @@ -52,3 +53,126 @@ class BundleGetterMethod extends Method, TaintPreservingCallable { override predicate returnsTaintFrom(int arg) { arg = -1 } } + +private class IntentBundleFlowSteps extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //"namespace;type;subtypes;name;signature;ext;input;output;kind" + "android.os;BaseBundle;true;get;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;BaseBundle;true;getString;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;BaseBundle;true;getString;(String,String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;BaseBundle;true;getString;(String,String);;Argument[1];ReturnValue;value", + "android.os;BaseBundle;true;getStringArray;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;BaseBundle;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value", + "android.os;BaseBundle;true;putAll;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putAll;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value", + "android.os;BaseBundle;true;putBoolean;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putBooleanArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putDouble;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putDoubleArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putInt;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putIntArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putLong;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putLongArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putString;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putString;;;Argument[1];MapValue of Argument[-1];value", + "android.os;BaseBundle;true;putStringArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;BaseBundle;true;putStringArray;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;getBinder;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getBundle;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getByteArray;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getCharArray;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getCharSequence;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getCharSequence;(String,CharSequence);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getCharSequence;(String,CharSequence);;Argument[1];ReturnValue;value", + "android.os;Bundle;true;getCharSequenceArray;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getCharSequenceArrayList;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getParcelable;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getParcelableArrayList;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getSerializable;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getSparseParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;getStringArrayList;(String);;MapValue of Argument[-1];ReturnValue;value", + "android.os;Bundle;true;putAll;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putAll;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value", + "android.os;Bundle;true;putBinder;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putBinder;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putBundle;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putBundle;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putByte;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putByteArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putByteArray;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putChar;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putCharArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putCharArray;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putCharSequence;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putCharSequence;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putCharSequenceArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putCharSequenceArray;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putCharSequenceArrayList;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putCharSequenceArrayList;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putFloat;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putFloatArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putIntegerArrayList;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putParcelable;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putParcelable;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putParcelableArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putParcelableArray;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putParcelableArrayList;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putParcelableArrayList;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putSerializable;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putSerializable;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putShort;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putShortArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putSize;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putSizeF;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putSparceParcelableArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putSparseParcelableArray;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;putStringArrayList;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint", + "android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint", + "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getCharArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getCharSequenceArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getCharSequenceArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getCharSequenceExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getParcelableArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getParcelableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getSerializableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getStringArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getStringArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getStringExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;putIntegerArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putIntegerArrayListExtra;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;putStringArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putStringArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putStringArrayListExtra;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;putExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtras;(Bundle);;Argument[-1];ReturnValue;value", + "android.content;Intent;true;putExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtras;(Intent);;Argument[-1];ReturnValue;value", + "android.content;Intent;true;replaceExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;replaceExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;replaceExtras;(Bundle);;Argument[-1];ReturnValue;value", + "android.content;Intent;true;replaceExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;replaceExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value" + ] + } +} From 81adb7dd2a73b4e1fd3ac54bf10e9330de258b7e Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 23 Sep 2021 15:28:05 +0200 Subject: [PATCH 063/361] Python: Add tests for `os.path`-functions --- .../library-tests/frameworks/stdlib/FileSystemAccess.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py index bcf6589ef85..ccc2dd76f2c 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py +++ b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py @@ -27,3 +27,10 @@ def through_function(open_file): open_file.write("foo") # $ fileWriteData="foo" getAPathArgument="path" through_function(f) + +from os import path +path.exists("filepath") # $ MISSING: getAPathArgument="filepath" +path.isfile("filepath") # $ MISSING: getAPathArgument="filepath" +path.isdir("filepath") # $ MISSING: getAPathArgument="filepath" +path.islink("filepath") # $ MISSING: getAPathArgument="filepath" +path.ismount("filepath") # $ MISSING: getAPathArgument="filepath" From f2fbeed4903522dcb4f415c18504672006ad46de Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 23 Sep 2021 15:28:33 +0200 Subject: [PATCH 064/361] Python: Model `os.path`-functions --- .../lib/semmle/python/frameworks/Stdlib.qll | 26 +++++++++++++++++++ .../frameworks/stdlib/FileSystemAccess.py | 10 +++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 539f0dcabb0..46f0349de77 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -195,6 +195,32 @@ private module StdlibPrivate { } } + /** + * A call to `os.path.exists` or `os.path.lexists` will check if a file exists on the file system. + * The `os.path` module offers e number of methods for checking if a file exists and/or has certain + * properties, leading to a file system access. + * (Although, on some platforms, the check may return `false` due to missing permissions.) + * See: + * - https://docs.python.org/3/library/os.path.html#os.path.exists + * - https://docs.python.org/3/library/os.path.html#os.path.lexists + * - https://docs.python.org/3/library/os.path.html#os.path.isfile + * - https://docs.python.org/3/library/os.path.html#os.path.isdir + * - https://docs.python.org/3/library/os.path.html#os.path.islink + * - https://docs.python.org/3/library/os.path.html#os.path.ismount + */ + private class OsPathProbingCall extends FileSystemAccess::Range, DataFlow::CallCfgNode { + OsPathProbingCall() { + this = + os::path() + .getMember(["exists", "lexists", "isfile", "isdir", "islink", "ismount"]) + .getACall() + } + + override DataFlow::Node getAPathArgument() { + result in [this.getArg(0), this.getArgByName("path")] + } + } + /** * A call to `os.path.normpath`. * See https://docs.python.org/3/library/os.path.html#os.path.normpath diff --git a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py index ccc2dd76f2c..64f8ad5010d 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py +++ b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py @@ -29,8 +29,8 @@ def through_function(open_file): through_function(f) from os import path -path.exists("filepath") # $ MISSING: getAPathArgument="filepath" -path.isfile("filepath") # $ MISSING: getAPathArgument="filepath" -path.isdir("filepath") # $ MISSING: getAPathArgument="filepath" -path.islink("filepath") # $ MISSING: getAPathArgument="filepath" -path.ismount("filepath") # $ MISSING: getAPathArgument="filepath" +path.exists("filepath") # $ getAPathArgument="filepath" +path.isfile("filepath") # $ getAPathArgument="filepath" +path.isdir("filepath") # $ getAPathArgument="filepath" +path.islink("filepath") # $ getAPathArgument="filepath" +path.ismount("filepath") # $ getAPathArgument="filepath" From 9b969e15fc82e878ade65c93805792af519ccb04 Mon Sep 17 00:00:00 2001 From: haby0 <ha_yub@163.com> Date: Fri, 24 Sep 2021 12:56:10 +0800 Subject: [PATCH 065/361] Modify according to @yoff suggestion --- .../ClientSuppliedIpUsedInSecurityCheck.ql | 4 +- ...ClientSuppliedIpUsedInSecurityCheckLib.qll | 85 ++++++++++--------- 2 files changed, 46 insertions(+), 43 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql index 1c96a10d531..270a0444cfb 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql @@ -27,9 +27,7 @@ class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configura source instanceof ClientSuppliedIpUsedInSecurityCheck } - override predicate isSink(DataFlow::Node sink) { - sink instanceof ClientSuppliedIpUsedInSecurityCheckSink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof PossibleSecurityCheck } override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { exists(DataFlow::CallCfgNode ccn | diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll index 82da4f5b46f..97e9bbfd457 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll @@ -14,55 +14,60 @@ abstract class ClientSuppliedIpUsedInSecurityCheck extends DataFlow::CallCfgNode private class FlaskClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { FlaskClientSuppliedIpUsedInSecurityCheck() { - this = - API::moduleImport("flask") - .getMember("request") - .getMember("headers") - .getMember(["get", "get_all", "getlist"]) - .getACall() and - this.getArg(0).asCfgNode().getNode().(StrConst).getText().toLowerCase() = - clientIpParameterName() + exists(RemoteFlowSource rfs, DataFlow::AttrRead get | + rfs.getSourceType() = "flask.request" and this.getFunction() = get + | + // `get` is a call to request.headers.get or request.headers.get_all or request.headers.getlist + // request.headers + get.getObject() + .(DataFlow::AttrRead) + // request + .getObject() + .getALocalSource() = rfs and + get.getAttributeName() in ["get", "get_all", "getlist"] and + get.getObject().(DataFlow::AttrRead).getAttributeName() = "headers" and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() + ) } } private class DjangoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { DjangoClientSuppliedIpUsedInSecurityCheck() { - exists(RemoteFlowSource rfs, DataFlow::LocalSourceNode lsn | - rfs.getSourceType() = "django.http.request.HttpRequest" and rfs.asCfgNode() = lsn.asCfgNode() + exists(RemoteFlowSource rfs, DataFlow::AttrRead get | + rfs.getSourceType() = "django.http.request.HttpRequest" and this.getFunction() = get | - lsn.flowsTo(DataFlow::exprNode(this.getFunction() - .asExpr() - .(Attribute) - .getObject() - .(Attribute) - .getObject())) and - this.getFunction().asExpr().(Attribute).getName() = "get" and - this.getFunction().asExpr().(Attribute).getObject().(Attribute).getName() in [ - "headers", "META" - ] and - this.getArg(0).asCfgNode().getNode().(StrConst).getText().toLowerCase() = - clientIpParameterName() + // `get` is a call to request.headers.get or request.META.get + // request.headers + get.getObject() + .(DataFlow::AttrRead) + // request + .getObject() + .getALocalSource() = rfs and + get.getAttributeName() = "get" and + get.getObject().(DataFlow::AttrRead).getAttributeName() in ["headers", "META"] and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() ) } } private class TornadoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { TornadoClientSuppliedIpUsedInSecurityCheck() { - exists(RemoteFlowSource rfs, DataFlow::LocalSourceNode lsn | - rfs.getSourceType() = "tornado.web.RequestHandler" and rfs.asCfgNode() = lsn.asCfgNode() + exists(RemoteFlowSource rfs, DataFlow::AttrRead get | + rfs.getSourceType() = "tornado.web.RequestHandler" and this.getFunction() = get | - lsn.flowsTo(DataFlow::exprNode(this.getFunction() - .asExpr() - .(Attribute) - .getObject() - .(Attribute) - .getObject() - .(Attribute) - .getObject())) and - this.getFunction().asExpr().(Attribute).getName() in ["get", "get_list"] and - this.getFunction().asExpr().(Attribute).getObject().(Attribute).getName() = "headers" and - this.getArg(0).asCfgNode().getNode().(StrConst).getText().toLowerCase() = - clientIpParameterName() + // `get` is a call to `rfs`.request.headers.get + // `rfs`.request.headers + get.getObject() + .(DataFlow::AttrRead) + // `rfs`.request + .getObject() + .(DataFlow::AttrRead) + // `rfs` + .getObject() + .getALocalSource() = rfs and + get.getAttributeName() in ["get", "get_list"] and + get.getObject().(DataFlow::AttrRead).getAttributeName() = "headers" and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() ) } } @@ -77,11 +82,11 @@ private string clientIpParameterName() { } /** A data flow sink for ip address forgery vulnerabilities. */ -abstract class ClientSuppliedIpUsedInSecurityCheckSink extends DataFlow::Node { } +abstract class PossibleSecurityCheck extends DataFlow::Node { } /** A data flow sink for sql operation. */ -private class SqlOperationSink extends ClientSuppliedIpUsedInSecurityCheckSink { - SqlOperationSink() { this = any(SqlExecution e).getSql() } +private class SqlOperationAsSecurityCheck extends PossibleSecurityCheck { + SqlOperationAsSecurityCheck() { this = any(SqlExecution e).getSql() } } /** @@ -90,7 +95,7 @@ private class SqlOperationSink extends ClientSuppliedIpUsedInSecurityCheckSink { * For example: `if not ipAddr.startswith('192.168.') : ...` determine whether the client ip starts * with `192.168.`, and the program can be deceived by forging the ip address. */ -private class CompareSink extends ClientSuppliedIpUsedInSecurityCheckSink { +private class CompareSink extends PossibleSecurityCheck { CompareSink() { exists(Call call | call.getFunc().(Attribute).getName() = "startswith" and From 49f8f463541d22b9fe541e384218a18ff7243239 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Fri, 17 Sep 2021 18:15:47 +0100 Subject: [PATCH 066/361] Java: Cache params string computation. --- java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index bce80a3ee08..9c46291c58f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -638,6 +638,7 @@ private string paramsStringPart(Callable c, int i) { * Returns the empty string if the callable has no parameters. * Parameter types are represented by their type erasure. */ +cached string paramsString(Callable c) { result = concat(int i | | paramsStringPart(c, i) order by i) } private Element interpretElement0( From 9f59bc8f7bccbb298bd84a0a5682580c6e3d788c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 24 Sep 2021 14:35:10 +0100 Subject: [PATCH 067/361] C++: Naive translation to use RemoteFlow*Function. --- .../CWE/CWE-311/CleartextTransmission.ql | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index c130c9a49b6..70d0b472d66 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -14,6 +14,7 @@ import cpp import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.models.interfaces.FlowSource import DataFlow::PathGraph /** @@ -38,30 +39,38 @@ abstract class NetworkSendRecv extends FunctionCall { * note: functions such as `write` may be writing to a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it usually isn't very important which query reports a result as long as its reported exactly once. */ class NetworkSend extends NetworkSendRecv { - NetworkSend() { - this.getTarget() - .hasGlobalName(["send", "sendto", "sendmsg", "write", "writev", "pwritev", "pwritev2"]) - } + RemoteFlowSinkFunction target; + + NetworkSend() { target = this.getTarget() } override Expr getSocketExpr() { result = this.getArgument(0) } - override Expr getDataExpr() { result = this.getArgument(1) } + override Expr getDataExpr() { + exists(FunctionInput input, int arg | + target.hasRemoteFlowSink(input, _) and + input.isParameterDeref(arg) and + result = this.getArgument(arg) + ) + } } /** * A function call that receives data over a network. */ class NetworkRecv extends NetworkSendRecv { - NetworkRecv() { - this.getTarget() - .hasGlobalName([ - "recv", "recvfrom", "recvmsg", "read", "pread", "readv", "preadv", "preadv2" - ]) - } + RemoteFlowSourceFunction target; + + NetworkRecv() { target = this.getTarget() } override Expr getSocketExpr() { result = this.getArgument(0) } - override Expr getDataExpr() { result = this.getArgument(1) } + override Expr getDataExpr() { + exists(FunctionOutput output, int arg | + target.hasRemoteFlowSource(output, _) and + output.isParameterDeref(arg) and + result = this.getArgument(arg) + ) + } } /** @@ -76,7 +85,6 @@ class SensitiveSendRecvConfiguration extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { exists(NetworkSendRecv transmission | sink.asExpr() = transmission.getDataExpr() and - // a zero file descriptor is standard input, which is not interesting for this query. not exists(Zero zero | DataFlow::localFlow(DataFlow::exprNode(zero), From 6901d9d9c254c9c825270f6052bd9922db751696 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 24 Sep 2021 14:55:28 +0100 Subject: [PATCH 068/361] C++: Add and use getRemoteSocket predicates. --- .../code/cpp/models/implementations/Recv.qll | 4 ++++ .../code/cpp/models/implementations/Send.qll | 4 ++++ .../code/cpp/models/interfaces/FlowSource.qll | 12 ++++++++++++ .../CWE/CWE-311/CleartextTransmission.ql | 18 +++++++++++++++--- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll index 691ba528f42..de4d470ce1f 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll @@ -85,4 +85,8 @@ private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, ) and description = "Buffer read by " + this.getName() } + + override predicate hasSocketInput(FunctionInput input) { + input.isParameter(0) + } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll index 6086bc7748f..e747d8182b7 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll @@ -60,4 +60,8 @@ private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, Rem override predicate hasRemoteFlowSink(FunctionInput input, string description) { input.isParameterDeref(1) and description = "Buffer sent by " + this.getName() } + + override predicate hasSocketInput(FunctionInput input) { + input.isParameter(0) + } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll index 8c80377c8ec..d454257ea86 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll @@ -18,6 +18,12 @@ abstract class RemoteFlowSourceFunction extends Function { * Holds if remote data described by `description` flows from `output` of a call to this function. */ abstract predicate hasRemoteFlowSource(FunctionOutput output, string description); + + /** + * Holds if remote data from this source comes from a socket described by + * `input`. There is no result if a socket is not specified. + */ + predicate hasSocketInput(FunctionInput input) { none() } } /** @@ -51,4 +57,10 @@ abstract class RemoteFlowSinkFunction extends Function { * send over a network connection. */ abstract predicate hasRemoteFlowSink(FunctionInput input, string description); + + /** + * Holds if data put into this sink is transmitted through a socket described + * by `input`. There is no result if a socket is not specified. + */ + predicate hasSocketInput(FunctionInput input) { none() } } diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 70d0b472d66..70b00aecd6d 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -43,7 +43,13 @@ class NetworkSend extends NetworkSendRecv { NetworkSend() { target = this.getTarget() } - override Expr getSocketExpr() { result = this.getArgument(0) } + override Expr getSocketExpr() { + exists(FunctionInput input, int arg | + target.hasSocketInput(input) and + input.isParameter(arg) and + result = this.getArgument(arg) + ) + } override Expr getDataExpr() { exists(FunctionInput input, int arg | @@ -62,7 +68,13 @@ class NetworkRecv extends NetworkSendRecv { NetworkRecv() { target = this.getTarget() } - override Expr getSocketExpr() { result = this.getArgument(0) } + override Expr getSocketExpr() { + exists(FunctionInput input, int arg | + target.hasSocketInput(input) and + input.isParameter(arg) and + result = this.getArgument(arg) + ) + } override Expr getDataExpr() { exists(FunctionOutput output, int arg | @@ -85,7 +97,7 @@ class SensitiveSendRecvConfiguration extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { exists(NetworkSendRecv transmission | sink.asExpr() = transmission.getDataExpr() and - // a zero file descriptor is standard input, which is not interesting for this query. + // a zero socket descriptor is standard input, which is not interesting for this query. not exists(Zero zero | DataFlow::localFlow(DataFlow::exprNode(zero), DataFlow::exprNode(transmission.getSocketExpr())) From ded30885293f934e6d4d3436a5789de43f7260d7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 27 Sep 2021 12:08:40 +0200 Subject: [PATCH 069/361] Python/JS: Recognize SHA-3 hash functions Official names are SHA3-224, SHA3-256, SHA3-384, SHA3-512 as per https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf --- .../semmle/javascript/security/CryptoAlgorithms.qll | 6 +++++- .../ql/lib/semmle/python/concepts/CryptoAlgorithms.qll | 6 +++++- .../test/library-tests/frameworks/crypto/test_sha3.py | 10 ++++++++++ .../library-tests/frameworks/cryptodome/test_sha3.py | 10 ++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 python/ql/test/library-tests/frameworks/crypto/test_sha3.py create mode 100644 python/ql/test/library-tests/frameworks/cryptodome/test_sha3.py diff --git a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll index d9f25b42c9a..a5bfd6696be 100644 --- a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll +++ b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll @@ -28,7 +28,11 @@ private module AlgorithmNames { name = "SHA256" or name = "SHA384" or name = "SHA512" or - name = "SHA3" + name = "SHA3" or + name = "SHA3224" or + name = "SHA3256" or + name = "SHA3384" or + name = "SHA3512" } predicate isWeakHashingAlgorithm(string name) { diff --git a/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll index d9f25b42c9a..a5bfd6696be 100644 --- a/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll +++ b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll @@ -28,7 +28,11 @@ private module AlgorithmNames { name = "SHA256" or name = "SHA384" or name = "SHA512" or - name = "SHA3" + name = "SHA3" or + name = "SHA3224" or + name = "SHA3256" or + name = "SHA3384" or + name = "SHA3512" } predicate isWeakHashingAlgorithm(string name) { diff --git a/python/ql/test/library-tests/frameworks/crypto/test_sha3.py b/python/ql/test/library-tests/frameworks/crypto/test_sha3.py new file mode 100644 index 00000000000..426d0266fc4 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/crypto/test_sha3.py @@ -0,0 +1,10 @@ +from Crypto.Hash import SHA3_224 + +hasher = SHA3_224.new(b"secret message") # $ CryptographicOperation CryptographicOperationInput=b"secret message" CryptographicOperationAlgorithm=SHA3224 +print(hasher.hexdigest()) + + +hasher = SHA3_224.new() # $ CryptographicOperation CryptographicOperationAlgorithm=SHA3224 +hasher.update(b"secret") # $ CryptographicOperation CryptographicOperationInput=b"secret" CryptographicOperationAlgorithm=SHA3224 +hasher.update(b" message") # $ CryptographicOperation CryptographicOperationInput=b" message" CryptographicOperationAlgorithm=SHA3224 +print(hasher.hexdigest()) diff --git a/python/ql/test/library-tests/frameworks/cryptodome/test_sha3.py b/python/ql/test/library-tests/frameworks/cryptodome/test_sha3.py new file mode 100644 index 00000000000..2329fd7e1c0 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/cryptodome/test_sha3.py @@ -0,0 +1,10 @@ +from Cryptodome.Hash import SHA3_224 + +hasher = SHA3_224.new(b"secret message") # $ CryptographicOperation CryptographicOperationInput=b"secret message" CryptographicOperationAlgorithm=SHA3224 +print(hasher.hexdigest()) + + +hasher = SHA3_224.new() # $ CryptographicOperation CryptographicOperationAlgorithm=SHA3224 +hasher.update(b"secret") # $ CryptographicOperation CryptographicOperationInput=b"secret" CryptographicOperationAlgorithm=SHA3224 +hasher.update(b" message") # $ CryptographicOperation CryptographicOperationInput=b" message" CryptographicOperationAlgorithm=SHA3224 +print(hasher.hexdigest()) From 9a9bbe3123d8670e93cf2d91ea920d9370883492 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Mon, 20 Sep 2021 14:22:50 +0200 Subject: [PATCH 070/361] Dataflow: Support side-effects for callbacks in summaries. --- .../dataflow/internal/FlowSummaryImpl.qll | 108 ++++++++++++------ .../internal/FlowSummaryImplSpecific.qll | 5 + .../dataflow/callback-dispatch/A.java | 59 ++++++++++ .../dataflow/callback-dispatch/test.ql | 4 + 4 files changed, 144 insertions(+), 32 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 523516e60f8..f76baca5b8a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -186,10 +186,15 @@ module Private { TArgumentSummaryComponent(int i) { parameterPosition(i) } or TReturnSummaryComponent(ReturnKind rk) + private TSummaryComponent thisParam() { result = TParameterSummaryComponent(instanceParameterPosition()) } + newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or TConsSummaryComponentStack(SummaryComponent head, SummaryComponentStack tail) { tail.(RequiredSummaryComponentStack).required(head) + or + tail.(RequiredSummaryComponentStack).required(TParameterSummaryComponent(_)) and + head = thisParam() } pragma[nomagic] @@ -198,21 +203,63 @@ module Private { boolean preservesValue ) { c.propagatesFlow(input, output, preservesValue) + or + // observe side effects of callbacks on input arguments + c.propagatesFlow(output, input, preservesValue) and + preservesValue = true and + isCallbackParameter(input) and + isContentOfArgument(output) + or + // flow from the receiver of a callback into the instance-parameter + exists(SummaryComponentStack s, SummaryComponentStack callbackRef | + c.propagatesFlow(s, _, _) or c.propagatesFlow(_, s, _) + | + callbackRef = s.drop(_) and + (isCallbackParameter(callbackRef) or callbackRef.head() = TReturnSummaryComponent(_)) and + input = callbackRef.tail() and + output = TConsSummaryComponentStack(thisParam(), input) and + preservesValue = true + ) + } + + private predicate isCallbackParameter(SummaryComponentStack s) { + s.head() = TParameterSummaryComponent(_) and exists(s.tail()) + } + + private predicate isContentOfArgument(SummaryComponentStack s) { + s.head() = TContentSummaryComponent(_) and isContentOfArgument(s.tail()) + or + s = TSingletonSummaryComponentStack(TArgumentSummaryComponent(_)) + } + + private predicate outputState(SummarizedCallable c, SummaryComponentStack s) { + summary(c, _, s, _) + or + exists(SummaryComponentStack out | + outputState(c, out) and + out.head() = TContentSummaryComponent(_) and + s = out.tail() + ) + or + // Add the argument node corresponding to the requested post-update node + inputState(c, s) and isCallbackParameter(s) + } + + private predicate inputState(SummarizedCallable c, SummaryComponentStack s) { + summary(c, s, _, _) + or + exists(SummaryComponentStack inp | inputState(c, inp) and s = inp.tail()) + or + exists(SummaryComponentStack out | + outputState(c, out) and + out.head() = TParameterSummaryComponent(_) and + s = out.tail() + ) } private newtype TSummaryNodeState = - TSummaryNodeInputState(SummaryComponentStack s) { - exists(SummaryComponentStack input | - summary(_, input, _, _) and - s = input.drop(_) - ) - } or - TSummaryNodeOutputState(SummaryComponentStack s) { - exists(SummaryComponentStack output | - summary(_, _, output, _) and - s = output.drop(_) - ) - } + TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or + TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } /** * A state used to break up (complex) flow summaries into atomic flow steps. @@ -238,20 +285,14 @@ module Private { pragma[nomagic] predicate isInputState(SummarizedCallable c, SummaryComponentStack s) { this = TSummaryNodeInputState(s) and - exists(SummaryComponentStack input | - summary(c, input, _, _) and - s = input.drop(_) - ) + inputState(c, s) } /** Holds if this state is a valid output state for `c`. */ pragma[nomagic] predicate isOutputState(SummarizedCallable c, SummaryComponentStack s) { this = TSummaryNodeOutputState(s) and - exists(SummaryComponentStack output | - summary(c, _, output, _) and - s = output.drop(_) - ) + outputState(c, s) } /** Gets a textual representation of this state. */ @@ -331,19 +372,12 @@ module Private { receiver = summaryNodeInputState(c, s.drop(1)) } - private Node pre(Node post) { - summaryPostUpdateNode(post, result) - or - not summaryPostUpdateNode(post, _) and - result = post - } - private predicate callbackInput( SummarizedCallable c, SummaryComponentStack s, Node receiver, int i ) { any(SummaryNodeState state).isOutputState(c, s) and s.head() = TParameterSummaryComponent(i) and - receiver = pre(summaryNodeOutputState(c, s.drop(1))) + receiver = summaryNodeInputState(c, s.drop(1)) } /** Holds if a call targeting `receiver` should be synthesized inside `c`. */ @@ -395,7 +429,7 @@ module Private { or exists(int i | head = TParameterSummaryComponent(i) | result = - getCallbackParameterType(getNodeType(summaryNodeOutputState(pragma[only_bind_out](c), + getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c), s.drop(1))), i) ) ) @@ -421,10 +455,16 @@ module Private { } /** Holds if summary node `post` is a post-update node with pre-update node `pre`. */ - predicate summaryPostUpdateNode(Node post, ParamNode pre) { + predicate summaryPostUpdateNode(Node post, Node pre) { exists(SummarizedCallable c, int i | isParameterPostUpdate(post, c, i) and - pre.isParameterOf(c, i) + pre.(ParamNode).isParameterOf(c, i) + ) + or + exists(SummarizedCallable callable, SummaryComponentStack s | + callbackInput(callable, s, _, _) and + pre = summaryNodeOutputState(callable, s) and + post = summaryNodeInputState(callable, s) ) } @@ -462,7 +502,11 @@ module Private { // for `StringBuilder.append(x)` with a specified value flow from qualifier to // return value and taint flow from argument 0 to the qualifier, then this // allows us to infer taint flow from argument 0 to the return value. - summaryPostUpdateNode(pred, succ) and preservesValue = true + succ instanceof ParamNode and summaryPostUpdateNode(pred, succ) and preservesValue = true + or + // Similarly we would like to chain together summaries where values get passed + // into callbacks along the way. + pred instanceof ArgNode and summaryPostUpdateNode(succ, pred) and preservesValue = true } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll index d3a4612255d..e4c3091f05e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll @@ -16,6 +16,9 @@ private module FlowSummaries { /** Holds is `i` is a valid parameter position. */ predicate parameterPosition(int i) { i in [-1 .. any(Parameter p).getPosition()] } +/** Gets the parameter position of the instance parameter. */ +int instanceParameterPosition() { result = -1 } + /** Gets the synthesized summary data-flow node for the given values. */ Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = getSummaryNode(c, state) } @@ -37,6 +40,8 @@ DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { */ DataFlowType getCallbackParameterType(DataFlowType t, int i) { result = getErasedRepr(t.(FunctionalInterface).getRunMethod().getParameterType(i)) + or + result = getErasedRepr(t.(FunctionalInterface)) and i = -1 } /** diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java index 4a4f0b11ded..6224a2e3d95 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java @@ -1,5 +1,7 @@ package my.callback.qltest; +import java.util.*; + public class A { public interface Consumer1 { void eat(Object o); @@ -28,6 +30,20 @@ public class A { // con.eat(x); } + static <T> T applyConsumer3_ret_postup(Consumer3<T> con) { + // summary: + // x = new T(); + // con.eat(x); + // return x; + return null; + } + + static <T> void forEach(T[] xs, Consumer3<T> con) { + // summary: + // x = xs[..]; + // con.eat(x); + } + public interface Producer1<T> { T make(); } @@ -38,6 +54,14 @@ public class A { return null; } + static <T> T produceConsume(Producer1<T> prod, Consumer3<T> con) { + // summary: + // x = prod.make(); + // con.eat(x); + // return x; + return null; + } + public interface Converter1<T1,T2> { T2 conv(T1 x); } @@ -109,5 +133,40 @@ public class A { }; applyConsumer3(new Integer[] { (Integer)source(12) }, pc); sink(applyProducer1(pc)[0]); // $ flow=11 + + Integer res = applyProducer1(new Producer1<Integer>() { + private Integer ii = (Integer)source(13); + @Override public Integer make() { + return this.ii; + } + }); + sink(res); // $ flow=13 + + ArrayList<Object> list = new ArrayList<>(); + applyConsumer3(list, l -> l.add(source(14))); + sink(list.get(0)); // $ flow=14 + + Consumer3<ArrayList<Object>> tainter = l -> l.add(source(15)); + sink(applyConsumer3_ret_postup(tainter).get(0)); // $ flow=15 + + forEach(new Object[] {source(16)}, x -> sink(x)); // $ flow=16 + + // Spurious flow from 17 is reasonable as it would likely + // also occur if the lambda body was inlined in a for loop. + // It occurs from the combination of being able to observe + // the side-effect of the callback on the other argument and + // being able to chain summaries that update/read arguments, + // e.g. fluent apis. + // Spurious flow from 18 is due to not matching call targets + // in a return-from-call-to-enter-call flow sequence. + forEach(new Object[2][], xs -> { sink(xs[0]); xs[0] = source(17); }); // $ SPURIOUS: flow=17 flow=18 + + Object[][] xss = new Object[][] { { null } }; + forEach(xss, x -> {x[0] = source(18);}); + sink(xss[0][0]); // $ flow=18 + + Object res2 = produceConsume(() -> source(19), A::sink); // $ flow=19 + sink(res2); // $ flow=19 } + } diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/test.ql b/java/ql/test/library-tests/dataflow/callback-dispatch/test.ql index 934bdcfac28..63eeee53823 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/test.ql +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/test.ql @@ -10,7 +10,11 @@ class SummaryModelTest extends SummaryModelCsv { "my.callback.qltest;A;false;applyConsumer1;(Object,Consumer1);;Argument[0];Parameter[0] of Argument[1];value", "my.callback.qltest;A;false;applyConsumer2;(Object,Consumer2);;Argument[0];Parameter[0] of Argument[1];value", "my.callback.qltest;A;false;applyConsumer3;(Object,Consumer3);;Argument[0];Parameter[0] of Argument[1];value", + "my.callback.qltest;A;false;applyConsumer3_ret_postup;(Consumer3);;Parameter[0] of Argument[0];ReturnValue;value", + "my.callback.qltest;A;false;forEach;(Object[],Consumer3);;ArrayElement of Argument[0];Parameter[0] of Argument[1];value", "my.callback.qltest;A;false;applyProducer1;(Producer1);;ReturnValue of Argument[0];ReturnValue;value", + "my.callback.qltest;A;false;produceConsume;(Producer1,Consumer3);;ReturnValue of Argument[0];Parameter[0] of Argument[1];value", + "my.callback.qltest;A;false;produceConsume;(Producer1,Consumer3);;Parameter[0] of Argument[1];ReturnValue;value", "my.callback.qltest;A;false;applyConverter1;(Object,Converter1);;Argument[0];Parameter[0] of Argument[1];value", "my.callback.qltest;A;false;applyConverter1;(Object,Converter1);;ReturnValue of Argument[1];ReturnValue;value" ] From b11cb88a9ffe11e1683e21d465fb7747ffc58ed3 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Tue, 28 Sep 2021 11:45:33 +0200 Subject: [PATCH 071/361] Dataflow: Sync to C#. --- .../dataflow/internal/FlowSummaryImpl.qll | 108 ++++++++++++------ .../internal/FlowSummaryImplSpecific.qll | 3 + 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 523516e60f8..f76baca5b8a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -186,10 +186,15 @@ module Private { TArgumentSummaryComponent(int i) { parameterPosition(i) } or TReturnSummaryComponent(ReturnKind rk) + private TSummaryComponent thisParam() { result = TParameterSummaryComponent(instanceParameterPosition()) } + newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or TConsSummaryComponentStack(SummaryComponent head, SummaryComponentStack tail) { tail.(RequiredSummaryComponentStack).required(head) + or + tail.(RequiredSummaryComponentStack).required(TParameterSummaryComponent(_)) and + head = thisParam() } pragma[nomagic] @@ -198,21 +203,63 @@ module Private { boolean preservesValue ) { c.propagatesFlow(input, output, preservesValue) + or + // observe side effects of callbacks on input arguments + c.propagatesFlow(output, input, preservesValue) and + preservesValue = true and + isCallbackParameter(input) and + isContentOfArgument(output) + or + // flow from the receiver of a callback into the instance-parameter + exists(SummaryComponentStack s, SummaryComponentStack callbackRef | + c.propagatesFlow(s, _, _) or c.propagatesFlow(_, s, _) + | + callbackRef = s.drop(_) and + (isCallbackParameter(callbackRef) or callbackRef.head() = TReturnSummaryComponent(_)) and + input = callbackRef.tail() and + output = TConsSummaryComponentStack(thisParam(), input) and + preservesValue = true + ) + } + + private predicate isCallbackParameter(SummaryComponentStack s) { + s.head() = TParameterSummaryComponent(_) and exists(s.tail()) + } + + private predicate isContentOfArgument(SummaryComponentStack s) { + s.head() = TContentSummaryComponent(_) and isContentOfArgument(s.tail()) + or + s = TSingletonSummaryComponentStack(TArgumentSummaryComponent(_)) + } + + private predicate outputState(SummarizedCallable c, SummaryComponentStack s) { + summary(c, _, s, _) + or + exists(SummaryComponentStack out | + outputState(c, out) and + out.head() = TContentSummaryComponent(_) and + s = out.tail() + ) + or + // Add the argument node corresponding to the requested post-update node + inputState(c, s) and isCallbackParameter(s) + } + + private predicate inputState(SummarizedCallable c, SummaryComponentStack s) { + summary(c, s, _, _) + or + exists(SummaryComponentStack inp | inputState(c, inp) and s = inp.tail()) + or + exists(SummaryComponentStack out | + outputState(c, out) and + out.head() = TParameterSummaryComponent(_) and + s = out.tail() + ) } private newtype TSummaryNodeState = - TSummaryNodeInputState(SummaryComponentStack s) { - exists(SummaryComponentStack input | - summary(_, input, _, _) and - s = input.drop(_) - ) - } or - TSummaryNodeOutputState(SummaryComponentStack s) { - exists(SummaryComponentStack output | - summary(_, _, output, _) and - s = output.drop(_) - ) - } + TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or + TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } /** * A state used to break up (complex) flow summaries into atomic flow steps. @@ -238,20 +285,14 @@ module Private { pragma[nomagic] predicate isInputState(SummarizedCallable c, SummaryComponentStack s) { this = TSummaryNodeInputState(s) and - exists(SummaryComponentStack input | - summary(c, input, _, _) and - s = input.drop(_) - ) + inputState(c, s) } /** Holds if this state is a valid output state for `c`. */ pragma[nomagic] predicate isOutputState(SummarizedCallable c, SummaryComponentStack s) { this = TSummaryNodeOutputState(s) and - exists(SummaryComponentStack output | - summary(c, _, output, _) and - s = output.drop(_) - ) + outputState(c, s) } /** Gets a textual representation of this state. */ @@ -331,19 +372,12 @@ module Private { receiver = summaryNodeInputState(c, s.drop(1)) } - private Node pre(Node post) { - summaryPostUpdateNode(post, result) - or - not summaryPostUpdateNode(post, _) and - result = post - } - private predicate callbackInput( SummarizedCallable c, SummaryComponentStack s, Node receiver, int i ) { any(SummaryNodeState state).isOutputState(c, s) and s.head() = TParameterSummaryComponent(i) and - receiver = pre(summaryNodeOutputState(c, s.drop(1))) + receiver = summaryNodeInputState(c, s.drop(1)) } /** Holds if a call targeting `receiver` should be synthesized inside `c`. */ @@ -395,7 +429,7 @@ module Private { or exists(int i | head = TParameterSummaryComponent(i) | result = - getCallbackParameterType(getNodeType(summaryNodeOutputState(pragma[only_bind_out](c), + getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c), s.drop(1))), i) ) ) @@ -421,10 +455,16 @@ module Private { } /** Holds if summary node `post` is a post-update node with pre-update node `pre`. */ - predicate summaryPostUpdateNode(Node post, ParamNode pre) { + predicate summaryPostUpdateNode(Node post, Node pre) { exists(SummarizedCallable c, int i | isParameterPostUpdate(post, c, i) and - pre.isParameterOf(c, i) + pre.(ParamNode).isParameterOf(c, i) + ) + or + exists(SummarizedCallable callable, SummaryComponentStack s | + callbackInput(callable, s, _, _) and + pre = summaryNodeOutputState(callable, s) and + post = summaryNodeInputState(callable, s) ) } @@ -462,7 +502,11 @@ module Private { // for `StringBuilder.append(x)` with a specified value flow from qualifier to // return value and taint flow from argument 0 to the qualifier, then this // allows us to infer taint flow from argument 0 to the return value. - summaryPostUpdateNode(pred, succ) and preservesValue = true + succ instanceof ParamNode and summaryPostUpdateNode(pred, succ) and preservesValue = true + or + // Similarly we would like to chain together summaries where values get passed + // into callbacks along the way. + pred instanceof ArgNode and summaryPostUpdateNode(succ, pred) and preservesValue = true } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll index b0f67e8692f..822822a24c6 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll @@ -16,6 +16,9 @@ private import semmle.code.csharp.dataflow.ExternalFlow /** Holds is `i` is a valid parameter position. */ predicate parameterPosition(int i) { i in [-1 .. any(Parameter p).getPosition()] } +/** Gets the parameter position of the instance parameter. */ +int instanceParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks + /** Gets the synthesized summary data-flow node for the given values. */ Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) } From e95dc8208747a7c1e24d441e4dec3c5ed647db81 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Tue, 28 Sep 2021 13:00:50 +0200 Subject: [PATCH 072/361] Autoformat. --- .../semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll | 4 +++- .../semmle/code/java/dataflow/internal/FlowSummaryImpl.qll | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index f76baca5b8a..8bca0699e04 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -186,7 +186,9 @@ module Private { TArgumentSummaryComponent(int i) { parameterPosition(i) } or TReturnSummaryComponent(ReturnKind rk) - private TSummaryComponent thisParam() { result = TParameterSummaryComponent(instanceParameterPosition()) } + private TSummaryComponent thisParam() { + result = TParameterSummaryComponent(instanceParameterPosition()) + } newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index f76baca5b8a..8bca0699e04 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -186,7 +186,9 @@ module Private { TArgumentSummaryComponent(int i) { parameterPosition(i) } or TReturnSummaryComponent(ReturnKind rk) - private TSummaryComponent thisParam() { result = TParameterSummaryComponent(instanceParameterPosition()) } + private TSummaryComponent thisParam() { + result = TParameterSummaryComponent(instanceParameterPosition()) + } newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or From 10323ac819f930b3503f0899cf666e1798ceb5ec Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 28 Sep 2021 15:13:29 +0100 Subject: [PATCH 073/361] Update cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp Co-authored-by: Jonas Jensen <jbj@github.com> --- cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp b/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp index 47540e6cf3a..f5e978e05cb 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp @@ -9,7 +9,7 @@ storage.</p> </overview> <recommendation> -<p>Ensure that sensitive information is always encrypted before being stored or transmitted, especially before writing to a file. +<p>Ensure that sensitive information is always encrypted before being stored to a file or transmitted over the network. It may be wise to encrypt information before it is put into a buffer that may be readable in memory.</p> <p>In general, decrypt sensitive information only at the point where it is necessary for it to be used in From 89098f54be7c09a23af7defbb4a7d4086c88903c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 28 Sep 2021 16:03:04 +0100 Subject: [PATCH 074/361] C++: Correct comment. --- cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 70b00aecd6d..d7e5343d6dc 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -23,7 +23,7 @@ import DataFlow::PathGraph abstract class NetworkSendRecv extends FunctionCall { /** * Gets the expression for the socket or similar object used for sending or - * receiving data. + * receiving data (if any). */ abstract Expr getSocketExpr(); From 5317022d2ea7af5b0c59f058d871ecce04e2eecd Mon Sep 17 00:00:00 2001 From: Calum Grant <calumgrant@github.com> Date: Tue, 28 Sep 2021 20:51:21 +0100 Subject: [PATCH 075/361] Basic query for Ruby --- .../basic-query-for-ruby-code.rst | 146 ++++++++++++++++++ .../codeql/reusables/ruby-further-reading.rst | 3 + 2 files changed, 149 insertions(+) create mode 100644 docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst create mode 100644 docs/codeql/reusables/ruby-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst new file mode 100644 index 00000000000..a48933fc4cf --- /dev/null +++ b/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst @@ -0,0 +1,146 @@ +.. _basic-query-for-ruby-code: + +Basic query for Ruby code +========================= + +Learn to write and run a simple CodeQL query using CodeQL. + +About the query +--------------- + +The query we're going to run performs a basic search of the code for ``if`` expressions that are redundant, in the sense that they have an empty ``then`` branch. For example, code such as: + +.. code-block:: ruby + + if error + # Handle the error + +Running the query +----------------- + +#. In the main search box on LGTM.com, search for the project you want to query. For tips, see `Searching <https://lgtm.com/help/lgtm/searching>`__. + +#. Click the project in the search results. + +#. Click **Query this project**. + + This opens the query console. (For information about using this, see `Using the query console <https://lgtm.com/help/lgtm/using-query-console>`__.) + + .. pull-quote:: + + Note + + Alternatively, you can go straight to the query console by clicking **Query console** (at the top of any page), selecting **Ruby** from the **Language** drop-down list, then choosing one or more projects to query from those displayed in the **Project** drop-down list. + +#. Copy the following query into the text box in the query console: + + .. code-block:: ql + + import ruby + + from IfExpr ifexpr + where + not exists(ifexpr.getThen()) + select ifexpr, "This 'if' expression is redundant." + + LGTM checks whether your query compiles and, if all is well, the **Run** button changes to green to indicate that you can go ahead and run the query. + +#. Click **Run**. + + The name of the project you are querying, and the ID of the most recently analyzed commit to the project, are listed below the query box. To the right of this is an icon that indicates the progress of the query operation: + + .. image:: ../images/query-progress.png + :align: center + + .. pull-quote:: + + Note + + Your query is always run against the most recently analyzed commit to the selected project. + + The query will take a few moments to return results. When the query completes, the results are displayed below the project name. The query results are listed in two columns, corresponding to the two expressions in the ``select`` clause of the query. The first column corresponds to the expression ``ifexpr`` and is linked to the location in the source code of the project where ``ifexpr`` occurs. The second column is the alert message. + + ➤ `Example query results <https://lgtm.com/query/1214010107827821393/>`__ + + .. pull-quote:: + + Note + + An ellipsis (…) at the bottom of the table indicates that the entire list is not displayed—click it to show more results. + +#. If any matching code is found, click a link in the ``ifexpr`` column to view the ``if`` statement in the code viewer. + + The matching ``if`` expression is highlighted with a yellow background in the code viewer. If any code in the file also matches a query from the standard query library for that language, you will see a red alert message at the appropriate point within the code. + +About the query structure +~~~~~~~~~~~~~~~~~~~~~~~~~ + +After the initial ``import`` statement, this simple query comprises three parts that serve similar purposes to the FROM, WHERE, and SELECT parts of an SQL query. + ++---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+ +| Query part | Purpose | Details | ++===============================================================+===================================================================================================================+========================================================================================================================+ +| ``import ruby`` | Imports the standard CodeQL libraries for Ruby. | Every query begins with one or more ``import`` statements. | ++---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+ +| ``from IfExpr ifexpr`` | Defines the variables for the query. | We use: an ``IfExpr`` variable for ``if`` expressions. | +| | Declarations are of the form: | | +| | ``<type> <variable name>`` | | ++---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+ +| ``where not exists(ifexpr.getThen())`` | Defines a condition on the variables. | ``ifexpr.getThen()``: gets the ``then`` branch of the ``if`` expression. | +| | | | +| | | ``exists(...)``: requires that there is a matching element, in this case a ``then`` branch. | ++---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+ +| ``select ifexpr, "This 'if' expression is redundant."`` | Defines what to report for each match. | Reports the resulting ``if`` expression with a string that explains the problem. | +| | | | +| | ``select`` statements for queries that are used to find instances of poor coding practice are always in the form: | | +| | ``select <program element>, "<alert message>"`` | | ++---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+ + +Extend the query +---------------- + +Query writing is an inherently iterative process. You write a simple query and then, when you run it, you discover examples that you had not previously considered, or opportunities for improvement. + +Remove false positive results +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Browsing the results of our basic query shows that it could be improved. Among the results you are likely to find examples of ``if`` statements with an ``else`` branch, where an empty ``then`` branch does serve a purpose. For example: + +.. code-block:: ruby + + if ... + ... + elsif option == "-verbose" + # nothing to do - handled earlier + else + error "unrecognized option" + +In this case, identifying the ``if`` statement with the empty ``then`` branch as redundant is a false positive. One solution to this is to modify the query to ignore empty ``then`` branches if the ``if`` statement has an ``else`` branch. + +To exclude ``if`` statements that have an ``else`` branch: + +#. Add the following to the where clause: + + .. code-block:: ql + + and not exists(ifstmt.getElse()) + + The ``where`` clause is now: + + .. code-block:: ql + + where + not exists(ifexpr.getThen()) and + not exists(ifexpr.getElse()) + +#. Click **Run**. + + There are now fewer results because ``if`` expressions with an ``else`` branch are no longer included. + +➤ `See this in the query console <https://lgtm.com/query/6233102733683510530/>`__ + +Further reading +--------------- + +.. include:: ../reusables/ruby-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/reusables/ruby-further-reading.rst b/docs/codeql/reusables/ruby-further-reading.rst new file mode 100644 index 00000000000..032eaff5112 --- /dev/null +++ b/docs/codeql/reusables/ruby-further-reading.rst @@ -0,0 +1,3 @@ +- `CodeQL queries for Ruby <https://github.com/github/codeql-ruby/tree/main/ql/src>`__ +- `Example queries for Ruby <https://github.com/github/codeql-ruby/tree/main/ql/examples>`__ +- `CodeQL library reference for Ruby <https://codeql.github.com/codeql-standard-libraries/ruby/>`__ From dea8dde566abd228890e6a4064488c014f12684b Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Wed, 22 Sep 2021 15:17:06 +0100 Subject: [PATCH 076/361] Java: Improve performance of confusing overloading query. --- .../Naming Conventions/ConfusingOverloading.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql b/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql index 1d8509c6e03..22bf9d36142 100644 --- a/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql +++ b/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql @@ -50,6 +50,7 @@ private predicate whitelist(string name) { name = "visit" } * Method `m` has name `name`, number of parameters `numParams` * and is declared in `t` or inherited from a supertype of `t`. */ +pragma[nomagic] private predicate candidateMethod(RefType t, Method m, string name, int numParam) { exists(Method n | n.getSourceDeclaration() = m | t.inherits(n)) and m.getName() = name and From 3ae5f13c3dbb3dc012b11a65d8fc2c683159abb1 Mon Sep 17 00:00:00 2001 From: Joe Farebrother <joefarebrother@github.com> Date: Wed, 29 Sep 2021 15:44:21 +0100 Subject: [PATCH 077/361] Generate tests and stubs --- .../code/java/frameworks/android/Intent.qll | 2 +- .../frameworks/android/intent/Test.java | 1316 +++++++++++++++++ .../frameworks/android/intent/models.csv | 114 ++ .../frameworks/android/intent/options | 1 + .../frameworks/android/intent/test.expected | 0 .../frameworks/android/intent/test.ql | 17 + .../android/android/accounts/Account.java | 21 + .../android/content/BroadcastReceiver.java | 292 +--- .../android/android/content/ClipData.java | 51 + .../android/content/ClipDescription.java | 32 + .../android/content/ComponentCallbacks.java | 11 + .../android/content/ComponentCallbacks2.java | 17 + .../android/content/ComponentName.java | 35 + .../android/content/ContentProvider.java | 85 +- .../content/ContentProviderClient.java | 49 + .../content/ContentProviderOperation.java | 58 + .../content/ContentProviderResult.java | 26 + .../android/content/ContentResolver.java | 163 +- .../android/content/ContentValues.java | 47 +- .../android/android/content/Context.java | 262 +++- .../stubs/android/android/content/Intent.java | 641 +++++--- .../android/android/content/IntentFilter.java | 104 ++ .../android/android/content/IntentSender.java | 40 + .../android/android/content/PeriodicSync.java | 23 + .../android/content/ServiceConnection.java | 14 + .../android/content/SharedPreferences.java | 38 + .../android/content/SyncAdapterType.java | 28 + .../android/android/content/SyncInfo.java | 16 + .../android/android/content/SyncRequest.java | 13 + .../android/content/SyncStatusObserver.java | 9 + .../android/content/UriPermission.java | 20 + .../android/content/pm/ActivityInfo.java | 112 ++ .../android/content/pm/ApplicationInfo.java | 101 ++ .../android/content/pm/ChangedPackages.java | 18 + .../android/content/pm/ComponentInfo.java | 29 + .../android/content/pm/ConfigurationInfo.java | 25 + .../android/content/pm/FeatureGroupInfo.java | 17 + .../android/content/pm/FeatureInfo.java | 23 + .../android/content/pm/InstallSourceInfo.java | 18 + .../content/pm/InstrumentationInfo.java | 27 + .../android/content/pm/ModuleInfo.java | 19 + .../android/content/pm/PackageInfo.java | 59 + .../android/content/pm/PackageInstaller.java | 151 ++ .../android/content/pm/PackageItemInfo.java | 34 + .../android/content/pm/PackageManager.java | 331 +++++ .../android/content/pm/PathPermission.java | 18 + .../content/pm/PermissionGroupInfo.java | 24 + .../android/content/pm/PermissionInfo.java | 48 + .../android/content/pm/ProviderInfo.java | 33 + .../android/content/pm/ResolveInfo.java | 42 + .../android/content/pm/ServiceInfo.java | 37 + .../android/content/pm/SharedLibraryInfo.java | 26 + .../android/android/content/pm/Signature.java | 22 + .../android/content/pm/SigningInfo.java | 20 + .../android/content/pm/VersionedPackage.java | 22 + .../content/res/AssetFileDescriptor.java | 33 + .../android/content/res/AssetManager.java | 26 + .../android/content/res/ColorStateList.java | 27 + .../android/content/res/Configuration.java | 130 ++ .../android/content/res/Resources.java | 105 ++ .../android/content/res/TypedArray.java | 46 + .../content/res/XmlResourceParser.java | 12 + .../content/res/loader/AssetsProvider.java | 10 + .../content/res/loader/ResourcesLoader.java | 16 + .../content/res/loader/ResourcesProvider.java | 21 + .../android/database/CharArrayBuffer.java | 13 + .../android/database/ContentObserver.java | 22 + .../android/android/database/Cursor.java | 61 +- .../android/database/DataSetObserver.java | 11 + .../database/DatabaseErrorHandler.java | 10 + .../database/sqlite/SQLiteClosable.java | 16 + .../database/sqlite/SQLiteCursorDriver.java | 15 + .../database/sqlite/SQLiteDatabase.java | 171 ++- .../database/sqlite/SQLiteProgram.java | 18 + .../android/database/sqlite/SQLiteQuery.java | 10 + .../database/sqlite/SQLiteStatement.java | 17 + .../sqlite/SQLiteTransactionListener.java | 11 + .../android/android/graphics/Bitmap.java | 97 ++ .../android/graphics/BitmapFactory.java | 54 + .../android/android/graphics/BlendMode.java | 10 + .../android/android/graphics/Canvas.java | 141 ++ .../stubs/android/android/graphics/Color.java | 80 + .../android/android/graphics/ColorFilter.java | 9 + .../android/android/graphics/ColorSpace.java | 120 ++ .../android/android/graphics/DrawFilter.java | 10 + .../android/android/graphics/Insets.java | 29 + .../android/android/graphics/MaskFilter.java | 10 + .../android/android/graphics/Matrix.java | 74 + .../stubs/android/android/graphics/Movie.java | 23 + .../android/android/graphics/NinePatch.java | 31 + .../android/android/graphics/Outline.java | 29 + .../stubs/android/android/graphics/Paint.java | 212 +++ .../stubs/android/android/graphics/Path.java | 73 + .../android/android/graphics/PathEffect.java | 10 + .../android/android/graphics/Picture.java | 18 + .../stubs/android/android/graphics/Point.java | 26 + .../android/android/graphics/PorterDuff.java | 14 + .../android/graphics/RecordingCanvas.java | 82 + .../stubs/android/android/graphics/Rect.java | 52 + .../stubs/android/android/graphics/RectF.java | 53 + .../android/android/graphics/Region.java | 53 + .../android/android/graphics/RenderNode.java | 82 + .../android/android/graphics/Shader.java | 12 + .../android/android/graphics/Typeface.java | 33 + .../android/android/graphics/Xfermode.java | 9 + .../android/graphics/drawable/Drawable.java | 111 ++ .../android/graphics/drawable/Icon.java | 55 + .../android/graphics/text/MeasuredText.java | 13 + .../android/hardware/HardwareBuffer.java | 50 + .../android/android/icu/util/ULocale.java | 138 ++ .../test/stubs/android/android/net/Uri.java | 73 +- .../stubs/android/android/os/BaseBundle.java | 43 + .../test/stubs/android/android/os/Bundle.java | 163 +- .../android/os/CancellationSignal.java | 14 +- .../stubs/android/android/os/Handler.java | 53 + .../stubs/android/android/os/IBinder.java | 33 + .../stubs/android/android/os/IInterface.java | 10 + .../stubs/android/android/os/LocaleList.java | 32 + .../test/stubs/android/android/os/Looper.java | 25 + .../stubs/android/android/os/Message.java | 44 + .../android/android/os/MessageQueue.java | 26 + .../stubs/android/android/os/Messenger.java | 25 + .../test/stubs/android/android/os/Parcel.java | 146 ++ .../android/os/ParcelFileDescriptor.java | 55 +- .../stubs/android/android/os/Parcelable.java | 18 + .../android/android/os/PatternMatcher.java | 24 + .../android/android/os/PersistableBundle.java | 27 + .../stubs/android/android/os/UserHandle.java | 21 + .../android/util/AndroidException.java | 12 + .../stubs/android/android/util/ArrayMap.java | 40 + .../android/android/util/AttributeSet.java | 95 +- .../android/android/util/DisplayMetrics.java | 46 + .../test/stubs/android/android/util/Pair.java | 16 + .../stubs/android/android/util/Printer.java | 9 + .../test/stubs/android/android/util/Size.java | 16 + .../stubs/android/android/util/SizeF.java | 16 + .../android/android/util/SparseArray.java | 28 + .../android/util/SparseBooleanArray.java | 27 + .../android/android/util/TypedValue.java | 73 + .../stubs/android/android/view/Display.java | 89 ++ .../android/android/view/DisplayCutout.java | 28 + .../android/org/xmlpull/v1/XmlPullParser.java | 64 + .../android/org/xmlpull/v1/XmlSerializer.java | 35 + 143 files changed, 8174 insertions(+), 667 deletions(-) create mode 100644 java/ql/test/library-tests/frameworks/android/intent/Test.java create mode 100644 java/ql/test/library-tests/frameworks/android/intent/models.csv create mode 100644 java/ql/test/library-tests/frameworks/android/intent/options create mode 100644 java/ql/test/library-tests/frameworks/android/intent/test.expected create mode 100644 java/ql/test/library-tests/frameworks/android/intent/test.ql create mode 100644 java/ql/test/stubs/android/android/accounts/Account.java create mode 100644 java/ql/test/stubs/android/android/content/ClipData.java create mode 100644 java/ql/test/stubs/android/android/content/ClipDescription.java create mode 100644 java/ql/test/stubs/android/android/content/ComponentCallbacks.java create mode 100644 java/ql/test/stubs/android/android/content/ComponentCallbacks2.java create mode 100644 java/ql/test/stubs/android/android/content/ComponentName.java create mode 100644 java/ql/test/stubs/android/android/content/ContentProviderClient.java create mode 100644 java/ql/test/stubs/android/android/content/ContentProviderOperation.java create mode 100644 java/ql/test/stubs/android/android/content/ContentProviderResult.java create mode 100644 java/ql/test/stubs/android/android/content/IntentFilter.java create mode 100644 java/ql/test/stubs/android/android/content/IntentSender.java create mode 100644 java/ql/test/stubs/android/android/content/PeriodicSync.java create mode 100644 java/ql/test/stubs/android/android/content/ServiceConnection.java create mode 100644 java/ql/test/stubs/android/android/content/SharedPreferences.java create mode 100644 java/ql/test/stubs/android/android/content/SyncAdapterType.java create mode 100644 java/ql/test/stubs/android/android/content/SyncInfo.java create mode 100644 java/ql/test/stubs/android/android/content/SyncRequest.java create mode 100644 java/ql/test/stubs/android/android/content/SyncStatusObserver.java create mode 100644 java/ql/test/stubs/android/android/content/UriPermission.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ActivityInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ApplicationInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ChangedPackages.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ComponentInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ConfigurationInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/FeatureGroupInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/FeatureInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/InstallSourceInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/InstrumentationInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ModuleInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/PackageInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/PackageInstaller.java create mode 100644 java/ql/test/stubs/android/android/content/pm/PackageItemInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/PackageManager.java create mode 100644 java/ql/test/stubs/android/android/content/pm/PathPermission.java create mode 100644 java/ql/test/stubs/android/android/content/pm/PermissionGroupInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/PermissionInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ProviderInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ResolveInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/ServiceInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/SharedLibraryInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/Signature.java create mode 100644 java/ql/test/stubs/android/android/content/pm/SigningInfo.java create mode 100644 java/ql/test/stubs/android/android/content/pm/VersionedPackage.java create mode 100644 java/ql/test/stubs/android/android/content/res/AssetFileDescriptor.java create mode 100644 java/ql/test/stubs/android/android/content/res/AssetManager.java create mode 100644 java/ql/test/stubs/android/android/content/res/ColorStateList.java create mode 100644 java/ql/test/stubs/android/android/content/res/Configuration.java create mode 100644 java/ql/test/stubs/android/android/content/res/Resources.java create mode 100644 java/ql/test/stubs/android/android/content/res/TypedArray.java create mode 100644 java/ql/test/stubs/android/android/content/res/XmlResourceParser.java create mode 100644 java/ql/test/stubs/android/android/content/res/loader/AssetsProvider.java create mode 100644 java/ql/test/stubs/android/android/content/res/loader/ResourcesLoader.java create mode 100644 java/ql/test/stubs/android/android/content/res/loader/ResourcesProvider.java create mode 100644 java/ql/test/stubs/android/android/database/CharArrayBuffer.java create mode 100644 java/ql/test/stubs/android/android/database/ContentObserver.java create mode 100644 java/ql/test/stubs/android/android/database/DataSetObserver.java create mode 100644 java/ql/test/stubs/android/android/database/DatabaseErrorHandler.java create mode 100644 java/ql/test/stubs/android/android/database/sqlite/SQLiteClosable.java create mode 100644 java/ql/test/stubs/android/android/database/sqlite/SQLiteCursorDriver.java create mode 100644 java/ql/test/stubs/android/android/database/sqlite/SQLiteProgram.java create mode 100644 java/ql/test/stubs/android/android/database/sqlite/SQLiteQuery.java create mode 100644 java/ql/test/stubs/android/android/database/sqlite/SQLiteStatement.java create mode 100644 java/ql/test/stubs/android/android/database/sqlite/SQLiteTransactionListener.java create mode 100644 java/ql/test/stubs/android/android/graphics/Bitmap.java create mode 100644 java/ql/test/stubs/android/android/graphics/BitmapFactory.java create mode 100644 java/ql/test/stubs/android/android/graphics/BlendMode.java create mode 100644 java/ql/test/stubs/android/android/graphics/Canvas.java create mode 100644 java/ql/test/stubs/android/android/graphics/Color.java create mode 100644 java/ql/test/stubs/android/android/graphics/ColorFilter.java create mode 100644 java/ql/test/stubs/android/android/graphics/ColorSpace.java create mode 100644 java/ql/test/stubs/android/android/graphics/DrawFilter.java create mode 100644 java/ql/test/stubs/android/android/graphics/Insets.java create mode 100644 java/ql/test/stubs/android/android/graphics/MaskFilter.java create mode 100644 java/ql/test/stubs/android/android/graphics/Matrix.java create mode 100644 java/ql/test/stubs/android/android/graphics/Movie.java create mode 100644 java/ql/test/stubs/android/android/graphics/NinePatch.java create mode 100644 java/ql/test/stubs/android/android/graphics/Outline.java create mode 100644 java/ql/test/stubs/android/android/graphics/Paint.java create mode 100644 java/ql/test/stubs/android/android/graphics/Path.java create mode 100644 java/ql/test/stubs/android/android/graphics/PathEffect.java create mode 100644 java/ql/test/stubs/android/android/graphics/Picture.java create mode 100644 java/ql/test/stubs/android/android/graphics/Point.java create mode 100644 java/ql/test/stubs/android/android/graphics/PorterDuff.java create mode 100644 java/ql/test/stubs/android/android/graphics/RecordingCanvas.java create mode 100644 java/ql/test/stubs/android/android/graphics/Rect.java create mode 100644 java/ql/test/stubs/android/android/graphics/RectF.java create mode 100644 java/ql/test/stubs/android/android/graphics/Region.java create mode 100644 java/ql/test/stubs/android/android/graphics/RenderNode.java create mode 100644 java/ql/test/stubs/android/android/graphics/Shader.java create mode 100644 java/ql/test/stubs/android/android/graphics/Typeface.java create mode 100644 java/ql/test/stubs/android/android/graphics/Xfermode.java create mode 100644 java/ql/test/stubs/android/android/graphics/drawable/Drawable.java create mode 100644 java/ql/test/stubs/android/android/graphics/drawable/Icon.java create mode 100644 java/ql/test/stubs/android/android/graphics/text/MeasuredText.java create mode 100644 java/ql/test/stubs/android/android/hardware/HardwareBuffer.java create mode 100644 java/ql/test/stubs/android/android/icu/util/ULocale.java create mode 100644 java/ql/test/stubs/android/android/os/BaseBundle.java create mode 100644 java/ql/test/stubs/android/android/os/Handler.java create mode 100644 java/ql/test/stubs/android/android/os/IBinder.java create mode 100644 java/ql/test/stubs/android/android/os/IInterface.java create mode 100644 java/ql/test/stubs/android/android/os/LocaleList.java create mode 100644 java/ql/test/stubs/android/android/os/Looper.java create mode 100644 java/ql/test/stubs/android/android/os/Message.java create mode 100644 java/ql/test/stubs/android/android/os/MessageQueue.java create mode 100644 java/ql/test/stubs/android/android/os/Messenger.java create mode 100644 java/ql/test/stubs/android/android/os/Parcel.java create mode 100644 java/ql/test/stubs/android/android/os/Parcelable.java create mode 100644 java/ql/test/stubs/android/android/os/PatternMatcher.java create mode 100644 java/ql/test/stubs/android/android/os/PersistableBundle.java create mode 100644 java/ql/test/stubs/android/android/os/UserHandle.java create mode 100644 java/ql/test/stubs/android/android/util/AndroidException.java create mode 100644 java/ql/test/stubs/android/android/util/ArrayMap.java create mode 100644 java/ql/test/stubs/android/android/util/DisplayMetrics.java create mode 100644 java/ql/test/stubs/android/android/util/Pair.java create mode 100644 java/ql/test/stubs/android/android/util/Printer.java create mode 100644 java/ql/test/stubs/android/android/util/Size.java create mode 100644 java/ql/test/stubs/android/android/util/SizeF.java create mode 100644 java/ql/test/stubs/android/android/util/SparseArray.java create mode 100644 java/ql/test/stubs/android/android/util/SparseBooleanArray.java create mode 100644 java/ql/test/stubs/android/android/util/TypedValue.java create mode 100644 java/ql/test/stubs/android/android/view/Display.java create mode 100644 java/ql/test/stubs/android/android/view/DisplayCutout.java create mode 100644 java/ql/test/stubs/android/org/xmlpull/v1/XmlPullParser.java create mode 100644 java/ql/test/stubs/android/org/xmlpull/v1/XmlSerializer.java diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index edb981cff8e..77c45b1e6f2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -127,7 +127,7 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.os;Bundle;true;putShortArray;;;Argument[0];MapKey of Argument[-1];value", "android.os;Bundle;true;putSize;;;Argument[0];MapKey of Argument[-1];value", "android.os;Bundle;true;putSizeF;;;Argument[0];MapKey of Argument[-1];value", - "android.os;Bundle;true;putSparceParcelableArray;;;Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;true;putSparseParcelableArray;;;Argument[0];MapKey of Argument[-1];value", "android.os;Bundle;true;putSparseParcelableArray;;;Argument[1];MapValue of Argument[-1];value", "android.os;Bundle;true;putStringArrayList;;;Argument[0];MapKey of Argument[-1];value", "android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value", diff --git a/java/ql/test/library-tests/frameworks/android/intent/Test.java b/java/ql/test/library-tests/frameworks/android/intent/Test.java new file mode 100644 index 00000000000..525986aeb45 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/Test.java @@ -0,0 +1,1316 @@ +package generatedtest; + +import android.content.Intent; +import android.os.BaseBundle; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; +import android.util.SparseArray; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Set; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + <T> T getElement(Iterable<T> it) { return it.iterator().next(); } + Object getIntent_extrasDefault(Object container) { return null; } + Object getMapKeyDefault(Object container) { return null; } + Object getMapValueDefault(Object container) { return null; } + Object newWithIntent_extrasDefault(Object element) { return null; } + Object newWithMapKeyDefault(Object element) { return null; } + Object newWithMapValueDefault(Object element) { return null; } + Object source() { return null; } + void sink(Object o) { } + + public void test() throws Exception { + + { + // "android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + Bundle out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getBundleExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + byte[] out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getByteArrayExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getCharArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + char[] out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getCharArrayExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getCharSequenceArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + CharSequence[] out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getCharSequenceArrayExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getCharSequenceArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + ArrayList out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getCharSequenceArrayListExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getCharSequenceExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + CharSequence out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getCharSequenceExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + Bundle out = null; + Intent in = (Intent)newWithIntent_extrasDefault(source()); + out = in.getExtras(); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + Parcelable[] out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getParcelableArrayExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getParcelableArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + ArrayList out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getParcelableArrayListExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getParcelableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + Parcelable out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getParcelableExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getSerializableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + Serializable out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getSerializableExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getStringArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + String[] out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getStringArrayExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getStringArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + ArrayList out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getStringArrayListExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getStringExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" + String out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = in.getStringExtra(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putCharSequenceArrayListExtra(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putCharSequenceArrayListExtra(in, null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + ArrayList in = (ArrayList)source(); + out.putCharSequenceArrayListExtra(null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, false); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, 0L); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, 0.0f); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, 0.0); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, 0); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (short[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (short)0); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (long[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (int[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (float[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (double[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (char[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (byte)0); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (boolean[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (String[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (String)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (Serializable)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (Parcelable[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (Parcelable)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (CharSequence[])null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (CharSequence)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, (Bundle)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtra((String)null, '\0'); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, false); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, 0L); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, 0.0f); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, 0.0); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, 0); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (short[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (short)0); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (long[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (int[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (float[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (double[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (char[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (byte[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (byte)0); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (boolean[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (String[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (String)null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (Serializable)null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (Parcelable[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (Parcelable)null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (CharSequence[])null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (CharSequence)null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, (Bundle)null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra(in, '\0'); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + short[] in = (short[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + short in = (short)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + long[] in = (long[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + long in = (long)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + int[] in = (int[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + int in = (int)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + float[] in = (float[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + float in = (float)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + double[] in = (double[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + double in = (double)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + char[] in = (char[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + char in = (char)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + byte[] in = (byte[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + byte in = (byte)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + boolean[] in = (boolean[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + boolean in = (boolean)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String[] in = (String[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Serializable in = (Serializable)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Parcelable[] in = (Parcelable[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Parcelable in = (Parcelable)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + CharSequence[] in = (CharSequence[])source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + CharSequence in = (CharSequence)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Bundle in = (Bundle)source(); + out.putExtra((String)null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtras;(Bundle);;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtras((Bundle)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Bundle in = (Bundle)newWithMapKeyDefault(source()); + out.putExtras(in); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out.putExtras(in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtras;(Intent);;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putExtras((Intent)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapKeyDefault(source())); + out.putExtras(in); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out.putExtras(in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putIntegerArrayListExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putIntegerArrayListExtra(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putIntegerArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putIntegerArrayListExtra(in, null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putParcelableArrayListExtra(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putParcelableArrayListExtra(in, null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + ArrayList in = (ArrayList)source(); + out.putParcelableArrayListExtra(null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putStringArrayListExtra;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.putStringArrayListExtra(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;putStringArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + String in = (String)source(); + out.putStringArrayListExtra(in, null); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;putStringArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + ArrayList in = (ArrayList)source(); + out.putStringArrayListExtra(null, in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;replaceExtras;(Bundle);;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.replaceExtras((Bundle)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;replaceExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Bundle in = (Bundle)newWithMapKeyDefault(source()); + out.replaceExtras(in); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;replaceExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out.replaceExtras(in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.replaceExtras((Intent)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;replaceExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapKeyDefault(source())); + out.replaceExtras(in); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;replaceExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out.replaceExtras(in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;get;(String);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + BaseBundle in = (BaseBundle)newWithMapValueDefault(source()); + out = in.get(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;getString;(String);;MapValue of Argument[-1];ReturnValue;value" + String out = null; + BaseBundle in = (BaseBundle)newWithMapValueDefault(source()); + out = in.getString(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;getString;(String,String);;Argument[1];ReturnValue;value" + String out = null; + String in = (String)source(); + BaseBundle instance = null; + out = instance.getString(null, in); + sink(out); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;getString;(String,String);;MapValue of Argument[-1];ReturnValue;value" + String out = null; + BaseBundle in = (BaseBundle)newWithMapValueDefault(source()); + out = in.getString(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;getStringArray;(String);;MapValue of Argument[-1];ReturnValue;value" + String[] out = null; + BaseBundle in = (BaseBundle)newWithMapValueDefault(source()); + out = in.getStringArray(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value" + Set out = null; + BaseBundle in = (BaseBundle)newWithMapKeyDefault(source()); + out = in.keySet(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putAll;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + PersistableBundle in = (PersistableBundle)newWithMapKeyDefault(source()); + out.putAll(in); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putAll;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value" + BaseBundle out = null; + PersistableBundle in = (PersistableBundle)newWithMapValueDefault(source()); + out.putAll(in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putBoolean;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putBoolean(in, false); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putBooleanArray;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putBooleanArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putDouble;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putDouble(in, 0.0); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putDoubleArray;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putDoubleArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putInt;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putInt(in, 0); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putIntArray;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putIntArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putLong;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putLong(in, 0L); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putLongArray;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putLongArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putString;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putString(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putString;;;Argument[1];MapValue of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putString(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putStringArray;;;Argument[0];MapKey of Argument[-1];value" + BaseBundle out = null; + String in = (String)source(); + out.putStringArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;BaseBundle;true;putStringArray;;;Argument[1];MapValue of Argument[-1];value" + BaseBundle out = null; + String[] in = (String[])source(); + out.putStringArray(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getBinder;(String);;MapValue of Argument[-1];ReturnValue;value" + IBinder out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getBinder(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getBundle;(String);;MapValue of Argument[-1];ReturnValue;value" + Bundle out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getBundle(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getByteArray;(String);;MapValue of Argument[-1];ReturnValue;value" + byte[] out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getByteArray(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getCharArray;(String);;MapValue of Argument[-1];ReturnValue;value" + char[] out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getCharArray(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getCharSequence;(String);;MapValue of Argument[-1];ReturnValue;value" + CharSequence out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getCharSequence(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getCharSequence;(String,CharSequence);;Argument[1];ReturnValue;value" + CharSequence out = null; + CharSequence in = (CharSequence)source(); + Bundle instance = null; + out = instance.getCharSequence(null, in); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getCharSequence;(String,CharSequence);;MapValue of Argument[-1];ReturnValue;value" + CharSequence out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getCharSequence(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getCharSequenceArray;(String);;MapValue of Argument[-1];ReturnValue;value" + CharSequence[] out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getCharSequenceArray(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getCharSequenceArrayList;(String);;MapValue of Argument[-1];ReturnValue;value" + ArrayList out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getCharSequenceArrayList(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getParcelable;(String);;MapValue of Argument[-1];ReturnValue;value" + Parcelable out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getParcelable(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value" + Parcelable[] out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getParcelableArray(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getParcelableArrayList;(String);;MapValue of Argument[-1];ReturnValue;value" + ArrayList out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getParcelableArrayList(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getSerializable;(String);;MapValue of Argument[-1];ReturnValue;value" + Serializable out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getSerializable(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getSparseParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value" + SparseArray out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getSparseParcelableArray(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;getStringArrayList;(String);;MapValue of Argument[-1];ReturnValue;value" + ArrayList out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.getStringArrayList(null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putAll;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + Bundle in = (Bundle)newWithMapKeyDefault(source()); + out.putAll(in); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putAll;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value" + Bundle out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out.putAll(in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putBinder;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putBinder(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putBinder;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + IBinder in = (IBinder)source(); + out.putBinder(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putBundle;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putBundle(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putBundle;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + Bundle in = (Bundle)source(); + out.putBundle(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putByte;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putByte(in, (byte)0); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putByteArray;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putByteArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putByteArray;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + byte[] in = (byte[])source(); + out.putByteArray(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putChar;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putChar(in, '\0'); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putCharArray;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putCharArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putCharArray;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + char[] in = (char[])source(); + out.putCharArray(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putCharSequence;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putCharSequence(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putCharSequence;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + CharSequence in = (CharSequence)source(); + out.putCharSequence(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putCharSequenceArray;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putCharSequenceArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putCharSequenceArray;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + CharSequence[] in = (CharSequence[])source(); + out.putCharSequenceArray(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putCharSequenceArrayList;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putCharSequenceArrayList(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putCharSequenceArrayList;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + ArrayList in = (ArrayList)source(); + out.putCharSequenceArrayList(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putFloat;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putFloat(in, 0.0f); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putFloatArray;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putFloatArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putIntegerArrayList;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putIntegerArrayList(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putParcelable;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putParcelable(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putParcelable;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + Parcelable in = (Parcelable)source(); + out.putParcelable(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putParcelableArray;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putParcelableArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putParcelableArray;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + Parcelable[] in = (Parcelable[])source(); + out.putParcelableArray(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putParcelableArrayList;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putParcelableArrayList(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putParcelableArrayList;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + ArrayList in = (ArrayList)source(); + out.putParcelableArrayList(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putSerializable;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putSerializable(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putSerializable;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + Serializable in = (Serializable)source(); + out.putSerializable(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putShort;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putShort(in, (short)0); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putShortArray;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putShortArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putSize;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putSize(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putSizeF;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putSizeF(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putSparseParcelableArray;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putSparseParcelableArray(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putSparseParcelableArray;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + SparseArray in = (SparseArray)source(); + out.putSparseParcelableArray(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putStringArrayList;;;Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + String in = (String)source(); + out.putStringArrayList(in, null); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value" + Bundle out = null; + ArrayList in = (ArrayList)source(); + out.putStringArrayList(null, in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint" + Bundle out = null; + Parcel in = (Parcel)source(); + out.readFromParcel(in); + sink(getMapKeyDefault(out)); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint" + Bundle out = null; + Parcel in = (Parcel)source(); + out.readFromParcel(in); + sink(getMapValueDefault(out)); // $ hasTaintFlow + } + + } + +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/android/intent/models.csv b/java/ql/test/library-tests/frameworks/android/intent/models.csv new file mode 100644 index 00000000000..83be9bbcb0c --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/models.csv @@ -0,0 +1,114 @@ +android.os;BaseBundle;true;get;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;BaseBundle;true;getString;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;BaseBundle;true;getString;(String,String);;MapValue of Argument[-1];ReturnValue;value +android.os;BaseBundle;true;getString;(String,String);;Argument[1];ReturnValue;value +android.os;BaseBundle;true;getStringArray;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;BaseBundle;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value +android.os;BaseBundle;true;putAll;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putAll;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value +android.os;BaseBundle;true;putBoolean;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putBooleanArray;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putDouble;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putDoubleArray;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putInt;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putIntArray;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putLong;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putLongArray;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putString;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putString;;;Argument[1];MapValue of Argument[-1];value +android.os;BaseBundle;true;putStringArray;;;Argument[0];MapKey of Argument[-1];value +android.os;BaseBundle;true;putStringArray;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;getBinder;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getBundle;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getByteArray;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getCharArray;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getCharSequence;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getCharSequence;(String,CharSequence);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getCharSequence;(String,CharSequence);;Argument[1];ReturnValue;value +android.os;Bundle;true;getCharSequenceArray;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getCharSequenceArrayList;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getParcelable;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getParcelableArrayList;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getSerializable;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getSparseParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;getStringArrayList;(String);;MapValue of Argument[-1];ReturnValue;value +android.os;Bundle;true;putAll;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putAll;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value +android.os;Bundle;true;putBinder;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putBinder;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putBundle;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putBundle;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putByte;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putByteArray;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putByteArray;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putChar;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putCharArray;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putCharArray;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putCharSequence;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putCharSequence;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putCharSequenceArray;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putCharSequenceArray;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putCharSequenceArrayList;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putCharSequenceArrayList;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putFloat;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putFloatArray;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putIntegerArrayList;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putParcelable;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putParcelable;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putParcelableArray;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putParcelableArray;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putParcelableArrayList;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putParcelableArrayList;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putSerializable;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putSerializable;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putShort;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putShortArray;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putSize;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putSizeF;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putSparseParcelableArray;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putSparseParcelableArray;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;putStringArrayList;;;Argument[0];MapKey of Argument[-1];value +android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint +android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint +android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getCharArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getCharSequenceArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getCharSequenceArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getCharSequenceExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getParcelableArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getParcelableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getSerializableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getStringArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getStringArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;getStringExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value +android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;value +android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value +android.content;Intent;true;putIntegerArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putIntegerArrayListExtra;;;Argument[-1];ReturnValue;value +android.content;Intent;true;putParcelableArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putParcelableArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putParcelableArrayListExtra;;;Argument[-1];ReturnValue;value +android.content;Intent;true;putStringArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putStringArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putStringArrayListExtra;;;Argument[-1];ReturnValue;value +android.content;Intent;true;putExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putExtras;(Bundle);;Argument[-1];ReturnValue;value +android.content;Intent;true;putExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;putExtras;(Intent);;Argument[-1];ReturnValue;value +android.content;Intent;true;replaceExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;replaceExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;replaceExtras;(Bundle);;Argument[-1];ReturnValue;value +android.content;Intent;true;replaceExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;replaceExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/android/intent/options b/java/ql/test/library-tests/frameworks/android/intent/options new file mode 100644 index 00000000000..020a4a1cebb --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/android diff --git a/java/ql/test/library-tests/frameworks/android/intent/test.expected b/java/ql/test/library-tests/frameworks/android/intent/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/android/intent/test.ql b/java/ql/test/library-tests/frameworks/android/intent/test.ql new file mode 100644 index 00000000000..e89ac1ba290 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/test.ql @@ -0,0 +1,17 @@ +import java +import TestUtilities.InlineFlowTest + +class SummaryModelTest extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", + "generatedtest;Test;false;newWithMapKeyDefault;(Object);;Argument[0];MapKey of ReturnValue;value", + "generatedtest;Test;false;getMapKeyDefault;(Object);;MapKey of Argument[0];ReturnValue;value", + "generatedtest;Test;false;newWithMapValueDefault;(Object);;Argument[0];MapValue of ReturnValue;value", + "generatedtest;Test;false;getMapValueDefault;(Object);;MapValue of Argument[0];ReturnValue;value", + "generatedtest;Test;false;newWithIntent_extrasDefault;(Object);;Argument[0];SyntheticField[android.content.Intent.extras] of ReturnValue;value", + "generatedtest;Test;false;getIntent_extrasDefault;(Object);;SyntheticField[android.content.Intent.extras] of Argument[0];ReturnValue;value" + ] + } +} diff --git a/java/ql/test/stubs/android/android/accounts/Account.java b/java/ql/test/stubs/android/android/accounts/Account.java new file mode 100644 index 00000000000..806f076452e --- /dev/null +++ b/java/ql/test/stubs/android/android/accounts/Account.java @@ -0,0 +1,21 @@ +// Generated automatically from android.accounts.Account for testing purposes + +package android.accounts; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Account implements Parcelable +{ + protected Account() {} + public Account(Parcel p0){} + public Account(String p0, String p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final String name = null; + public final String type = null; + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<Account> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/BroadcastReceiver.java b/java/ql/test/stubs/android/android/content/BroadcastReceiver.java index 1d73018c96d..93375c04d85 100644 --- a/java/ql/test/stubs/android/android/content/BroadcastReceiver.java +++ b/java/ql/test/stubs/android/android/content/BroadcastReceiver.java @@ -1,255 +1,45 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.content.BroadcastReceiver for testing purposes + package android.content; +import android.content.Context; +import android.content.Intent; import android.os.Bundle; -/** - * Base class for code that will receive intents sent by sendBroadcast(). - * - * <p>If you don't need to send broadcasts across applications, consider using - * this class with {@link android.support.v4.content.LocalBroadcastManager} instead - * of the more general facilities described below. This will give you a much - * more efficient implementation (no cross-process communication needed) and allow - * you to avoid thinking about any security issues related to other applications - * being able to receive or send your broadcasts. - * - * <p>You can either dynamically register an instance of this class with - * {@link Context#registerReceiver Context.registerReceiver()} - * or statically publish an implementation through the - * {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag in your <code>AndroidManifest.xml</code>. - * - * <p><em><strong>Note:</strong></em> - *    If registering a receiver in your - * {@link android.app.Activity#onResume() Activity.onResume()} - * implementation, you should unregister it in - * {@link android.app.Activity#onPause() Activity.onPause()}. - * (You won't receive intents when paused, - * and this will cut down on unnecessary system overhead). Do not unregister in - * {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) Activity.onSaveInstanceState()}, - * because this won't be called if the user moves back in the history - * stack. - * - * <p>There are two major classes of broadcasts that can be received:</p> - * <ul> - * <li> <b>Normal broadcasts</b> (sent with {@link Context#sendBroadcast(Intent) - * Context.sendBroadcast}) are completely asynchronous. All receivers of the - * broadcast are run in an undefined order, often at the same time. This is - * more efficient, but means that receivers cannot use the result or abort - * APIs included here. - * <li> <b>Ordered broadcasts</b> (sent with {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast}) are delivered to one receiver at a time. - * As each receiver executes in turn, it can propagate a result to the next - * receiver, or it can completely abort the broadcast so that it won't be passed - * to other receivers. The order receivers run in can be controlled with the - * {@link android.R.styleable#AndroidManifestIntentFilter_priority - * android:priority} attribute of the matching intent-filter; receivers with - * the same priority will be run in an arbitrary order. - * </ul> - * - * <p>Even in the case of normal broadcasts, the system may in some - * situations revert to delivering the broadcast one receiver at a time. In - * particular, for receivers that may require the creation of a process, only - * one will be run at a time to avoid overloading the system with new processes. - * In this situation, however, the non-ordered semantics hold: these receivers still - * cannot return results or abort their broadcast.</p> - * - * <p>Note that, although the Intent class is used for sending and receiving - * these broadcasts, the Intent broadcast mechanism here is completely separate - * from Intents that are used to start Activities with - * {@link Context#startActivity Context.startActivity()}. - * There is no way for a BroadcastReceiver - * to see or capture Intents used with startActivity(); likewise, when - * you broadcast an Intent, you will never find or start an Activity. - * These two operations are semantically very different: starting an - * Activity with an Intent is a foreground operation that modifies what the - * user is currently interacting with; broadcasting an Intent is a background - * operation that the user is not normally aware of. - * - * <p>The BroadcastReceiver class (when launched as a component through - * a manifest's {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag) is an important part of an - * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">application's overall lifecycle</a>.</p> - * - * <p>Topics covered here: - * <ol> - * <li><a href="#Security">Security</a> - * <li><a href="#ReceiverLifecycle">Receiver Lifecycle</a> - * <li><a href="#ProcessLifecycle">Process Lifecycle</a> - * </ol> - * - * <div class="special reference"> - * <h3>Developer Guides</h3> - * <p>For information about how to use this class to receive and resolve intents, read the - * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a> - * developer guide.</p> - * </div> - * - * <a name="Security"></a> - * <h3>Security</h3> - * - * <p>Receivers used with the {@link Context} APIs are by their nature a - * cross-application facility, so you must consider how other applications - * may be able to abuse your use of them. Some things to consider are: - * - * <ul> - * <li><p>The Intent namespace is global. Make sure that Intent action names and - * other strings are written in a namespace you own, or else you may inadvertantly - * conflict with other applications. - * <li><p>When you use {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)}, - * <em>any</em> application may send broadcasts to that registered receiver. You can - * control who can send broadcasts to it through permissions described below. - * <li><p>When you publish a receiver in your application's manifest and specify - * intent-filters for it, any other application can send broadcasts to it regardless - * of the filters you specify. To prevent others from sending to it, make it - * unavailable to them with <code>android:exported="false"</code>. - * <li><p>When you use {@link Context#sendBroadcast(Intent)} or related methods, - * normally any other application can receive these broadcasts. You can control who - * can receive such broadcasts through permissions described below. Alternatively, - * starting with {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, you - * can also safely restrict the broadcast to a single application with - * {@link Intent#setPackage(String) Intent.setPackage} - * </ul> - * - * <p>None of these issues exist when using - * {@link android.support.v4.content.LocalBroadcastManager}, since intents - * broadcast it never go outside of the current process. - * - * <p>Access permissions can be enforced by either the sender or receiver - * of a broadcast. - * - * <p>To enforce a permission when sending, you supply a non-null - * <var>permission</var> argument to - * {@link Context#sendBroadcast(Intent, String)} or - * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}. - * Only receivers who have been granted this permission - * (by requesting it with the - * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} - * tag in their <code>AndroidManifest.xml</code>) will be able to receive - * the broadcast. - * - * <p>To enforce a permission when receiving, you supply a non-null - * <var>permission</var> when registering your receiver -- either when calling - * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)} - * or in the static - * {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag in your <code>AndroidManifest.xml</code>. Only broadcasters who have - * been granted this permission (by requesting it with the - * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} - * tag in their <code>AndroidManifest.xml</code>) will be able to send an - * Intent to the receiver. - * - * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> - * document for more information on permissions and security in general. - * - * <a name="ReceiverLifecycle"></a> - * <h3>Receiver Lifecycle</h3> - * - * <p>A BroadcastReceiver object is only valid for the duration of the call - * to {@link #onReceive}. Once your code returns from this function, - * the system considers the object to be finished and no longer active. - * - * <p>This has important repercussions to what you can do in an - * {@link #onReceive} implementation: anything that requires asynchronous - * operation is not available, because you will need to return from the - * function to handle the asynchronous operation, but at that point the - * BroadcastReceiver is no longer active and thus the system is free to kill - * its process before the asynchronous operation completes. - * - * <p>In particular, you may <i>not</i> show a dialog or bind to a service from - * within a BroadcastReceiver. For the former, you should instead use the - * {@link android.app.NotificationManager} API. For the latter, you can - * use {@link android.content.Context#startService Context.startService()} to - * send a command to the service. - * - * <a name="ProcessLifecycle"></a> - * <h3>Process Lifecycle</h3> - * - * <p>A process that is currently executing a BroadcastReceiver (that is, - * currently running the code in its {@link #onReceive} method) is - * considered to be a foreground process and will be kept running by the - * system except under cases of extreme memory pressure. - * - * <p>Once you return from onReceive(), the BroadcastReceiver is no longer - * active, and its hosting process is only as important as any other application - * components that are running in it. This is especially important because if - * that process was only hosting the BroadcastReceiver (a common case for - * applications that the user has never or not recently interacted with), then - * upon returning from onReceive() the system will consider its process - * to be empty and aggressively kill it so that resources are available for other - * more important processes. - * - * <p>This means that for longer-running operations you will often use - * a {@link android.app.Service} in conjunction with a BroadcastReceiver to keep - * the containing process active for the entire time of your operation. - */ -public abstract class BroadcastReceiver { - - /** - * State for a result that is pending for a broadcast receiver. Returned - * by {@link BroadcastReceiver#goAsync() goAsync()} - * while in {@link BroadcastReceiver#onReceive BroadcastReceiver.onReceive()}. - * This allows you to return from onReceive() without having the broadcast - * terminate; you must call {@link #finish()} once you are done with the - * broadcast. This allows you to process the broadcast off of the main - * thread of your app. - * - * <p>Note on threading: the state inside of this class is not itself - * thread-safe, however you can use it from any thread if you properly - * sure that you do not have races. Typically this means you will hand - * the entire object to another thread, which will be solely responsible - * for setting any results and finally calling {@link #finish()}. - */ - - public BroadcastReceiver() { +import android.os.IBinder; + +abstract public class BroadcastReceiver +{ + public BroadcastReceiver(){} + public IBinder peekService(Context p0, Intent p1){ return null; } + public abstract void onReceive(Context p0, Intent p1); + public final BroadcastReceiver.PendingResult goAsync(){ return null; } + public final Bundle getResultExtras(boolean p0){ return null; } + public final String getResultData(){ return null; } + public final boolean getAbortBroadcast(){ return false; } + public final boolean getDebugUnregister(){ return false; } + public final boolean isInitialStickyBroadcast(){ return false; } + public final boolean isOrderedBroadcast(){ return false; } + public final int getResultCode(){ return 0; } + public final void abortBroadcast(){} + public final void clearAbortBroadcast(){} + public final void setDebugUnregister(boolean p0){} + public final void setOrderedHint(boolean p0){} + public final void setResult(int p0, String p1, Bundle p2){} + public final void setResultCode(int p0){} + public final void setResultData(String p0){} + public final void setResultExtras(Bundle p0){} + static public class PendingResult + { + public final Bundle getResultExtras(boolean p0){ return null; } + public final String getResultData(){ return null; } + public final boolean getAbortBroadcast(){ return false; } + public final int getResultCode(){ return 0; } + public final void abortBroadcast(){} + public final void clearAbortBroadcast(){} + public final void finish(){} + public final void setResult(int p0, String p1, Bundle p2){} + public final void setResultCode(int p0){} + public final void setResultData(String p0){} + public final void setResultExtras(Bundle p0){} } - /** - * This method is called when the BroadcastReceiver is receiving an Intent - * broadcast. During this time you can use the other methods on - * BroadcastReceiver to view/modify the current result values. This method - * is always called within the main thread of its process, unless you - * explicitly asked for it to be scheduled on a different thread using - * {@link android.content.Context#registerReceiver(BroadcastReceiver, - * IntentFilter, String, android.os.Handler)}. When it runs on the main - * thread you should - * never perform long-running operations in it (there is a timeout of - * 10 seconds that the system allows before considering the receiver to - * be blocked and a candidate to be killed). You cannot launch a popup dialog - * in your implementation of onReceive(). - * - * <p><b>If this BroadcastReceiver was launched through a <receiver> tag, - * then the object is no longer alive after returning from this - * function.</b> This means you should not perform any operations that - * return a result to you asynchronously -- in particular, for interacting - * with services, you should use - * {@link Context#startService(Intent)} instead of - * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish - * to interact with a service that is already running, you can use - * {@link #peekService}. - * - * <p>The Intent filters used in {@link android.content.Context#registerReceiver} - * and in application manifests are <em>not</em> guaranteed to be exclusive. They - * are hints to the operating system about how to find suitable recipients. It is - * possible for senders to force delivery to specific recipients, bypassing filter - * resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()} - * implementations should respond only to known actions, ignoring any unexpected - * Intents that they may receive. - * - * @param context The Context in which the receiver is running. - * @param intent The Intent being received. - */ - public abstract void onReceive(Context context, Intent intent); -} \ No newline at end of file +} diff --git a/java/ql/test/stubs/android/android/content/ClipData.java b/java/ql/test/stubs/android/android/content/ClipData.java new file mode 100644 index 00000000000..490aff3323a --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ClipData.java @@ -0,0 +1,51 @@ +// Generated automatically from android.content.ClipData for testing purposes + +package android.content; + +import android.content.ClipDescription; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +public class ClipData implements Parcelable +{ + protected ClipData() {} + public ClipData(CharSequence p0, String[] p1, ClipData.Item p2){} + public ClipData(ClipData p0){} + public ClipData(ClipDescription p0, ClipData.Item p1){} + public ClipData.Item getItemAt(int p0){ return null; } + public ClipDescription getDescription(){ return null; } + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int getItemCount(){ return 0; } + public static ClipData newHtmlText(CharSequence p0, CharSequence p1, String p2){ return null; } + public static ClipData newIntent(CharSequence p0, Intent p1){ return null; } + public static ClipData newPlainText(CharSequence p0, CharSequence p1){ return null; } + public static ClipData newRawUri(CharSequence p0, Uri p1){ return null; } + public static ClipData newUri(ContentResolver p0, CharSequence p1, Uri p2){ return null; } + public static Parcelable.Creator<ClipData> CREATOR = null; + public void addItem(ClipData.Item p0){} + public void addItem(ContentResolver p0, ClipData.Item p1){} + public void writeToParcel(Parcel p0, int p1){} + static public class Item + { + protected Item() {} + public CharSequence coerceToStyledText(Context p0){ return null; } + public CharSequence coerceToText(Context p0){ return null; } + public CharSequence getText(){ return null; } + public Intent getIntent(){ return null; } + public Item(CharSequence p0){} + public Item(CharSequence p0, Intent p1, Uri p2){} + public Item(CharSequence p0, String p1){} + public Item(CharSequence p0, String p1, Intent p2, Uri p3){} + public Item(Intent p0){} + public Item(Uri p0){} + public String coerceToHtmlText(Context p0){ return null; } + public String getHtmlText(){ return null; } + public String toString(){ return null; } + public Uri getUri(){ return null; } + } +} diff --git a/java/ql/test/stubs/android/android/content/ClipDescription.java b/java/ql/test/stubs/android/android/content/ClipDescription.java new file mode 100644 index 00000000000..34fe5a59715 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ClipDescription.java @@ -0,0 +1,32 @@ +// Generated automatically from android.content.ClipDescription for testing purposes + +package android.content; + +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; + +public class ClipDescription implements Parcelable +{ + protected ClipDescription() {} + public CharSequence getLabel(){ return null; } + public ClipDescription(CharSequence p0, String[] p1){} + public ClipDescription(ClipDescription p0){} + public PersistableBundle getExtras(){ return null; } + public String getMimeType(int p0){ return null; } + public String toString(){ return null; } + public String[] filterMimeTypes(String p0){ return null; } + public boolean hasMimeType(String p0){ return false; } + public int describeContents(){ return 0; } + public int getMimeTypeCount(){ return 0; } + public long getTimestamp(){ return 0; } + public static Parcelable.Creator<ClipDescription> CREATOR = null; + public static String MIMETYPE_TEXT_HTML = null; + public static String MIMETYPE_TEXT_INTENT = null; + public static String MIMETYPE_TEXT_PLAIN = null; + public static String MIMETYPE_TEXT_URILIST = null; + public static String MIMETYPE_UNKNOWN = null; + public static boolean compareMimeTypes(String p0, String p1){ return false; } + public void setExtras(PersistableBundle p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/ComponentCallbacks.java b/java/ql/test/stubs/android/android/content/ComponentCallbacks.java new file mode 100644 index 00000000000..51726693d00 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ComponentCallbacks.java @@ -0,0 +1,11 @@ +// Generated automatically from android.content.ComponentCallbacks for testing purposes + +package android.content; + +import android.content.res.Configuration; + +public interface ComponentCallbacks +{ + void onConfigurationChanged(Configuration p0); + void onLowMemory(); +} diff --git a/java/ql/test/stubs/android/android/content/ComponentCallbacks2.java b/java/ql/test/stubs/android/android/content/ComponentCallbacks2.java new file mode 100644 index 00000000000..f8c83ab104d --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ComponentCallbacks2.java @@ -0,0 +1,17 @@ +// Generated automatically from android.content.ComponentCallbacks2 for testing purposes + +package android.content; + +import android.content.ComponentCallbacks; + +public interface ComponentCallbacks2 extends ComponentCallbacks +{ + static int TRIM_MEMORY_BACKGROUND = 0; + static int TRIM_MEMORY_COMPLETE = 0; + static int TRIM_MEMORY_MODERATE = 0; + static int TRIM_MEMORY_RUNNING_CRITICAL = 0; + static int TRIM_MEMORY_RUNNING_LOW = 0; + static int TRIM_MEMORY_RUNNING_MODERATE = 0; + static int TRIM_MEMORY_UI_HIDDEN = 0; + void onTrimMemory(int p0); +} diff --git a/java/ql/test/stubs/android/android/content/ComponentName.java b/java/ql/test/stubs/android/android/content/ComponentName.java new file mode 100644 index 00000000000..2c72a0a5125 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ComponentName.java @@ -0,0 +1,35 @@ +// Generated automatically from android.content.ComponentName for testing purposes + +package android.content; + +import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; + +public class ComponentName implements Cloneable, Comparable<ComponentName>, Parcelable +{ + protected ComponentName() {} + public ComponentName clone(){ return null; } + public ComponentName(Context p0, Class<? extends Object> p1){} + public ComponentName(Context p0, String p1){} + public ComponentName(Parcel p0){} + public ComponentName(String p0, String p1){} + public String flattenToShortString(){ return null; } + public String flattenToString(){ return null; } + public String getClassName(){ return null; } + public String getPackageName(){ return null; } + public String getShortClassName(){ return null; } + public String toShortString(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int compareTo(ComponentName p0){ return 0; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static ComponentName createRelative(Context p0, String p1){ return null; } + public static ComponentName createRelative(String p0, String p1){ return null; } + public static ComponentName readFromParcel(Parcel p0){ return null; } + public static ComponentName unflattenFromString(String p0){ return null; } + public static Parcelable.Creator<ComponentName> CREATOR = null; + public static void writeToParcel(ComponentName p0, Parcel p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/ContentProvider.java b/java/ql/test/stubs/android/android/content/ContentProvider.java index dfbd61f2ae6..d0928e0e9d0 100644 --- a/java/ql/test/stubs/android/android/content/ContentProvider.java +++ b/java/ql/test/stubs/android/android/content/ContentProvider.java @@ -1,17 +1,82 @@ +// Generated automatically from android.content.ContentProvider for testing purposes + package android.content; +import android.content.ComponentCallbacks2; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentValues; +import android.content.Context; +import android.content.pm.PathPermission; +import android.content.pm.ProviderInfo; +import android.content.res.AssetFileDescriptor; +import android.content.res.Configuration; import android.database.Cursor; import android.net.Uri; +import android.os.Bundle; import android.os.CancellationSignal; +import android.os.ParcelFileDescriptor; +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; -public abstract class ContentProvider { - public abstract int delete(Uri uri, String selection, String[] selectionArgs); - - public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, - CancellationSignal cancellationSignal); - - public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder); - - public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs); - +abstract public class ContentProvider implements ComponentCallbacks2 +{ + protected boolean isTemporary(){ return false; } + protected final ParcelFileDescriptor openFileHelper(Uri p0, String p1){ return null; } + protected final void setPathPermissions(PathPermission[] p0){} + protected final void setReadPermission(String p0){} + protected final void setWritePermission(String p0){} + public <T> ParcelFileDescriptor openPipeHelper(Uri p0, String p1, Bundle p2, T p3, ContentProvider.PipeDataWriter<T> p4){ return null; } + public AssetFileDescriptor openAssetFile(Uri p0, String p1){ return null; } + public AssetFileDescriptor openAssetFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public AssetFileDescriptor openTypedAssetFile(Uri p0, String p1, Bundle p2){ return null; } + public AssetFileDescriptor openTypedAssetFile(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public Bundle call(String p0, String p1, Bundle p2){ return null; } + public Bundle call(String p0, String p1, String p2, Bundle p3){ return null; } + public ContentProvider(){} + public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> p0){ return null; } + public ContentProviderResult[] applyBatch(String p0, ArrayList<ContentProviderOperation> p1){ return null; } + public Cursor query(Uri p0, String[] p1, Bundle p2, CancellationSignal p3){ return null; } + public Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4, CancellationSignal p5){ return null; } + public ParcelFileDescriptor openFile(Uri p0, String p1){ return null; } + public ParcelFileDescriptor openFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public String[] getStreamTypes(Uri p0, String p1){ return null; } + public Uri canonicalize(Uri p0){ return null; } + public Uri insert(Uri p0, ContentValues p1, Bundle p2){ return null; } + public Uri uncanonicalize(Uri p0){ return null; } + public abstract Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4); + public abstract String getType(Uri p0); + public abstract Uri insert(Uri p0, ContentValues p1); + public abstract boolean onCreate(); + public abstract int delete(Uri p0, String p1, String[] p2); + public abstract int update(Uri p0, ContentValues p1, String p2, String[] p3); + public boolean refresh(Uri p0, Bundle p1, CancellationSignal p2){ return false; } + public class CallingIdentity + { + } + public final ContentProvider.CallingIdentity clearCallingIdentity(){ return null; } + public final Context getContext(){ return null; } + public final Context requireContext(){ return null; } + public final PathPermission[] getPathPermissions(){ return null; } + public final String getCallingAttributionTag(){ return null; } + public final String getCallingPackage(){ return null; } + public final String getCallingPackageUnchecked(){ return null; } + public final String getReadPermission(){ return null; } + public final String getWritePermission(){ return null; } + public final void restoreCallingIdentity(ContentProvider.CallingIdentity p0){} + public int bulkInsert(Uri p0, ContentValues[] p1){ return 0; } + public int delete(Uri p0, Bundle p1){ return 0; } + public int update(Uri p0, ContentValues p1, Bundle p2){ return 0; } + public void attachInfo(Context p0, ProviderInfo p1){} + public void dump(FileDescriptor p0, PrintWriter p1, String[] p2){} + public void onCallingPackageChanged(){} + public void onConfigurationChanged(Configuration p0){} + public void onLowMemory(){} + public void onTrimMemory(int p0){} + public void shutdown(){} + static public interface PipeDataWriter<T> + { + void writeDataToPipe(ParcelFileDescriptor p0, Uri p1, String p2, Bundle p3, T p4); + } } diff --git a/java/ql/test/stubs/android/android/content/ContentProviderClient.java b/java/ql/test/stubs/android/android/content/ContentProviderClient.java new file mode 100644 index 00000000000..0cb6890ad1b --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ContentProviderClient.java @@ -0,0 +1,49 @@ +// Generated automatically from android.content.ContentProviderClient for testing purposes + +package android.content; + +import android.content.ContentProvider; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentValues; +import android.content.res.AssetFileDescriptor; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.os.CancellationSignal; +import android.os.ParcelFileDescriptor; +import java.util.ArrayList; + +public class ContentProviderClient implements AutoCloseable +{ + protected void finalize(){} + public AssetFileDescriptor openAssetFile(Uri p0, String p1){ return null; } + public AssetFileDescriptor openAssetFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public Bundle call(String p0, String p1, Bundle p2){ return null; } + public Bundle call(String p0, String p1, String p2, Bundle p3){ return null; } + public ContentProvider getLocalContentProvider(){ return null; } + public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> p0){ return null; } + public ContentProviderResult[] applyBatch(String p0, ArrayList<ContentProviderOperation> p1){ return null; } + public Cursor query(Uri p0, String[] p1, Bundle p2, CancellationSignal p3){ return null; } + public Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4){ return null; } + public Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4, CancellationSignal p5){ return null; } + public ParcelFileDescriptor openFile(Uri p0, String p1){ return null; } + public ParcelFileDescriptor openFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public String getType(Uri p0){ return null; } + public String[] getStreamTypes(Uri p0, String p1){ return null; } + public Uri insert(Uri p0, ContentValues p1){ return null; } + public Uri insert(Uri p0, ContentValues p1, Bundle p2){ return null; } + public boolean refresh(Uri p0, Bundle p1, CancellationSignal p2){ return false; } + public boolean release(){ return false; } + public final AssetFileDescriptor openTypedAssetFile(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri p0, String p1, Bundle p2){ return null; } + public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public final Uri canonicalize(Uri p0){ return null; } + public final Uri uncanonicalize(Uri p0){ return null; } + public int bulkInsert(Uri p0, ContentValues[] p1){ return 0; } + public int delete(Uri p0, Bundle p1){ return 0; } + public int delete(Uri p0, String p1, String[] p2){ return 0; } + public int update(Uri p0, ContentValues p1, Bundle p2){ return 0; } + public int update(Uri p0, ContentValues p1, String p2, String[] p3){ return 0; } + public void close(){} +} diff --git a/java/ql/test/stubs/android/android/content/ContentProviderOperation.java b/java/ql/test/stubs/android/android/content/ContentProviderOperation.java new file mode 100644 index 00000000000..59fb8b366ca --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ContentProviderOperation.java @@ -0,0 +1,58 @@ +// Generated automatically from android.content.ContentProviderOperation for testing purposes + +package android.content; + +import android.content.ContentProvider; +import android.content.ContentProviderResult; +import android.content.ContentValues; +import android.net.Uri; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +public class ContentProviderOperation implements Parcelable +{ + public Bundle resolveExtrasBackReferences(ContentProviderResult[] p0, int p1){ return null; } + public ContentProviderResult apply(ContentProvider p0, ContentProviderResult[] p1, int p2){ return null; } + public ContentValues resolveValueBackReferences(ContentProviderResult[] p0, int p1){ return null; } + public String toString(){ return null; } + public String[] resolveSelectionArgsBackReferences(ContentProviderResult[] p0, int p1){ return null; } + public Uri getUri(){ return null; } + public boolean isAssertQuery(){ return false; } + public boolean isCall(){ return false; } + public boolean isDelete(){ return false; } + public boolean isExceptionAllowed(){ return false; } + public boolean isInsert(){ return false; } + public boolean isReadOperation(){ return false; } + public boolean isUpdate(){ return false; } + public boolean isWriteOperation(){ return false; } + public boolean isYieldAllowed(){ return false; } + public int describeContents(){ return 0; } + public static ContentProviderOperation.Builder newAssertQuery(Uri p0){ return null; } + public static ContentProviderOperation.Builder newCall(Uri p0, String p1, String p2){ return null; } + public static ContentProviderOperation.Builder newDelete(Uri p0){ return null; } + public static ContentProviderOperation.Builder newInsert(Uri p0){ return null; } + public static ContentProviderOperation.Builder newUpdate(Uri p0){ return null; } + public static Parcelable.Creator<ContentProviderOperation> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} + static public class Builder + { + protected Builder() {} + public ContentProviderOperation build(){ return null; } + public ContentProviderOperation.Builder withExceptionAllowed(boolean p0){ return null; } + public ContentProviderOperation.Builder withExpectedCount(int p0){ return null; } + public ContentProviderOperation.Builder withExtra(String p0, Object p1){ return null; } + public ContentProviderOperation.Builder withExtraBackReference(String p0, int p1){ return null; } + public ContentProviderOperation.Builder withExtraBackReference(String p0, int p1, String p2){ return null; } + public ContentProviderOperation.Builder withExtras(Bundle p0){ return null; } + public ContentProviderOperation.Builder withSelection(String p0, String[] p1){ return null; } + public ContentProviderOperation.Builder withSelectionBackReference(int p0, int p1){ return null; } + public ContentProviderOperation.Builder withSelectionBackReference(int p0, int p1, String p2){ return null; } + public ContentProviderOperation.Builder withValue(String p0, Object p1){ return null; } + public ContentProviderOperation.Builder withValueBackReference(String p0, int p1){ return null; } + public ContentProviderOperation.Builder withValueBackReference(String p0, int p1, String p2){ return null; } + public ContentProviderOperation.Builder withValueBackReferences(ContentValues p0){ return null; } + public ContentProviderOperation.Builder withValues(ContentValues p0){ return null; } + public ContentProviderOperation.Builder withYieldAllowed(boolean p0){ return null; } + } +} diff --git a/java/ql/test/stubs/android/android/content/ContentProviderResult.java b/java/ql/test/stubs/android/android/content/ContentProviderResult.java new file mode 100644 index 00000000000..b0f285d5c92 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ContentProviderResult.java @@ -0,0 +1,26 @@ +// Generated automatically from android.content.ContentProviderResult for testing purposes + +package android.content; + +import android.net.Uri; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +public class ContentProviderResult implements Parcelable +{ + protected ContentProviderResult() {} + public ContentProviderResult(Bundle p0){} + public ContentProviderResult(Parcel p0){} + public ContentProviderResult(Throwable p0){} + public ContentProviderResult(Uri p0){} + public ContentProviderResult(int p0){} + public String toString(){ return null; } + public final Bundle extras = null; + public final Integer count = null; + public final Throwable exception = null; + public final Uri uri = null; + public int describeContents(){ return 0; } + public static Parcelable.Creator<ContentProviderResult> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/ContentResolver.java b/java/ql/test/stubs/android/android/content/ContentResolver.java index 27308ee87be..1d03e20ecf9 100644 --- a/java/ql/test/stubs/android/android/content/ContentResolver.java +++ b/java/ql/test/stubs/android/android/content/ContentResolver.java @@ -1,17 +1,160 @@ +// Generated automatically from android.content.ContentResolver for testing purposes + package android.content; +import android.accounts.Account; +import android.content.ContentProvider; +import android.content.ContentProviderClient; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentValues; +import android.content.Context; +import android.content.PeriodicSync; +import android.content.SyncAdapterType; +import android.content.SyncInfo; +import android.content.SyncRequest; +import android.content.SyncStatusObserver; +import android.content.UriPermission; +import android.content.res.AssetFileDescriptor; +import android.database.ContentObserver; import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.drawable.Icon; import android.net.Uri; +import android.os.Bundle; import android.os.CancellationSignal; +import android.os.ParcelFileDescriptor; +import android.util.Size; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; -public abstract class ContentResolver { - public abstract int delete(Uri uri, String selection, String[] selectionArgs); - - public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, - CancellationSignal cancellationSignal); - - public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder); - - public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs); - +abstract public class ContentResolver +{ + protected ContentResolver() {} + public Bitmap loadThumbnail(Uri p0, Size p1, CancellationSignal p2){ return null; } + public ContentProviderResult[] applyBatch(String p0, ArrayList<ContentProviderOperation> p1){ return null; } + public ContentResolver(Context p0){} + public List<UriPermission> getOutgoingPersistedUriPermissions(){ return null; } + public List<UriPermission> getPersistedUriPermissions(){ return null; } + public String[] getStreamTypes(Uri p0, String p1){ return null; } + public final AssetFileDescriptor openAssetFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public final AssetFileDescriptor openAssetFileDescriptor(Uri p0, String p1){ return null; } + public final AssetFileDescriptor openAssetFileDescriptor(Uri p0, String p1, CancellationSignal p2){ return null; } + public final AssetFileDescriptor openTypedAssetFile(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri p0, String p1, Bundle p2){ return null; } + public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public final Bundle call(String p0, String p1, String p2, Bundle p3){ return null; } + public final Bundle call(Uri p0, String p1, String p2, Bundle p3){ return null; } + public final ContentProviderClient acquireContentProviderClient(String p0){ return null; } + public final ContentProviderClient acquireContentProviderClient(Uri p0){ return null; } + public final ContentProviderClient acquireUnstableContentProviderClient(String p0){ return null; } + public final ContentProviderClient acquireUnstableContentProviderClient(Uri p0){ return null; } + public final ContentResolver.MimeTypeInfo getTypeInfo(String p0){ return null; } + public final Cursor query(Uri p0, String[] p1, Bundle p2, CancellationSignal p3){ return null; } + public final Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4){ return null; } + public final Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4, CancellationSignal p5){ return null; } + public final InputStream openInputStream(Uri p0){ return null; } + public final OutputStream openOutputStream(Uri p0){ return null; } + public final OutputStream openOutputStream(Uri p0, String p1){ return null; } + public final ParcelFileDescriptor openFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public final ParcelFileDescriptor openFileDescriptor(Uri p0, String p1){ return null; } + public final ParcelFileDescriptor openFileDescriptor(Uri p0, String p1, CancellationSignal p2){ return null; } + public final String getType(Uri p0){ return null; } + public final Uri canonicalize(Uri p0){ return null; } + public final Uri insert(Uri p0, ContentValues p1){ return null; } + public final Uri insert(Uri p0, ContentValues p1, Bundle p2){ return null; } + public final Uri uncanonicalize(Uri p0){ return null; } + public final boolean refresh(Uri p0, Bundle p1, CancellationSignal p2){ return false; } + public final int bulkInsert(Uri p0, ContentValues[] p1){ return 0; } + public final int delete(Uri p0, Bundle p1){ return 0; } + public final int delete(Uri p0, String p1, String[] p2){ return 0; } + public final int update(Uri p0, ContentValues p1, Bundle p2){ return 0; } + public final int update(Uri p0, ContentValues p1, String p2, String[] p3){ return 0; } + public final void registerContentObserver(Uri p0, boolean p1, ContentObserver p2){} + public final void unregisterContentObserver(ContentObserver p0){} + public static ContentResolver wrap(ContentProvider p0){ return null; } + public static ContentResolver wrap(ContentProviderClient p0){ return null; } + public static List<PeriodicSync> getPeriodicSyncs(Account p0, String p1){ return null; } + public static List<SyncInfo> getCurrentSyncs(){ return null; } + public static Object addStatusChangeListener(int p0, SyncStatusObserver p1){ return null; } + public static String ANY_CURSOR_ITEM_TYPE = null; + public static String CURSOR_DIR_BASE_TYPE = null; + public static String CURSOR_ITEM_BASE_TYPE = null; + public static String EXTRA_HONORED_ARGS = null; + public static String EXTRA_REFRESH_SUPPORTED = null; + public static String EXTRA_SIZE = null; + public static String EXTRA_TOTAL_COUNT = null; + public static String QUERY_ARG_GROUP_COLUMNS = null; + public static String QUERY_ARG_LIMIT = null; + public static String QUERY_ARG_OFFSET = null; + public static String QUERY_ARG_SORT_COLLATION = null; + public static String QUERY_ARG_SORT_COLUMNS = null; + public static String QUERY_ARG_SORT_DIRECTION = null; + public static String QUERY_ARG_SORT_LOCALE = null; + public static String QUERY_ARG_SQL_GROUP_BY = null; + public static String QUERY_ARG_SQL_HAVING = null; + public static String QUERY_ARG_SQL_LIMIT = null; + public static String QUERY_ARG_SQL_SELECTION = null; + public static String QUERY_ARG_SQL_SELECTION_ARGS = null; + public static String QUERY_ARG_SQL_SORT_ORDER = null; + public static String SCHEME_ANDROID_RESOURCE = null; + public static String SCHEME_CONTENT = null; + public static String SCHEME_FILE = null; + public static String SYNC_EXTRAS_ACCOUNT = null; + public static String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = null; + public static String SYNC_EXTRAS_DO_NOT_RETRY = null; + public static String SYNC_EXTRAS_EXPEDITED = null; + public static String SYNC_EXTRAS_FORCE = null; + public static String SYNC_EXTRAS_IGNORE_BACKOFF = null; + public static String SYNC_EXTRAS_IGNORE_SETTINGS = null; + public static String SYNC_EXTRAS_INITIALIZE = null; + public static String SYNC_EXTRAS_MANUAL = null; + public static String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = null; + public static String SYNC_EXTRAS_REQUIRE_CHARGING = null; + public static String SYNC_EXTRAS_UPLOAD = null; + public static SyncAdapterType[] getSyncAdapterTypes(){ return null; } + public static SyncInfo getCurrentSync(){ return null; } + public static boolean getMasterSyncAutomatically(){ return false; } + public static boolean getSyncAutomatically(Account p0, String p1){ return false; } + public static boolean isSyncActive(Account p0, String p1){ return false; } + public static boolean isSyncPending(Account p0, String p1){ return false; } + public static int NOTIFY_DELETE = 0; + public static int NOTIFY_INSERT = 0; + public static int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 0; + public static int NOTIFY_SYNC_TO_NETWORK = 0; + public static int NOTIFY_UPDATE = 0; + public static int QUERY_SORT_DIRECTION_ASCENDING = 0; + public static int QUERY_SORT_DIRECTION_DESCENDING = 0; + public static int SYNC_OBSERVER_TYPE_ACTIVE = 0; + public static int SYNC_OBSERVER_TYPE_PENDING = 0; + public static int SYNC_OBSERVER_TYPE_SETTINGS = 0; + public static int getIsSyncable(Account p0, String p1){ return 0; } + public static void addPeriodicSync(Account p0, String p1, Bundle p2, long p3){} + public static void cancelSync(Account p0, String p1){} + public static void cancelSync(SyncRequest p0){} + public static void removePeriodicSync(Account p0, String p1, Bundle p2){} + public static void removeStatusChangeListener(Object p0){} + public static void requestSync(Account p0, String p1, Bundle p2){} + public static void requestSync(SyncRequest p0){} + public static void setIsSyncable(Account p0, String p1, int p2){} + public static void setMasterSyncAutomatically(boolean p0){} + public static void setSyncAutomatically(Account p0, String p1, boolean p2){} + public static void validateSyncExtrasBundle(Bundle p0){} + public void cancelSync(Uri p0){} + public void notifyChange(Collection<Uri> p0, ContentObserver p1, int p2){} + public void notifyChange(Uri p0, ContentObserver p1){} + public void notifyChange(Uri p0, ContentObserver p1, boolean p2){} + public void notifyChange(Uri p0, ContentObserver p1, int p2){} + public void releasePersistableUriPermission(Uri p0, int p1){} + public void startSync(Uri p0, Bundle p1){} + public void takePersistableUriPermission(Uri p0, int p1){} + static public class MimeTypeInfo + { + public CharSequence getContentDescription(){ return null; } + public CharSequence getLabel(){ return null; } + public Icon getIcon(){ return null; } + } } diff --git a/java/ql/test/stubs/android/android/content/ContentValues.java b/java/ql/test/stubs/android/android/content/ContentValues.java index 105c3092d79..f85e1462717 100644 --- a/java/ql/test/stubs/android/android/content/ContentValues.java +++ b/java/ql/test/stubs/android/android/content/ContentValues.java @@ -1,5 +1,50 @@ +// Generated automatically from android.content.ContentValues for testing purposes + package android.content; -public class ContentValues { +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Map; +import java.util.Set; +public class ContentValues implements Parcelable +{ + public Boolean getAsBoolean(String p0){ return null; } + public Byte getAsByte(String p0){ return null; } + public ContentValues(){} + public ContentValues(ContentValues p0){} + public ContentValues(int p0){} + public Double getAsDouble(String p0){ return null; } + public Float getAsFloat(String p0){ return null; } + public Integer getAsInteger(String p0){ return null; } + public Long getAsLong(String p0){ return null; } + public Object get(String p0){ return null; } + public Set<Map.Entry<String, Object>> valueSet(){ return null; } + public Set<String> keySet(){ return null; } + public Short getAsShort(String p0){ return null; } + public String getAsString(String p0){ return null; } + public String toString(){ return null; } + public boolean containsKey(String p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public byte[] getAsByteArray(String p0){ return null; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public static Parcelable.Creator<ContentValues> CREATOR = null; + public static String TAG = null; + public void clear(){} + public void put(String p0, Boolean p1){} + public void put(String p0, Byte p1){} + public void put(String p0, Double p1){} + public void put(String p0, Float p1){} + public void put(String p0, Integer p1){} + public void put(String p0, Long p1){} + public void put(String p0, Short p1){} + public void put(String p0, String p1){} + public void put(String p0, byte[] p1){} + public void putAll(ContentValues p0){} + public void putNull(String p0){} + public void remove(String p0){} + public void writeToParcel(Parcel p0, int p1){} } diff --git a/java/ql/test/stubs/android/android/content/Context.java b/java/ql/test/stubs/android/android/content/Context.java index 118e170d788..7e507e89095 100644 --- a/java/ql/test/stubs/android/android/content/Context.java +++ b/java/ql/test/stubs/android/android/content/Context.java @@ -1,5 +1,265 @@ +// Generated automatically from android.content.Context for testing purposes + package android.content; -public class Context { +import android.content.BroadcastReceiver; +import android.content.ComponentCallbacks; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.IntentSender; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.AssetManager; +import android.content.res.ColorStateList; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.database.DatabaseErrorHandler; +import android.database.sqlite.SQLiteDatabase; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.util.AttributeSet; +import android.view.Display; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.concurrent.Executor; +abstract public class Context +{ + public Context createAttributionContext(String p0){ return null; } + public Context createWindowContext(int p0, Bundle p1){ return null; } + public Context(){} + public Display getDisplay(){ return null; } + public Executor getMainExecutor(){ return null; } + public String getAttributionTag(){ return null; } + public String getOpPackageName(){ return null; } + public abstract ApplicationInfo getApplicationInfo(); + public abstract AssetManager getAssets(); + public abstract ClassLoader getClassLoader(); + public abstract ComponentName startForegroundService(Intent p0); + public abstract ComponentName startService(Intent p0); + public abstract ContentResolver getContentResolver(); + public abstract Context createConfigurationContext(Configuration p0); + public abstract Context createContextForSplit(String p0); + public abstract Context createDeviceProtectedStorageContext(); + public abstract Context createDisplayContext(Display p0); + public abstract Context createPackageContext(String p0, int p1); + public abstract Context getApplicationContext(); + public abstract Drawable getWallpaper(); + public abstract Drawable peekWallpaper(); + public abstract File getCacheDir(); + public abstract File getCodeCacheDir(); + public abstract File getDataDir(); + public abstract File getDatabasePath(String p0); + public abstract File getDir(String p0, int p1); + public abstract File getExternalCacheDir(); + public abstract File getExternalFilesDir(String p0); + public abstract File getFileStreamPath(String p0); + public abstract File getFilesDir(); + public abstract File getNoBackupFilesDir(); + public abstract File getObbDir(); + public abstract FileInputStream openFileInput(String p0); + public abstract FileOutputStream openFileOutput(String p0, int p1); + public abstract File[] getExternalCacheDirs(); + public abstract File[] getExternalFilesDirs(String p0); + public abstract File[] getExternalMediaDirs(); + public abstract File[] getObbDirs(); + public abstract Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1); + public abstract Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, String p2, Handler p3); + public abstract Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, String p2, Handler p3, int p4); + public abstract Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, int p2); + public abstract Looper getMainLooper(); + public abstract Object getSystemService(String p0); + public abstract PackageManager getPackageManager(); + public abstract Resources getResources(); + public abstract Resources.Theme getTheme(); + public abstract SQLiteDatabase openOrCreateDatabase(String p0, int p1, SQLiteDatabase.CursorFactory p2); + public abstract SQLiteDatabase openOrCreateDatabase(String p0, int p1, SQLiteDatabase.CursorFactory p2, DatabaseErrorHandler p3); + public abstract SharedPreferences getSharedPreferences(String p0, int p1); + public abstract String getPackageCodePath(); + public abstract String getPackageName(); + public abstract String getPackageResourcePath(); + public abstract String getSystemServiceName(Class<? extends Object> p0); + public abstract String[] databaseList(); + public abstract String[] fileList(); + public abstract boolean bindService(Intent p0, ServiceConnection p1, int p2); + public abstract boolean deleteDatabase(String p0); + public abstract boolean deleteFile(String p0); + public abstract boolean deleteSharedPreferences(String p0); + public abstract boolean isDeviceProtectedStorage(); + public abstract boolean moveDatabaseFrom(Context p0, String p1); + public abstract boolean moveSharedPreferencesFrom(Context p0, String p1); + public abstract boolean startInstrumentation(ComponentName p0, String p1, Bundle p2); + public abstract boolean stopService(Intent p0); + public abstract int checkCallingOrSelfPermission(String p0); + public abstract int checkCallingOrSelfUriPermission(Uri p0, int p1); + public abstract int checkCallingPermission(String p0); + public abstract int checkCallingUriPermission(Uri p0, int p1); + public abstract int checkPermission(String p0, int p1, int p2); + public abstract int checkSelfPermission(String p0); + public abstract int checkUriPermission(Uri p0, String p1, String p2, int p3, int p4, int p5); + public abstract int checkUriPermission(Uri p0, int p1, int p2, int p3); + public abstract int getWallpaperDesiredMinimumHeight(); + public abstract int getWallpaperDesiredMinimumWidth(); + public abstract void clearWallpaper(); + public abstract void enforceCallingOrSelfPermission(String p0, String p1); + public abstract void enforceCallingOrSelfUriPermission(Uri p0, int p1, String p2); + public abstract void enforceCallingPermission(String p0, String p1); + public abstract void enforceCallingUriPermission(Uri p0, int p1, String p2); + public abstract void enforcePermission(String p0, int p1, int p2, String p3); + public abstract void enforceUriPermission(Uri p0, String p1, String p2, int p3, int p4, int p5, String p6); + public abstract void enforceUriPermission(Uri p0, int p1, int p2, int p3, String p4); + public abstract void grantUriPermission(String p0, Uri p1, int p2); + public abstract void removeStickyBroadcast(Intent p0); + public abstract void removeStickyBroadcastAsUser(Intent p0, UserHandle p1); + public abstract void revokeUriPermission(String p0, Uri p1, int p2); + public abstract void revokeUriPermission(Uri p0, int p1); + public abstract void sendBroadcast(Intent p0); + public abstract void sendBroadcast(Intent p0, String p1); + public abstract void sendBroadcastAsUser(Intent p0, UserHandle p1); + public abstract void sendBroadcastAsUser(Intent p0, UserHandle p1, String p2); + public abstract void sendOrderedBroadcast(Intent p0, String p1); + public abstract void sendOrderedBroadcast(Intent p0, String p1, BroadcastReceiver p2, Handler p3, int p4, String p5, Bundle p6); + public abstract void sendOrderedBroadcastAsUser(Intent p0, UserHandle p1, String p2, BroadcastReceiver p3, Handler p4, int p5, String p6, Bundle p7); + public abstract void sendStickyBroadcast(Intent p0); + public abstract void sendStickyBroadcastAsUser(Intent p0, UserHandle p1); + public abstract void sendStickyOrderedBroadcast(Intent p0, BroadcastReceiver p1, Handler p2, int p3, String p4, Bundle p5); + public abstract void sendStickyOrderedBroadcastAsUser(Intent p0, UserHandle p1, BroadcastReceiver p2, Handler p3, int p4, String p5, Bundle p6); + public abstract void setTheme(int p0); + public abstract void setWallpaper(Bitmap p0); + public abstract void setWallpaper(InputStream p0); + public abstract void startActivities(Intent[] p0); + public abstract void startActivities(Intent[] p0, Bundle p1); + public abstract void startActivity(Intent p0); + public abstract void startActivity(Intent p0, Bundle p1); + public abstract void startIntentSender(IntentSender p0, Intent p1, int p2, int p3, int p4); + public abstract void startIntentSender(IntentSender p0, Intent p1, int p2, int p3, int p4, Bundle p5); + public abstract void unbindService(ServiceConnection p0); + public abstract void unregisterReceiver(BroadcastReceiver p0); + public boolean bindIsolatedService(Intent p0, int p1, String p2, Executor p3, ServiceConnection p4){ return false; } + public boolean bindService(Intent p0, int p1, Executor p2, ServiceConnection p3){ return false; } + public boolean bindServiceAsUser(Intent p0, ServiceConnection p1, int p2, UserHandle p3){ return false; } + public boolean isRestricted(){ return false; } + public final <T> T getSystemService(Class<T> p0){ return null; } + public final CharSequence getText(int p0){ return null; } + public final ColorStateList getColorStateList(int p0){ return null; } + public final Drawable getDrawable(int p0){ return null; } + public final String getString(int p0){ return null; } + public final String getString(int p0, Object... p1){ return null; } + public final TypedArray obtainStyledAttributes(AttributeSet p0, int[] p1){ return null; } + public final TypedArray obtainStyledAttributes(AttributeSet p0, int[] p1, int p2, int p3){ return null; } + public final TypedArray obtainStyledAttributes(int p0, int[] p1){ return null; } + public final TypedArray obtainStyledAttributes(int[] p0){ return null; } + public final int getColor(int p0){ return 0; } + public static String ACCESSIBILITY_SERVICE = null; + public static String ACCOUNT_SERVICE = null; + public static String ACTIVITY_SERVICE = null; + public static String ALARM_SERVICE = null; + public static String APPWIDGET_SERVICE = null; + public static String APP_OPS_SERVICE = null; + public static String AUDIO_SERVICE = null; + public static String BATTERY_SERVICE = null; + public static String BIOMETRIC_SERVICE = null; + public static String BLOB_STORE_SERVICE = null; + public static String BLUETOOTH_SERVICE = null; + public static String CAMERA_SERVICE = null; + public static String CAPTIONING_SERVICE = null; + public static String CARRIER_CONFIG_SERVICE = null; + public static String CLIPBOARD_SERVICE = null; + public static String COMPANION_DEVICE_SERVICE = null; + public static String CONNECTIVITY_DIAGNOSTICS_SERVICE = null; + public static String CONNECTIVITY_SERVICE = null; + public static String CONSUMER_IR_SERVICE = null; + public static String CROSS_PROFILE_APPS_SERVICE = null; + public static String DEVICE_POLICY_SERVICE = null; + public static String DISPLAY_SERVICE = null; + public static String DOWNLOAD_SERVICE = null; + public static String DROPBOX_SERVICE = null; + public static String EUICC_SERVICE = null; + public static String FILE_INTEGRITY_SERVICE = null; + public static String FINGERPRINT_SERVICE = null; + public static String HARDWARE_PROPERTIES_SERVICE = null; + public static String INPUT_METHOD_SERVICE = null; + public static String INPUT_SERVICE = null; + public static String IPSEC_SERVICE = null; + public static String JOB_SCHEDULER_SERVICE = null; + public static String KEYGUARD_SERVICE = null; + public static String LAUNCHER_APPS_SERVICE = null; + public static String LAYOUT_INFLATER_SERVICE = null; + public static String LOCATION_SERVICE = null; + public static String MEDIA_PROJECTION_SERVICE = null; + public static String MEDIA_ROUTER_SERVICE = null; + public static String MEDIA_SESSION_SERVICE = null; + public static String MIDI_SERVICE = null; + public static String NETWORK_STATS_SERVICE = null; + public static String NFC_SERVICE = null; + public static String NOTIFICATION_SERVICE = null; + public static String NSD_SERVICE = null; + public static String POWER_SERVICE = null; + public static String PRINT_SERVICE = null; + public static String RESTRICTIONS_SERVICE = null; + public static String ROLE_SERVICE = null; + public static String SEARCH_SERVICE = null; + public static String SENSOR_SERVICE = null; + public static String SHORTCUT_SERVICE = null; + public static String STORAGE_SERVICE = null; + public static String STORAGE_STATS_SERVICE = null; + public static String SYSTEM_HEALTH_SERVICE = null; + public static String TELECOM_SERVICE = null; + public static String TELEPHONY_IMS_SERVICE = null; + public static String TELEPHONY_SERVICE = null; + public static String TELEPHONY_SUBSCRIPTION_SERVICE = null; + public static String TEXT_CLASSIFICATION_SERVICE = null; + public static String TEXT_SERVICES_MANAGER_SERVICE = null; + public static String TV_INPUT_SERVICE = null; + public static String UI_MODE_SERVICE = null; + public static String USAGE_STATS_SERVICE = null; + public static String USB_SERVICE = null; + public static String USER_SERVICE = null; + public static String VIBRATOR_SERVICE = null; + public static String VPN_MANAGEMENT_SERVICE = null; + public static String WALLPAPER_SERVICE = null; + public static String WIFI_AWARE_SERVICE = null; + public static String WIFI_P2P_SERVICE = null; + public static String WIFI_RTT_RANGING_SERVICE = null; + public static String WIFI_SERVICE = null; + public static String WINDOW_SERVICE = null; + public static int BIND_ABOVE_CLIENT = 0; + public static int BIND_ADJUST_WITH_ACTIVITY = 0; + public static int BIND_ALLOW_OOM_MANAGEMENT = 0; + public static int BIND_AUTO_CREATE = 0; + public static int BIND_DEBUG_UNBIND = 0; + public static int BIND_EXTERNAL_SERVICE = 0; + public static int BIND_IMPORTANT = 0; + public static int BIND_INCLUDE_CAPABILITIES = 0; + public static int BIND_NOT_FOREGROUND = 0; + public static int BIND_NOT_PERCEPTIBLE = 0; + public static int BIND_WAIVE_PRIORITY = 0; + public static int CONTEXT_IGNORE_SECURITY = 0; + public static int CONTEXT_INCLUDE_CODE = 0; + public static int CONTEXT_RESTRICTED = 0; + public static int MODE_APPEND = 0; + public static int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0; + public static int MODE_MULTI_PROCESS = 0; + public static int MODE_NO_LOCALIZED_COLLATORS = 0; + public static int MODE_PRIVATE = 0; + public static int MODE_WORLD_READABLE = 0; + public static int MODE_WORLD_WRITEABLE = 0; + public static int RECEIVER_VISIBLE_TO_INSTANT_APPS = 0; + public void registerComponentCallbacks(ComponentCallbacks p0){} + public void sendBroadcastWithMultiplePermissions(Intent p0, String[] p1){} + public void sendOrderedBroadcast(Intent p0, String p1, String p2, BroadcastReceiver p3, Handler p4, int p5, String p6, Bundle p7){} + public void unregisterComponentCallbacks(ComponentCallbacks p0){} + public void updateServiceGroup(ServiceConnection p0, int p1, int p2){} } diff --git a/java/ql/test/stubs/android/android/content/Intent.java b/java/ql/test/stubs/android/android/content/Intent.java index 32b167509d3..d3dd30a8fc4 100644 --- a/java/ql/test/stubs/android/android/content/Intent.java +++ b/java/ql/test/stubs/android/android/content/Intent.java @@ -1,196 +1,461 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.content.Intent for testing purposes package android.content; +import android.content.ClipData; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.IntentSender; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; - -import java.io.PrintWriter; -import java.net.URISyntaxException; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import java.io.Serializable; +import java.util.ArrayList; import java.util.Set; +import org.xmlpull.v1.XmlPullParser; -public class Intent implements Cloneable { - - public static Intent createChooser(Intent target, CharSequence title) { - return null; - } - - public Intent() { - } - - public Intent(Intent o) { - } - - @Override - public Object clone() { - return null; - } - - public Intent(String action) { - } - - public Intent(String action, Uri uri) { - } - - public Intent(Context packageContext, Class<?> cls) { - } - - public Intent(String action, Uri uri, Context packageContext, Class<?> cls) { - } - - public static Intent makeMainSelectorActivity(String selectorAction, String selectorCategory) { - return null; - } - - public static Intent getIntent(String uri) throws URISyntaxException { - return null; - } - - public static Intent getIntentOld(String uri) throws URISyntaxException { - return null; - } - - public static void printIntentArgsHelp(PrintWriter pw, String prefix) { - } - - public boolean hasCategory(String category) { - return false; - } - - public Set<String> getCategories() { - return null; - } - - public int getContentUserHint() { - return 0; - } - - public String getLaunchToken() { - return null; - } - - public void setLaunchToken(String launchToken) { - } - - public boolean hasExtra(String name) { - return false; - } - - public boolean hasFileDescriptors() { - return false; - } - - public void setAllowFds(boolean allowFds) { - } - - public void setDefusable(boolean defusable) { - } - - public Object getExtra(String name) { - return null; - } - - public boolean getBooleanExtra(String name, boolean defaultValue) { - return false; - } - - public byte getByteExtra(String name, byte defaultValue) { - return 0; - } - - public short getShortExtra(String name, short defaultValue) { - return 0; - } - - public char getCharExtra(String name, char defaultValue) { - return '0'; - } - - public int getIntExtra(String name, int defaultValue) { - return 0; - } - - public long getLongExtra(String name, long defaultValue) { - return 0; - } - - public float getFloatExtra(String name, float defaultValue) { - return 0; - } - - public double getDoubleExtra(String name, double defaultValue) { - return 0; - } - - public String getStringExtra(String string) { - return null; - } - - public void removeUnsafeExtras() { - } - - public boolean canStripForHistory() { - return false; - } - - public Intent maybeStripForHistory() { - return null; - } - - public boolean isExcludingStopped() { - return false; - } - - public void removeCategory(String category) { - } - - public void prepareToLeaveUser(int userId) { - } - - public boolean filterEquals(Intent other) { - return false; - } - - public int filterHashCode() { - return 0; - } - - @Override - public String toString() { - return null; - } - - public String toInsecureString() { - return null; - } - - public String toInsecureStringWithClip() { - return null; - } - - public String toShortString(boolean secure, boolean comp, boolean extras, boolean clip) { - return null; - } - - public void toShortString(StringBuilder b, boolean secure, boolean comp, boolean extras, boolean clip) { - } - - public Bundle getExtras() { - return null; - } - +public class Intent implements Cloneable, Parcelable +{ + public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String p0){ return null; } + public <T extends Parcelable> T getParcelableExtra(String p0){ return null; } + public ActivityInfo resolveActivityInfo(PackageManager p0, int p1){ return null; } + public ArrayList<CharSequence> getCharSequenceArrayListExtra(String p0){ return null; } + public ArrayList<Integer> getIntegerArrayListExtra(String p0){ return null; } + public ArrayList<String> getStringArrayListExtra(String p0){ return null; } + public Bundle getBundleExtra(String p0){ return null; } + public Bundle getExtras(){ return null; } + public CharSequence getCharSequenceExtra(String p0){ return null; } + public CharSequence[] getCharSequenceArrayExtra(String p0){ return null; } + public ClipData getClipData(){ return null; } + public ComponentName getComponent(){ return null; } + public ComponentName resolveActivity(PackageManager p0){ return null; } + public Intent addCategory(String p0){ return null; } + public Intent addFlags(int p0){ return null; } + public Intent cloneFilter(){ return null; } + public Intent getSelector(){ return null; } + public Intent putCharSequenceArrayListExtra(String p0, ArrayList<CharSequence> p1){ return null; } + public Intent putExtra(String p0, Bundle p1){ return null; } + public Intent putExtra(String p0, CharSequence p1){ return null; } + public Intent putExtra(String p0, CharSequence[] p1){ return null; } + public Intent putExtra(String p0, Parcelable p1){ return null; } + public Intent putExtra(String p0, Parcelable[] p1){ return null; } + public Intent putExtra(String p0, Serializable p1){ return null; } + public Intent putExtra(String p0, String p1){ return null; } + public Intent putExtra(String p0, String[] p1){ return null; } + public Intent putExtra(String p0, boolean p1){ return null; } + public Intent putExtra(String p0, boolean[] p1){ return null; } + public Intent putExtra(String p0, byte p1){ return null; } + public Intent putExtra(String p0, byte[] p1){ return null; } + public Intent putExtra(String p0, char p1){ return null; } + public Intent putExtra(String p0, char[] p1){ return null; } + public Intent putExtra(String p0, double p1){ return null; } + public Intent putExtra(String p0, double[] p1){ return null; } + public Intent putExtra(String p0, float p1){ return null; } + public Intent putExtra(String p0, float[] p1){ return null; } + public Intent putExtra(String p0, int p1){ return null; } + public Intent putExtra(String p0, int[] p1){ return null; } + public Intent putExtra(String p0, long p1){ return null; } + public Intent putExtra(String p0, long[] p1){ return null; } + public Intent putExtra(String p0, short p1){ return null; } + public Intent putExtra(String p0, short[] p1){ return null; } + public Intent putExtras(Bundle p0){ return null; } + public Intent putExtras(Intent p0){ return null; } + public Intent putIntegerArrayListExtra(String p0, ArrayList<Integer> p1){ return null; } + public Intent putParcelableArrayListExtra(String p0, ArrayList<? extends Parcelable> p1){ return null; } + public Intent putStringArrayListExtra(String p0, ArrayList<String> p1){ return null; } + public Intent replaceExtras(Bundle p0){ return null; } + public Intent replaceExtras(Intent p0){ return null; } + public Intent setAction(String p0){ return null; } + public Intent setClass(Context p0, Class<? extends Object> p1){ return null; } + public Intent setClassName(Context p0, String p1){ return null; } + public Intent setClassName(String p0, String p1){ return null; } + public Intent setComponent(ComponentName p0){ return null; } + public Intent setData(Uri p0){ return null; } + public Intent setDataAndNormalize(Uri p0){ return null; } + public Intent setDataAndType(Uri p0, String p1){ return null; } + public Intent setDataAndTypeAndNormalize(Uri p0, String p1){ return null; } + public Intent setFlags(int p0){ return null; } + public Intent setIdentifier(String p0){ return null; } + public Intent setPackage(String p0){ return null; } + public Intent setType(String p0){ return null; } + public Intent setTypeAndNormalize(String p0){ return null; } + public Intent(){} + public Intent(Context p0, Class<? extends Object> p1){} + public Intent(Intent p0){} + public Intent(String p0){} + public Intent(String p0, Uri p1){} + public Intent(String p0, Uri p1, Context p2, Class<? extends Object> p3){} + public Object clone(){ return null; } + public Parcelable[] getParcelableArrayExtra(String p0){ return null; } + public Rect getSourceBounds(){ return null; } + public Serializable getSerializableExtra(String p0){ return null; } + public Set<String> getCategories(){ return null; } + public String getAction(){ return null; } + public String getDataString(){ return null; } + public String getIdentifier(){ return null; } + public String getPackage(){ return null; } + public String getScheme(){ return null; } + public String getStringExtra(String p0){ return null; } + public String getType(){ return null; } + public String resolveType(ContentResolver p0){ return null; } + public String resolveType(Context p0){ return null; } + public String resolveTypeIfNeeded(ContentResolver p0){ return null; } + public String toString(){ return null; } + public String toURI(){ return null; } + public String toUri(int p0){ return null; } + public String[] getStringArrayExtra(String p0){ return null; } + public Uri getData(){ return null; } + public boolean filterEquals(Intent p0){ return false; } + public boolean getBooleanExtra(String p0, boolean p1){ return false; } + public boolean hasCategory(String p0){ return false; } + public boolean hasExtra(String p0){ return false; } + public boolean hasFileDescriptors(){ return false; } + public boolean[] getBooleanArrayExtra(String p0){ return null; } + public byte getByteExtra(String p0, byte p1){ return 0; } + public byte[] getByteArrayExtra(String p0){ return null; } + public char getCharExtra(String p0, char p1){ return '0'; } + public char[] getCharArrayExtra(String p0){ return null; } + public double getDoubleExtra(String p0, double p1){ return 0; } + public double[] getDoubleArrayExtra(String p0){ return null; } + public float getFloatExtra(String p0, float p1){ return 0; } + public float[] getFloatArrayExtra(String p0){ return null; } + public int describeContents(){ return 0; } + public int fillIn(Intent p0, int p1){ return 0; } + public int filterHashCode(){ return 0; } + public int getFlags(){ return 0; } + public int getIntExtra(String p0, int p1){ return 0; } + public int[] getIntArrayExtra(String p0){ return null; } + public long getLongExtra(String p0, long p1){ return 0; } + public long[] getLongArrayExtra(String p0){ return null; } + public short getShortExtra(String p0, short p1){ return 0; } + public short[] getShortArrayExtra(String p0){ return null; } + public static Intent createChooser(Intent p0, CharSequence p1){ return null; } + public static Intent createChooser(Intent p0, CharSequence p1, IntentSender p2){ return null; } + public static Intent getIntent(String p0){ return null; } + public static Intent getIntentOld(String p0){ return null; } + public static Intent makeMainActivity(ComponentName p0){ return null; } + public static Intent makeMainSelectorActivity(String p0, String p1){ return null; } + public static Intent makeRestartActivityTask(ComponentName p0){ return null; } + public static Intent parseIntent(Resources p0, XmlPullParser p1, AttributeSet p2){ return null; } + public static Intent parseUri(String p0, int p1){ return null; } + public static Parcelable.Creator<Intent> CREATOR = null; + public static String ACTION_AIRPLANE_MODE_CHANGED = null; + public static String ACTION_ALL_APPS = null; + public static String ACTION_ANSWER = null; + public static String ACTION_APPLICATION_PREFERENCES = null; + public static String ACTION_APPLICATION_RESTRICTIONS_CHANGED = null; + public static String ACTION_APP_ERROR = null; + public static String ACTION_ASSIST = null; + public static String ACTION_ATTACH_DATA = null; + public static String ACTION_AUTO_REVOKE_PERMISSIONS = null; + public static String ACTION_BATTERY_CHANGED = null; + public static String ACTION_BATTERY_LOW = null; + public static String ACTION_BATTERY_OKAY = null; + public static String ACTION_BOOT_COMPLETED = null; + public static String ACTION_BUG_REPORT = null; + public static String ACTION_CALL = null; + public static String ACTION_CALL_BUTTON = null; + public static String ACTION_CAMERA_BUTTON = null; + public static String ACTION_CARRIER_SETUP = null; + public static String ACTION_CHOOSER = null; + public static String ACTION_CLOSE_SYSTEM_DIALOGS = null; + public static String ACTION_CONFIGURATION_CHANGED = null; + public static String ACTION_CREATE_DOCUMENT = null; + public static String ACTION_CREATE_REMINDER = null; + public static String ACTION_CREATE_SHORTCUT = null; + public static String ACTION_DATE_CHANGED = null; + public static String ACTION_DEFAULT = null; + public static String ACTION_DEFINE = null; + public static String ACTION_DELETE = null; + public static String ACTION_DEVICE_STORAGE_LOW = null; + public static String ACTION_DEVICE_STORAGE_OK = null; + public static String ACTION_DIAL = null; + public static String ACTION_DOCK_EVENT = null; + public static String ACTION_DREAMING_STARTED = null; + public static String ACTION_DREAMING_STOPPED = null; + public static String ACTION_EDIT = null; + public static String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = null; + public static String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = null; + public static String ACTION_FACTORY_TEST = null; + public static String ACTION_GET_CONTENT = null; + public static String ACTION_GET_RESTRICTION_ENTRIES = null; + public static String ACTION_GTALK_SERVICE_CONNECTED = null; + public static String ACTION_GTALK_SERVICE_DISCONNECTED = null; + public static String ACTION_HEADSET_PLUG = null; + public static String ACTION_INPUT_METHOD_CHANGED = null; + public static String ACTION_INSERT = null; + public static String ACTION_INSERT_OR_EDIT = null; + public static String ACTION_INSTALL_FAILURE = null; + public static String ACTION_INSTALL_PACKAGE = null; + public static String ACTION_LOCALE_CHANGED = null; + public static String ACTION_LOCKED_BOOT_COMPLETED = null; + public static String ACTION_MAIN = null; + public static String ACTION_MANAGED_PROFILE_ADDED = null; + public static String ACTION_MANAGED_PROFILE_AVAILABLE = null; + public static String ACTION_MANAGED_PROFILE_REMOVED = null; + public static String ACTION_MANAGED_PROFILE_UNAVAILABLE = null; + public static String ACTION_MANAGED_PROFILE_UNLOCKED = null; + public static String ACTION_MANAGE_NETWORK_USAGE = null; + public static String ACTION_MANAGE_PACKAGE_STORAGE = null; + public static String ACTION_MEDIA_BAD_REMOVAL = null; + public static String ACTION_MEDIA_BUTTON = null; + public static String ACTION_MEDIA_CHECKING = null; + public static String ACTION_MEDIA_EJECT = null; + public static String ACTION_MEDIA_MOUNTED = null; + public static String ACTION_MEDIA_NOFS = null; + public static String ACTION_MEDIA_REMOVED = null; + public static String ACTION_MEDIA_SCANNER_FINISHED = null; + public static String ACTION_MEDIA_SCANNER_SCAN_FILE = null; + public static String ACTION_MEDIA_SCANNER_STARTED = null; + public static String ACTION_MEDIA_SHARED = null; + public static String ACTION_MEDIA_UNMOUNTABLE = null; + public static String ACTION_MEDIA_UNMOUNTED = null; + public static String ACTION_MY_PACKAGE_REPLACED = null; + public static String ACTION_MY_PACKAGE_SUSPENDED = null; + public static String ACTION_MY_PACKAGE_UNSUSPENDED = null; + public static String ACTION_NEW_OUTGOING_CALL = null; + public static String ACTION_OPEN_DOCUMENT = null; + public static String ACTION_OPEN_DOCUMENT_TREE = null; + public static String ACTION_PACKAGES_SUSPENDED = null; + public static String ACTION_PACKAGES_UNSUSPENDED = null; + public static String ACTION_PACKAGE_ADDED = null; + public static String ACTION_PACKAGE_CHANGED = null; + public static String ACTION_PACKAGE_DATA_CLEARED = null; + public static String ACTION_PACKAGE_FIRST_LAUNCH = null; + public static String ACTION_PACKAGE_FULLY_REMOVED = null; + public static String ACTION_PACKAGE_INSTALL = null; + public static String ACTION_PACKAGE_NEEDS_VERIFICATION = null; + public static String ACTION_PACKAGE_REMOVED = null; + public static String ACTION_PACKAGE_REPLACED = null; + public static String ACTION_PACKAGE_RESTARTED = null; + public static String ACTION_PACKAGE_VERIFIED = null; + public static String ACTION_PASTE = null; + public static String ACTION_PICK = null; + public static String ACTION_PICK_ACTIVITY = null; + public static String ACTION_POWER_CONNECTED = null; + public static String ACTION_POWER_DISCONNECTED = null; + public static String ACTION_POWER_USAGE_SUMMARY = null; + public static String ACTION_PROCESS_TEXT = null; + public static String ACTION_PROVIDER_CHANGED = null; + public static String ACTION_QUICK_CLOCK = null; + public static String ACTION_QUICK_VIEW = null; + public static String ACTION_REBOOT = null; + public static String ACTION_RUN = null; + public static String ACTION_SCREEN_OFF = null; + public static String ACTION_SCREEN_ON = null; + public static String ACTION_SEARCH = null; + public static String ACTION_SEARCH_LONG_PRESS = null; + public static String ACTION_SEND = null; + public static String ACTION_SENDTO = null; + public static String ACTION_SEND_MULTIPLE = null; + public static String ACTION_SET_WALLPAPER = null; + public static String ACTION_SHOW_APP_INFO = null; + public static String ACTION_SHUTDOWN = null; + public static String ACTION_SYNC = null; + public static String ACTION_SYSTEM_TUTORIAL = null; + public static String ACTION_TIMEZONE_CHANGED = null; + public static String ACTION_TIME_CHANGED = null; + public static String ACTION_TIME_TICK = null; + public static String ACTION_TRANSLATE = null; + public static String ACTION_UID_REMOVED = null; + public static String ACTION_UMS_CONNECTED = null; + public static String ACTION_UMS_DISCONNECTED = null; + public static String ACTION_UNINSTALL_PACKAGE = null; + public static String ACTION_USER_BACKGROUND = null; + public static String ACTION_USER_FOREGROUND = null; + public static String ACTION_USER_INITIALIZE = null; + public static String ACTION_USER_PRESENT = null; + public static String ACTION_USER_UNLOCKED = null; + public static String ACTION_VIEW = null; + public static String ACTION_VIEW_LOCUS = null; + public static String ACTION_VIEW_PERMISSION_USAGE = null; + public static String ACTION_VOICE_COMMAND = null; + public static String ACTION_WALLPAPER_CHANGED = null; + public static String ACTION_WEB_SEARCH = null; + public static String CATEGORY_ACCESSIBILITY_SHORTCUT_TARGET = null; + public static String CATEGORY_ALTERNATIVE = null; + public static String CATEGORY_APP_BROWSER = null; + public static String CATEGORY_APP_CALCULATOR = null; + public static String CATEGORY_APP_CALENDAR = null; + public static String CATEGORY_APP_CONTACTS = null; + public static String CATEGORY_APP_EMAIL = null; + public static String CATEGORY_APP_FILES = null; + public static String CATEGORY_APP_GALLERY = null; + public static String CATEGORY_APP_MAPS = null; + public static String CATEGORY_APP_MARKET = null; + public static String CATEGORY_APP_MESSAGING = null; + public static String CATEGORY_APP_MUSIC = null; + public static String CATEGORY_BROWSABLE = null; + public static String CATEGORY_CAR_DOCK = null; + public static String CATEGORY_CAR_MODE = null; + public static String CATEGORY_DEFAULT = null; + public static String CATEGORY_DESK_DOCK = null; + public static String CATEGORY_DEVELOPMENT_PREFERENCE = null; + public static String CATEGORY_EMBED = null; + public static String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST = null; + public static String CATEGORY_HE_DESK_DOCK = null; + public static String CATEGORY_HOME = null; + public static String CATEGORY_INFO = null; + public static String CATEGORY_LAUNCHER = null; + public static String CATEGORY_LEANBACK_LAUNCHER = null; + public static String CATEGORY_LE_DESK_DOCK = null; + public static String CATEGORY_MONKEY = null; + public static String CATEGORY_OPENABLE = null; + public static String CATEGORY_PREFERENCE = null; + public static String CATEGORY_SAMPLE_CODE = null; + public static String CATEGORY_SECONDARY_HOME = null; + public static String CATEGORY_SELECTED_ALTERNATIVE = null; + public static String CATEGORY_TAB = null; + public static String CATEGORY_TEST = null; + public static String CATEGORY_TYPED_OPENABLE = null; + public static String CATEGORY_UNIT_TEST = null; + public static String CATEGORY_VOICE = null; + public static String CATEGORY_VR_HOME = null; + public static String EXTRA_ALARM_COUNT = null; + public static String EXTRA_ALLOW_MULTIPLE = null; + public static String EXTRA_ALLOW_REPLACE = null; + public static String EXTRA_ALTERNATE_INTENTS = null; + public static String EXTRA_ASSIST_CONTEXT = null; + public static String EXTRA_ASSIST_INPUT_DEVICE_ID = null; + public static String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = null; + public static String EXTRA_ASSIST_PACKAGE = null; + public static String EXTRA_ASSIST_UID = null; + public static String EXTRA_AUTO_LAUNCH_SINGLE_CHOICE = null; + public static String EXTRA_BCC = null; + public static String EXTRA_BUG_REPORT = null; + public static String EXTRA_CC = null; + public static String EXTRA_CHANGED_COMPONENT_NAME = null; + public static String EXTRA_CHANGED_COMPONENT_NAME_LIST = null; + public static String EXTRA_CHANGED_PACKAGE_LIST = null; + public static String EXTRA_CHANGED_UID_LIST = null; + public static String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = null; + public static String EXTRA_CHOOSER_TARGETS = null; + public static String EXTRA_CHOSEN_COMPONENT = null; + public static String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = null; + public static String EXTRA_COMPONENT_NAME = null; + public static String EXTRA_CONTENT_ANNOTATIONS = null; + public static String EXTRA_CONTENT_QUERY = null; + public static String EXTRA_DATA_REMOVED = null; + public static String EXTRA_DOCK_STATE = null; + public static String EXTRA_DONT_KILL_APP = null; + public static String EXTRA_DURATION_MILLIS = null; + public static String EXTRA_EMAIL = null; + public static String EXTRA_EXCLUDE_COMPONENTS = null; + public static String EXTRA_FROM_STORAGE = null; + public static String EXTRA_HTML_TEXT = null; + public static String EXTRA_INDEX = null; + public static String EXTRA_INITIAL_INTENTS = null; + public static String EXTRA_INSTALLER_PACKAGE_NAME = null; + public static String EXTRA_INTENT = null; + public static String EXTRA_KEY_EVENT = null; + public static String EXTRA_LOCAL_ONLY = null; + public static String EXTRA_LOCUS_ID = null; + public static String EXTRA_MIME_TYPES = null; + public static String EXTRA_NOT_UNKNOWN_SOURCE = null; + public static String EXTRA_ORIGINATING_URI = null; + public static String EXTRA_PACKAGE_NAME = null; + public static String EXTRA_PHONE_NUMBER = null; + public static String EXTRA_PROCESS_TEXT = null; + public static String EXTRA_PROCESS_TEXT_READONLY = null; + public static String EXTRA_QUICK_VIEW_FEATURES = null; + public static String EXTRA_QUIET_MODE = null; + public static String EXTRA_REFERRER = null; + public static String EXTRA_REFERRER_NAME = null; + public static String EXTRA_REMOTE_INTENT_TOKEN = null; + public static String EXTRA_REPLACEMENT_EXTRAS = null; + public static String EXTRA_REPLACING = null; + public static String EXTRA_RESTRICTIONS_BUNDLE = null; + public static String EXTRA_RESTRICTIONS_INTENT = null; + public static String EXTRA_RESTRICTIONS_LIST = null; + public static String EXTRA_RESULT_RECEIVER = null; + public static String EXTRA_RETURN_RESULT = null; + public static String EXTRA_SHORTCUT_ICON = null; + public static String EXTRA_SHORTCUT_ICON_RESOURCE = null; + public static String EXTRA_SHORTCUT_ID = null; + public static String EXTRA_SHORTCUT_INTENT = null; + public static String EXTRA_SHORTCUT_NAME = null; + public static String EXTRA_SHUTDOWN_USERSPACE_ONLY = null; + public static String EXTRA_SPLIT_NAME = null; + public static String EXTRA_STREAM = null; + public static String EXTRA_SUBJECT = null; + public static String EXTRA_SUSPENDED_PACKAGE_EXTRAS = null; + public static String EXTRA_TEMPLATE = null; + public static String EXTRA_TEXT = null; + public static String EXTRA_TIME = null; + public static String EXTRA_TIMEZONE = null; + public static String EXTRA_TITLE = null; + public static String EXTRA_UID = null; + public static String EXTRA_USER = null; + public static String METADATA_DOCK_HOME = null; + public static String normalizeMimeType(String p0){ return null; } + public static int EXTRA_DOCK_STATE_CAR = 0; + public static int EXTRA_DOCK_STATE_DESK = 0; + public static int EXTRA_DOCK_STATE_HE_DESK = 0; + public static int EXTRA_DOCK_STATE_LE_DESK = 0; + public static int EXTRA_DOCK_STATE_UNDOCKED = 0; + public static int FILL_IN_ACTION = 0; + public static int FILL_IN_CATEGORIES = 0; + public static int FILL_IN_CLIP_DATA = 0; + public static int FILL_IN_COMPONENT = 0; + public static int FILL_IN_DATA = 0; + public static int FILL_IN_IDENTIFIER = 0; + public static int FILL_IN_PACKAGE = 0; + public static int FILL_IN_SELECTOR = 0; + public static int FILL_IN_SOURCE_BOUNDS = 0; + public static int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 0; + public static int FLAG_ACTIVITY_CLEAR_TASK = 0; + public static int FLAG_ACTIVITY_CLEAR_TOP = 0; + public static int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0; + public static int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 0; + public static int FLAG_ACTIVITY_FORWARD_RESULT = 0; + public static int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 0; + public static int FLAG_ACTIVITY_LAUNCH_ADJACENT = 0; + public static int FLAG_ACTIVITY_MATCH_EXTERNAL = 0; + public static int FLAG_ACTIVITY_MULTIPLE_TASK = 0; + public static int FLAG_ACTIVITY_NEW_DOCUMENT = 0; + public static int FLAG_ACTIVITY_NEW_TASK = 0; + public static int FLAG_ACTIVITY_NO_ANIMATION = 0; + public static int FLAG_ACTIVITY_NO_HISTORY = 0; + public static int FLAG_ACTIVITY_NO_USER_ACTION = 0; + public static int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 0; + public static int FLAG_ACTIVITY_REORDER_TO_FRONT = 0; + public static int FLAG_ACTIVITY_REQUIRE_DEFAULT = 0; + public static int FLAG_ACTIVITY_REQUIRE_NON_BROWSER = 0; + public static int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 0; + public static int FLAG_ACTIVITY_RETAIN_IN_RECENTS = 0; + public static int FLAG_ACTIVITY_SINGLE_TOP = 0; + public static int FLAG_ACTIVITY_TASK_ON_HOME = 0; + public static int FLAG_DEBUG_LOG_RESOLUTION = 0; + public static int FLAG_DIRECT_BOOT_AUTO = 0; + public static int FLAG_EXCLUDE_STOPPED_PACKAGES = 0; + public static int FLAG_FROM_BACKGROUND = 0; + public static int FLAG_GRANT_PERSISTABLE_URI_PERMISSION = 0; + public static int FLAG_GRANT_PREFIX_URI_PERMISSION = 0; + public static int FLAG_GRANT_READ_URI_PERMISSION = 0; + public static int FLAG_GRANT_WRITE_URI_PERMISSION = 0; + public static int FLAG_INCLUDE_STOPPED_PACKAGES = 0; + public static int FLAG_RECEIVER_FOREGROUND = 0; + public static int FLAG_RECEIVER_NO_ABORT = 0; + public static int FLAG_RECEIVER_REGISTERED_ONLY = 0; + public static int FLAG_RECEIVER_REPLACE_PENDING = 0; + public static int FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS = 0; + public static int URI_ALLOW_UNSAFE = 0; + public static int URI_ANDROID_APP_SCHEME = 0; + public static int URI_INTENT_SCHEME = 0; + public void readFromParcel(Parcel p0){} + public void removeCategory(String p0){} + public void removeExtra(String p0){} + public void removeFlags(int p0){} + public void setClipData(ClipData p0){} + public void setExtrasClassLoader(ClassLoader p0){} + public void setSelector(Intent p0){} + public void setSourceBounds(Rect p0){} + public void writeToParcel(Parcel p0, int p1){} } diff --git a/java/ql/test/stubs/android/android/content/IntentFilter.java b/java/ql/test/stubs/android/android/content/IntentFilter.java new file mode 100644 index 00000000000..99de8481e14 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/IntentFilter.java @@ -0,0 +1,104 @@ +// Generated automatically from android.content.IntentFilter for testing purposes + +package android.content; + +import android.content.ContentResolver; +import android.content.Intent; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; +import android.util.AndroidException; +import android.util.Printer; +import java.util.Iterator; +import java.util.Set; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlSerializer; + +public class IntentFilter implements Parcelable +{ + public IntentFilter(){} + public IntentFilter(IntentFilter p0){} + public IntentFilter(String p0){} + public IntentFilter(String p0, String p1){} + public final IntentFilter.AuthorityEntry getDataAuthority(int p0){ return null; } + public final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator(){ return null; } + public final Iterator<PatternMatcher> pathsIterator(){ return null; } + public final Iterator<PatternMatcher> schemeSpecificPartsIterator(){ return null; } + public final Iterator<String> actionsIterator(){ return null; } + public final Iterator<String> categoriesIterator(){ return null; } + public final Iterator<String> schemesIterator(){ return null; } + public final Iterator<String> typesIterator(){ return null; } + public final PatternMatcher getDataPath(int p0){ return null; } + public final PatternMatcher getDataSchemeSpecificPart(int p0){ return null; } + public final String getAction(int p0){ return null; } + public final String getCategory(int p0){ return null; } + public final String getDataScheme(int p0){ return null; } + public final String getDataType(int p0){ return null; } + public final String matchCategories(Set<String> p0){ return null; } + public final boolean hasAction(String p0){ return false; } + public final boolean hasCategory(String p0){ return false; } + public final boolean hasDataAuthority(Uri p0){ return false; } + public final boolean hasDataPath(String p0){ return false; } + public final boolean hasDataScheme(String p0){ return false; } + public final boolean hasDataSchemeSpecificPart(String p0){ return false; } + public final boolean hasDataType(String p0){ return false; } + public final boolean matchAction(String p0){ return false; } + public final int countActions(){ return 0; } + public final int countCategories(){ return 0; } + public final int countDataAuthorities(){ return 0; } + public final int countDataPaths(){ return 0; } + public final int countDataSchemeSpecificParts(){ return 0; } + public final int countDataSchemes(){ return 0; } + public final int countDataTypes(){ return 0; } + public final int describeContents(){ return 0; } + public final int getPriority(){ return 0; } + public final int match(ContentResolver p0, Intent p1, boolean p2, String p3){ return 0; } + public final int match(String p0, String p1, String p2, Uri p3, Set<String> p4, String p5){ return 0; } + public final int matchData(String p0, String p1, Uri p2){ return 0; } + public final int matchDataAuthority(Uri p0){ return 0; } + public final void addAction(String p0){} + public final void addCategory(String p0){} + public final void addDataAuthority(String p0, String p1){} + public final void addDataPath(String p0, int p1){} + public final void addDataScheme(String p0){} + public final void addDataSchemeSpecificPart(String p0, int p1){} + public final void addDataType(String p0){} + public final void setPriority(int p0){} + public final void writeToParcel(Parcel p0, int p1){} + public static IntentFilter create(String p0, String p1){ return null; } + public static Parcelable.Creator<IntentFilter> CREATOR = null; + public static int MATCH_ADJUSTMENT_MASK = 0; + public static int MATCH_ADJUSTMENT_NORMAL = 0; + public static int MATCH_CATEGORY_EMPTY = 0; + public static int MATCH_CATEGORY_HOST = 0; + public static int MATCH_CATEGORY_MASK = 0; + public static int MATCH_CATEGORY_PATH = 0; + public static int MATCH_CATEGORY_PORT = 0; + public static int MATCH_CATEGORY_SCHEME = 0; + public static int MATCH_CATEGORY_SCHEME_SPECIFIC_PART = 0; + public static int MATCH_CATEGORY_TYPE = 0; + public static int NO_MATCH_ACTION = 0; + public static int NO_MATCH_CATEGORY = 0; + public static int NO_MATCH_DATA = 0; + public static int NO_MATCH_TYPE = 0; + public static int SYSTEM_HIGH_PRIORITY = 0; + public static int SYSTEM_LOW_PRIORITY = 0; + public void dump(Printer p0, String p1){} + public void readFromXml(XmlPullParser p0){} + public void writeToXml(XmlSerializer p0){} + static public class AuthorityEntry + { + protected AuthorityEntry() {} + public AuthorityEntry(String p0, String p1){} + public String getHost(){ return null; } + public boolean equals(Object p0){ return false; } + public int getPort(){ return 0; } + public int match(Uri p0){ return 0; } + } + static public class MalformedMimeTypeException extends AndroidException + { + public MalformedMimeTypeException(){} + public MalformedMimeTypeException(String p0){} + } +} diff --git a/java/ql/test/stubs/android/android/content/IntentSender.java b/java/ql/test/stubs/android/android/content/IntentSender.java new file mode 100644 index 00000000000..6008341e802 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/IntentSender.java @@ -0,0 +1,40 @@ +// Generated automatically from android.content.IntentSender for testing purposes + +package android.content; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; +import android.util.AndroidException; + +public class IntentSender implements Parcelable +{ + public String getCreatorPackage(){ return null; } + public String getTargetPackage(){ return null; } + public String toString(){ return null; } + public UserHandle getCreatorUserHandle(){ return null; } + public boolean equals(Object p0){ return false; } + public int describeContents(){ return 0; } + public int getCreatorUid(){ return 0; } + public int hashCode(){ return 0; } + public static IntentSender readIntentSenderOrNullFromParcel(Parcel p0){ return null; } + public static Parcelable.Creator<IntentSender> CREATOR = null; + public static void writeIntentSenderOrNullToParcel(IntentSender p0, Parcel p1){} + public void sendIntent(Context p0, int p1, Intent p2, IntentSender.OnFinished p3, Handler p4){} + public void sendIntent(Context p0, int p1, Intent p2, IntentSender.OnFinished p3, Handler p4, String p5){} + public void writeToParcel(Parcel p0, int p1){} + static public class SendIntentException extends AndroidException + { + public SendIntentException(){} + public SendIntentException(Exception p0){} + public SendIntentException(String p0){} + } + static public interface OnFinished + { + void onSendFinished(IntentSender p0, Intent p1, int p2, String p3, Bundle p4); + } +} diff --git a/java/ql/test/stubs/android/android/content/PeriodicSync.java b/java/ql/test/stubs/android/android/content/PeriodicSync.java new file mode 100644 index 00000000000..6842c06d22f --- /dev/null +++ b/java/ql/test/stubs/android/android/content/PeriodicSync.java @@ -0,0 +1,23 @@ +// Generated automatically from android.content.PeriodicSync for testing purposes + +package android.content; + +import android.accounts.Account; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +public class PeriodicSync implements Parcelable +{ + protected PeriodicSync() {} + public PeriodicSync(Account p0, String p1, Bundle p2, long p3){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final Account account = null; + public final Bundle extras = null; + public final String authority = null; + public final long period = 0; + public int describeContents(){ return 0; } + public static Parcelable.Creator<PeriodicSync> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/ServiceConnection.java b/java/ql/test/stubs/android/android/content/ServiceConnection.java new file mode 100644 index 00000000000..1b8534539c4 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ServiceConnection.java @@ -0,0 +1,14 @@ +// Generated automatically from android.content.ServiceConnection for testing purposes + +package android.content; + +import android.content.ComponentName; +import android.os.IBinder; + +public interface ServiceConnection +{ + default void onBindingDied(ComponentName p0){} + default void onNullBinding(ComponentName p0){} + void onServiceConnected(ComponentName p0, IBinder p1); + void onServiceDisconnected(ComponentName p0); +} diff --git a/java/ql/test/stubs/android/android/content/SharedPreferences.java b/java/ql/test/stubs/android/android/content/SharedPreferences.java new file mode 100644 index 00000000000..90cdc242501 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/SharedPreferences.java @@ -0,0 +1,38 @@ +// Generated automatically from android.content.SharedPreferences for testing purposes + +package android.content; + +import java.util.Map; +import java.util.Set; + +public interface SharedPreferences +{ + Map<String, ? extends Object> getAll(); + Set<String> getStringSet(String p0, Set<String> p1); + SharedPreferences.Editor edit(); + String getString(String p0, String p1); + boolean contains(String p0); + boolean getBoolean(String p0, boolean p1); + float getFloat(String p0, float p1); + int getInt(String p0, int p1); + long getLong(String p0, long p1); + static public interface Editor + { + SharedPreferences.Editor clear(); + SharedPreferences.Editor putBoolean(String p0, boolean p1); + SharedPreferences.Editor putFloat(String p0, float p1); + SharedPreferences.Editor putInt(String p0, int p1); + SharedPreferences.Editor putLong(String p0, long p1); + SharedPreferences.Editor putString(String p0, String p1); + SharedPreferences.Editor putStringSet(String p0, Set<String> p1); + SharedPreferences.Editor remove(String p0); + boolean commit(); + void apply(); + } + static public interface OnSharedPreferenceChangeListener + { + void onSharedPreferenceChanged(SharedPreferences p0, String p1); + } + void registerOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener p0); + void unregisterOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener p0); +} diff --git a/java/ql/test/stubs/android/android/content/SyncAdapterType.java b/java/ql/test/stubs/android/android/content/SyncAdapterType.java new file mode 100644 index 00000000000..b05e030a6c3 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/SyncAdapterType.java @@ -0,0 +1,28 @@ +// Generated automatically from android.content.SyncAdapterType for testing purposes + +package android.content; + +import android.os.Parcel; +import android.os.Parcelable; + +public class SyncAdapterType implements Parcelable +{ + protected SyncAdapterType() {} + public String getSettingsActivity(){ return null; } + public String toString(){ return null; } + public SyncAdapterType(Parcel p0){} + public SyncAdapterType(String p0, String p1, boolean p2, boolean p3){} + public boolean allowParallelSyncs(){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isAlwaysSyncable(){ return false; } + public boolean isUserVisible(){ return false; } + public boolean supportsUploading(){ return false; } + public final String accountType = null; + public final String authority = null; + public final boolean isKey = false; + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<SyncAdapterType> CREATOR = null; + public static SyncAdapterType newKey(String p0, String p1){ return null; } + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/SyncInfo.java b/java/ql/test/stubs/android/android/content/SyncInfo.java new file mode 100644 index 00000000000..500c5bd97bc --- /dev/null +++ b/java/ql/test/stubs/android/android/content/SyncInfo.java @@ -0,0 +1,16 @@ +// Generated automatically from android.content.SyncInfo for testing purposes + +package android.content; + +import android.accounts.Account; +import android.os.Parcel; +import android.os.Parcelable; + +public class SyncInfo implements Parcelable +{ + public final Account account = null; + public final String authority = null; + public final long startTime = 0; + public int describeContents(){ return 0; } + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/SyncRequest.java b/java/ql/test/stubs/android/android/content/SyncRequest.java new file mode 100644 index 00000000000..29a07c4b5a7 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/SyncRequest.java @@ -0,0 +1,13 @@ +// Generated automatically from android.content.SyncRequest for testing purposes + +package android.content; + +import android.os.Parcel; +import android.os.Parcelable; + +public class SyncRequest implements Parcelable +{ + public int describeContents(){ return 0; } + public static Parcelable.Creator<SyncRequest> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/SyncStatusObserver.java b/java/ql/test/stubs/android/android/content/SyncStatusObserver.java new file mode 100644 index 00000000000..534cd549be0 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/SyncStatusObserver.java @@ -0,0 +1,9 @@ +// Generated automatically from android.content.SyncStatusObserver for testing purposes + +package android.content; + + +public interface SyncStatusObserver +{ + void onStatusChanged(int p0); +} diff --git a/java/ql/test/stubs/android/android/content/UriPermission.java b/java/ql/test/stubs/android/android/content/UriPermission.java new file mode 100644 index 00000000000..efa9f6e7b95 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/UriPermission.java @@ -0,0 +1,20 @@ +// Generated automatically from android.content.UriPermission for testing purposes + +package android.content; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +public class UriPermission implements Parcelable +{ + public String toString(){ return null; } + public Uri getUri(){ return null; } + public boolean isReadPermission(){ return false; } + public boolean isWritePermission(){ return false; } + public int describeContents(){ return 0; } + public long getPersistedTime(){ return 0; } + public static Parcelable.Creator<UriPermission> CREATOR = null; + public static long INVALID_TIME = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/ActivityInfo.java b/java/ql/test/stubs/android/android/content/pm/ActivityInfo.java new file mode 100644 index 00000000000..ed0debb0412 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ActivityInfo.java @@ -0,0 +1,112 @@ +// Generated automatically from android.content.pm.ActivityInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ComponentInfo; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +public class ActivityInfo extends ComponentInfo implements Parcelable +{ + public ActivityInfo(){} + public ActivityInfo(ActivityInfo p0){} + public ActivityInfo.WindowLayout windowLayout = null; + public String parentActivityName = null; + public String permission = null; + public String targetActivity = null; + public String taskAffinity = null; + public String toString(){ return null; } + public final int getThemeResource(){ return 0; } + public int colorMode = 0; + public int configChanges = 0; + public int describeContents(){ return 0; } + public int documentLaunchMode = 0; + public int flags = 0; + public int launchMode = 0; + public int maxRecents = 0; + public int persistableMode = 0; + public int screenOrientation = 0; + public int softInputMode = 0; + public int theme = 0; + public int uiOptions = 0; + public static Parcelable.Creator<ActivityInfo> CREATOR = null; + public static int COLOR_MODE_DEFAULT = 0; + public static int COLOR_MODE_HDR = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT = 0; + public static int CONFIG_COLOR_MODE = 0; + public static int CONFIG_DENSITY = 0; + public static int CONFIG_FONT_SCALE = 0; + public static int CONFIG_KEYBOARD = 0; + public static int CONFIG_KEYBOARD_HIDDEN = 0; + public static int CONFIG_LAYOUT_DIRECTION = 0; + public static int CONFIG_LOCALE = 0; + public static int CONFIG_MCC = 0; + public static int CONFIG_MNC = 0; + public static int CONFIG_NAVIGATION = 0; + public static int CONFIG_ORIENTATION = 0; + public static int CONFIG_SCREEN_LAYOUT = 0; + public static int CONFIG_SCREEN_SIZE = 0; + public static int CONFIG_SMALLEST_SCREEN_SIZE = 0; + public static int CONFIG_TOUCHSCREEN = 0; + public static int CONFIG_UI_MODE = 0; + public static int DOCUMENT_LAUNCH_ALWAYS = 0; + public static int DOCUMENT_LAUNCH_INTO_EXISTING = 0; + public static int DOCUMENT_LAUNCH_NEVER = 0; + public static int DOCUMENT_LAUNCH_NONE = 0; + public static int FLAG_ALLOW_TASK_REPARENTING = 0; + public static int FLAG_ALWAYS_RETAIN_TASK_STATE = 0; + public static int FLAG_AUTO_REMOVE_FROM_RECENTS = 0; + public static int FLAG_CLEAR_TASK_ON_LAUNCH = 0; + public static int FLAG_ENABLE_VR_MODE = 0; + public static int FLAG_EXCLUDE_FROM_RECENTS = 0; + public static int FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS = 0; + public static int FLAG_FINISH_ON_TASK_LAUNCH = 0; + public static int FLAG_HARDWARE_ACCELERATED = 0; + public static int FLAG_IMMERSIVE = 0; + public static int FLAG_MULTIPROCESS = 0; + public static int FLAG_NO_HISTORY = 0; + public static int FLAG_PREFER_MINIMAL_POST_PROCESSING = 0; + public static int FLAG_RELINQUISH_TASK_IDENTITY = 0; + public static int FLAG_RESUME_WHILE_PAUSING = 0; + public static int FLAG_SINGLE_USER = 0; + public static int FLAG_STATE_NOT_NEEDED = 0; + public static int LAUNCH_MULTIPLE = 0; + public static int LAUNCH_SINGLE_INSTANCE = 0; + public static int LAUNCH_SINGLE_TASK = 0; + public static int LAUNCH_SINGLE_TOP = 0; + public static int PERSIST_ACROSS_REBOOTS = 0; + public static int PERSIST_NEVER = 0; + public static int PERSIST_ROOT_ONLY = 0; + public static int SCREEN_ORIENTATION_BEHIND = 0; + public static int SCREEN_ORIENTATION_FULL_SENSOR = 0; + public static int SCREEN_ORIENTATION_FULL_USER = 0; + public static int SCREEN_ORIENTATION_LANDSCAPE = 0; + public static int SCREEN_ORIENTATION_LOCKED = 0; + public static int SCREEN_ORIENTATION_NOSENSOR = 0; + public static int SCREEN_ORIENTATION_PORTRAIT = 0; + public static int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 0; + public static int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 0; + public static int SCREEN_ORIENTATION_SENSOR = 0; + public static int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 0; + public static int SCREEN_ORIENTATION_SENSOR_PORTRAIT = 0; + public static int SCREEN_ORIENTATION_UNSPECIFIED = 0; + public static int SCREEN_ORIENTATION_USER = 0; + public static int SCREEN_ORIENTATION_USER_LANDSCAPE = 0; + public static int SCREEN_ORIENTATION_USER_PORTRAIT = 0; + public static int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 0; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} + static public class WindowLayout + { + protected WindowLayout() {} + public WindowLayout(int p0, float p1, int p2, float p3, int p4, int p5, int p6){} + public final float heightFraction = 0; + public final float widthFraction = 0; + public final int gravity = 0; + public final int height = 0; + public final int minHeight = 0; + public final int minWidth = 0; + public final int width = 0; + } +} diff --git a/java/ql/test/stubs/android/android/content/pm/ApplicationInfo.java b/java/ql/test/stubs/android/android/content/pm/ApplicationInfo.java new file mode 100644 index 00000000000..51fc3974933 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ApplicationInfo.java @@ -0,0 +1,101 @@ +// Generated automatically from android.content.pm.ApplicationInfo for testing purposes + +package android.content.pm; + +import android.content.Context; +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; +import java.util.UUID; + +public class ApplicationInfo extends PackageItemInfo implements Parcelable +{ + public ApplicationInfo(){} + public ApplicationInfo(ApplicationInfo p0){} + public CharSequence loadDescription(PackageManager p0){ return null; } + public String appComponentFactory = null; + public String backupAgentName = null; + public String className = null; + public String dataDir = null; + public String deviceProtectedDataDir = null; + public String manageSpaceActivityName = null; + public String nativeLibraryDir = null; + public String permission = null; + public String processName = null; + public String publicSourceDir = null; + public String sourceDir = null; + public String taskAffinity = null; + public String toString(){ return null; } + public String[] sharedLibraryFiles = null; + public String[] splitNames = null; + public String[] splitPublicSourceDirs = null; + public String[] splitSourceDirs = null; + public UUID storageUuid = null; + public boolean enabled = false; + public boolean isProfileableByShell(){ return false; } + public boolean isResourceOverlay(){ return false; } + public boolean isVirtualPreload(){ return false; } + public int category = 0; + public int compatibleWidthLimitDp = 0; + public int describeContents(){ return 0; } + public int descriptionRes = 0; + public int flags = 0; + public int getGwpAsanMode(){ return 0; } + public int largestWidthLimitDp = 0; + public int minSdkVersion = 0; + public int requiresSmallestWidthDp = 0; + public int targetSdkVersion = 0; + public int theme = 0; + public int uiOptions = 0; + public int uid = 0; + public static CharSequence getCategoryTitle(Context p0, int p1){ return null; } + public static Parcelable.Creator<ApplicationInfo> CREATOR = null; + public static int CATEGORY_AUDIO = 0; + public static int CATEGORY_GAME = 0; + public static int CATEGORY_IMAGE = 0; + public static int CATEGORY_MAPS = 0; + public static int CATEGORY_NEWS = 0; + public static int CATEGORY_PRODUCTIVITY = 0; + public static int CATEGORY_SOCIAL = 0; + public static int CATEGORY_UNDEFINED = 0; + public static int CATEGORY_VIDEO = 0; + public static int FLAG_ALLOW_BACKUP = 0; + public static int FLAG_ALLOW_CLEAR_USER_DATA = 0; + public static int FLAG_ALLOW_TASK_REPARENTING = 0; + public static int FLAG_DEBUGGABLE = 0; + public static int FLAG_EXTERNAL_STORAGE = 0; + public static int FLAG_EXTRACT_NATIVE_LIBS = 0; + public static int FLAG_FACTORY_TEST = 0; + public static int FLAG_FULL_BACKUP_ONLY = 0; + public static int FLAG_HARDWARE_ACCELERATED = 0; + public static int FLAG_HAS_CODE = 0; + public static int FLAG_INSTALLED = 0; + public static int FLAG_IS_DATA_ONLY = 0; + public static int FLAG_IS_GAME = 0; + public static int FLAG_KILL_AFTER_RESTORE = 0; + public static int FLAG_LARGE_HEAP = 0; + public static int FLAG_MULTIARCH = 0; + public static int FLAG_PERSISTENT = 0; + public static int FLAG_RESIZEABLE_FOR_SCREENS = 0; + public static int FLAG_RESTORE_ANY_VERSION = 0; + public static int FLAG_STOPPED = 0; + public static int FLAG_SUPPORTS_LARGE_SCREENS = 0; + public static int FLAG_SUPPORTS_NORMAL_SCREENS = 0; + public static int FLAG_SUPPORTS_RTL = 0; + public static int FLAG_SUPPORTS_SCREEN_DENSITIES = 0; + public static int FLAG_SUPPORTS_SMALL_SCREENS = 0; + public static int FLAG_SUPPORTS_XLARGE_SCREENS = 0; + public static int FLAG_SUSPENDED = 0; + public static int FLAG_SYSTEM = 0; + public static int FLAG_TEST_ONLY = 0; + public static int FLAG_UPDATED_SYSTEM_APP = 0; + public static int FLAG_USES_CLEARTEXT_TRAFFIC = 0; + public static int FLAG_VM_SAFE_MODE = 0; + public static int GWP_ASAN_ALWAYS = 0; + public static int GWP_ASAN_DEFAULT = 0; + public static int GWP_ASAN_NEVER = 0; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/ChangedPackages.java b/java/ql/test/stubs/android/android/content/pm/ChangedPackages.java new file mode 100644 index 00000000000..08c10b13f3c --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ChangedPackages.java @@ -0,0 +1,18 @@ +// Generated automatically from android.content.pm.ChangedPackages for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import java.util.List; + +public class ChangedPackages implements Parcelable +{ + protected ChangedPackages() {} + public ChangedPackages(int p0, List<String> p1){} + public List<String> getPackageNames(){ return null; } + public int describeContents(){ return 0; } + public int getSequenceNumber(){ return 0; } + public static Parcelable.Creator<ChangedPackages> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/ComponentInfo.java b/java/ql/test/stubs/android/android/content/pm/ComponentInfo.java new file mode 100644 index 00000000000..fb92a43adbe --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ComponentInfo.java @@ -0,0 +1,29 @@ +// Generated automatically from android.content.pm.ComponentInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageItemInfo; +import android.os.Parcel; +import android.util.Printer; + +public class ComponentInfo extends PackageItemInfo +{ + protected ComponentInfo(Parcel p0){} + protected void dumpBack(Printer p0, String p1){} + protected void dumpFront(Printer p0, String p1){} + public ApplicationInfo applicationInfo = null; + public ComponentInfo(){} + public ComponentInfo(ComponentInfo p0){} + public String processName = null; + public String splitName = null; + public boolean directBootAware = false; + public boolean enabled = false; + public boolean exported = false; + public boolean isEnabled(){ return false; } + public final int getBannerResource(){ return 0; } + public final int getIconResource(){ return 0; } + public final int getLogoResource(){ return 0; } + public int descriptionRes = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/ConfigurationInfo.java b/java/ql/test/stubs/android/android/content/pm/ConfigurationInfo.java new file mode 100644 index 00000000000..ad178b8c6a3 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ConfigurationInfo.java @@ -0,0 +1,25 @@ +// Generated automatically from android.content.pm.ConfigurationInfo for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +public class ConfigurationInfo implements Parcelable +{ + public ConfigurationInfo(){} + public ConfigurationInfo(ConfigurationInfo p0){} + public String getGlEsVersion(){ return null; } + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int reqGlEsVersion = 0; + public int reqInputFeatures = 0; + public int reqKeyboardType = 0; + public int reqNavigation = 0; + public int reqTouchScreen = 0; + public static Parcelable.Creator<ConfigurationInfo> CREATOR = null; + public static int GL_ES_VERSION_UNDEFINED = 0; + public static int INPUT_FEATURE_FIVE_WAY_NAV = 0; + public static int INPUT_FEATURE_HARD_KEYBOARD = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/FeatureGroupInfo.java b/java/ql/test/stubs/android/android/content/pm/FeatureGroupInfo.java new file mode 100644 index 00000000000..9cf6eaa172a --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/FeatureGroupInfo.java @@ -0,0 +1,17 @@ +// Generated automatically from android.content.pm.FeatureGroupInfo for testing purposes + +package android.content.pm; + +import android.content.pm.FeatureInfo; +import android.os.Parcel; +import android.os.Parcelable; + +public class FeatureGroupInfo implements Parcelable +{ + public FeatureGroupInfo(){} + public FeatureGroupInfo(FeatureGroupInfo p0){} + public FeatureInfo[] features = null; + public int describeContents(){ return 0; } + public static Parcelable.Creator<FeatureGroupInfo> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/FeatureInfo.java b/java/ql/test/stubs/android/android/content/pm/FeatureInfo.java new file mode 100644 index 00000000000..5512590828f --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/FeatureInfo.java @@ -0,0 +1,23 @@ +// Generated automatically from android.content.pm.FeatureInfo for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +public class FeatureInfo implements Parcelable +{ + public FeatureInfo(){} + public FeatureInfo(FeatureInfo p0){} + public String getGlEsVersion(){ return null; } + public String name = null; + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int flags = 0; + public int reqGlEsVersion = 0; + public int version = 0; + public static Parcelable.Creator<FeatureInfo> CREATOR = null; + public static int FLAG_REQUIRED = 0; + public static int GL_ES_VERSION_UNDEFINED = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/InstallSourceInfo.java b/java/ql/test/stubs/android/android/content/pm/InstallSourceInfo.java new file mode 100644 index 00000000000..85c503025d0 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/InstallSourceInfo.java @@ -0,0 +1,18 @@ +// Generated automatically from android.content.pm.InstallSourceInfo for testing purposes + +package android.content.pm; + +import android.content.pm.SigningInfo; +import android.os.Parcel; +import android.os.Parcelable; + +public class InstallSourceInfo implements Parcelable +{ + public SigningInfo getInitiatingPackageSigningInfo(){ return null; } + public String getInitiatingPackageName(){ return null; } + public String getInstallingPackageName(){ return null; } + public String getOriginatingPackageName(){ return null; } + public int describeContents(){ return 0; } + public static Parcelable.Creator<InstallSourceInfo> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/InstrumentationInfo.java b/java/ql/test/stubs/android/android/content/pm/InstrumentationInfo.java new file mode 100644 index 00000000000..70063a09744 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/InstrumentationInfo.java @@ -0,0 +1,27 @@ +// Generated automatically from android.content.pm.InstrumentationInfo for testing purposes + +package android.content.pm; + +import android.content.pm.PackageItemInfo; +import android.os.Parcel; +import android.os.Parcelable; + +public class InstrumentationInfo extends PackageItemInfo implements Parcelable +{ + public InstrumentationInfo(){} + public InstrumentationInfo(InstrumentationInfo p0){} + public String dataDir = null; + public String publicSourceDir = null; + public String sourceDir = null; + public String targetPackage = null; + public String targetProcesses = null; + public String toString(){ return null; } + public String[] splitNames = null; + public String[] splitPublicSourceDirs = null; + public String[] splitSourceDirs = null; + public boolean functionalTest = false; + public boolean handleProfiling = false; + public int describeContents(){ return 0; } + public static Parcelable.Creator<InstrumentationInfo> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/ModuleInfo.java b/java/ql/test/stubs/android/android/content/pm/ModuleInfo.java new file mode 100644 index 00000000000..c7aef5f7ac7 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ModuleInfo.java @@ -0,0 +1,19 @@ +// Generated automatically from android.content.pm.ModuleInfo for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +public class ModuleInfo implements Parcelable +{ + public CharSequence getName(){ return null; } + public String getPackageName(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isHidden(){ return false; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<ModuleInfo> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/PackageInfo.java b/java/ql/test/stubs/android/android/content/pm/PackageInfo.java new file mode 100644 index 00000000000..566e8e73fbf --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/PackageInfo.java @@ -0,0 +1,59 @@ +// Generated automatically from android.content.pm.PackageInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ConfigurationInfo; +import android.content.pm.FeatureGroupInfo; +import android.content.pm.FeatureInfo; +import android.content.pm.InstrumentationInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ServiceInfo; +import android.content.pm.Signature; +import android.content.pm.SigningInfo; +import android.os.Parcel; +import android.os.Parcelable; + +public class PackageInfo implements Parcelable +{ + public ActivityInfo[] activities = null; + public ActivityInfo[] receivers = null; + public ApplicationInfo applicationInfo = null; + public ConfigurationInfo[] configPreferences = null; + public FeatureGroupInfo[] featureGroups = null; + public FeatureInfo[] reqFeatures = null; + public InstrumentationInfo[] instrumentation = null; + public PackageInfo(){} + public PermissionInfo[] permissions = null; + public ProviderInfo[] providers = null; + public ServiceInfo[] services = null; + public Signature[] signatures = null; + public SigningInfo signingInfo = null; + public String packageName = null; + public String sharedUserId = null; + public String toString(){ return null; } + public String versionName = null; + public String[] requestedPermissions = null; + public String[] splitNames = null; + public boolean isApex = false; + public int baseRevisionCode = 0; + public int describeContents(){ return 0; } + public int installLocation = 0; + public int sharedUserLabel = 0; + public int versionCode = 0; + public int[] gids = null; + public int[] requestedPermissionsFlags = null; + public int[] splitRevisionCodes = null; + public long firstInstallTime = 0; + public long getLongVersionCode(){ return 0; } + public long lastUpdateTime = 0; + public static Parcelable.Creator<PackageInfo> CREATOR = null; + public static int INSTALL_LOCATION_AUTO = 0; + public static int INSTALL_LOCATION_INTERNAL_ONLY = 0; + public static int INSTALL_LOCATION_PREFER_EXTERNAL = 0; + public static int REQUESTED_PERMISSION_GRANTED = 0; + public void setLongVersionCode(long p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/PackageInstaller.java b/java/ql/test/stubs/android/android/content/pm/PackageInstaller.java new file mode 100644 index 00000000000..46337e28f60 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/PackageInstaller.java @@ -0,0 +1,151 @@ +// Generated automatically from android.content.pm.PackageInstaller for testing purposes + +package android.content.pm; + +import android.content.Intent; +import android.content.IntentSender; +import android.content.pm.VersionedPackage; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; +import java.io.Closeable; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.Set; + +public class PackageInstaller +{ + abstract static public class SessionCallback + { + public SessionCallback(){} + public abstract void onActiveChanged(int p0, boolean p1); + public abstract void onBadgingChanged(int p0); + public abstract void onCreated(int p0); + public abstract void onFinished(int p0, boolean p1); + public abstract void onProgressChanged(int p0, float p1); + } + public List<PackageInstaller.SessionInfo> getActiveStagedSessions(){ return null; } + public List<PackageInstaller.SessionInfo> getAllSessions(){ return null; } + public List<PackageInstaller.SessionInfo> getMySessions(){ return null; } + public List<PackageInstaller.SessionInfo> getStagedSessions(){ return null; } + public PackageInstaller.Session openSession(int p0){ return null; } + public PackageInstaller.SessionInfo getActiveStagedSession(){ return null; } + public PackageInstaller.SessionInfo getSessionInfo(int p0){ return null; } + public int createSession(PackageInstaller.SessionParams p0){ return 0; } + public static String ACTION_SESSION_COMMITTED = null; + public static String ACTION_SESSION_DETAILS = null; + public static String ACTION_SESSION_UPDATED = null; + public static String EXTRA_OTHER_PACKAGE_NAME = null; + public static String EXTRA_PACKAGE_NAME = null; + public static String EXTRA_SESSION = null; + public static String EXTRA_SESSION_ID = null; + public static String EXTRA_STATUS = null; + public static String EXTRA_STATUS_MESSAGE = null; + public static String EXTRA_STORAGE_PATH = null; + public static int STATUS_FAILURE = 0; + public static int STATUS_FAILURE_ABORTED = 0; + public static int STATUS_FAILURE_BLOCKED = 0; + public static int STATUS_FAILURE_CONFLICT = 0; + public static int STATUS_FAILURE_INCOMPATIBLE = 0; + public static int STATUS_FAILURE_INVALID = 0; + public static int STATUS_FAILURE_STORAGE = 0; + public static int STATUS_PENDING_USER_ACTION = 0; + public static int STATUS_SUCCESS = 0; + public void abandonSession(int p0){} + public void installExistingPackage(String p0, int p1, IntentSender p2){} + public void registerSessionCallback(PackageInstaller.SessionCallback p0){} + public void registerSessionCallback(PackageInstaller.SessionCallback p0, Handler p1){} + public void uninstall(String p0, IntentSender p1){} + public void uninstall(VersionedPackage p0, IntentSender p1){} + public void unregisterSessionCallback(PackageInstaller.SessionCallback p0){} + public void updateSessionAppIcon(int p0, Bitmap p1){} + public void updateSessionAppLabel(int p0, CharSequence p1){} + static public class Session implements Closeable + { + public InputStream openRead(String p0){ return null; } + public OutputStream openWrite(String p0, long p1, long p2){ return null; } + public String[] getNames(){ return null; } + public boolean isMultiPackage(){ return false; } + public boolean isStaged(){ return false; } + public int getParentSessionId(){ return 0; } + public int[] getChildSessionIds(){ return null; } + public void abandon(){} + public void addChildSessionId(int p0){} + public void close(){} + public void commit(IntentSender p0){} + public void fsync(OutputStream p0){} + public void removeChildSessionId(int p0){} + public void removeSplit(String p0){} + public void setStagingProgress(float p0){} + public void transfer(String p0){} + } + static public class SessionInfo implements Parcelable + { + public Bitmap getAppIcon(){ return null; } + public CharSequence getAppLabel(){ return null; } + public Intent createDetailsIntent(){ return null; } + public String getAppPackageName(){ return null; } + public String getInstallerPackageName(){ return null; } + public String getStagedSessionErrorMessage(){ return null; } + public Uri getOriginatingUri(){ return null; } + public Uri getReferrerUri(){ return null; } + public UserHandle getUser(){ return null; } + public boolean hasParentSessionId(){ return false; } + public boolean isActive(){ return false; } + public boolean isCommitted(){ return false; } + public boolean isMultiPackage(){ return false; } + public boolean isSealed(){ return false; } + public boolean isStaged(){ return false; } + public boolean isStagedSessionActive(){ return false; } + public boolean isStagedSessionApplied(){ return false; } + public boolean isStagedSessionFailed(){ return false; } + public boolean isStagedSessionReady(){ return false; } + public float getProgress(){ return 0; } + public int describeContents(){ return 0; } + public int getInstallLocation(){ return 0; } + public int getInstallReason(){ return 0; } + public int getMode(){ return 0; } + public int getOriginatingUid(){ return 0; } + public int getParentSessionId(){ return 0; } + public int getSessionId(){ return 0; } + public int getStagedSessionErrorCode(){ return 0; } + public int[] getChildSessionIds(){ return null; } + public long getCreatedMillis(){ return 0; } + public long getSize(){ return 0; } + public long getUpdatedMillis(){ return 0; } + public static Parcelable.Creator<PackageInstaller.SessionInfo> CREATOR = null; + public static int INVALID_ID = 0; + public static int STAGED_SESSION_ACTIVATION_FAILED = 0; + public static int STAGED_SESSION_NO_ERROR = 0; + public static int STAGED_SESSION_UNKNOWN = 0; + public static int STAGED_SESSION_VERIFICATION_FAILED = 0; + public void writeToParcel(Parcel p0, int p1){} + } + static public class SessionParams implements Parcelable + { + protected SessionParams() {} + public SessionParams(int p0){} + public int describeContents(){ return 0; } + public static Parcelable.Creator<PackageInstaller.SessionParams> CREATOR = null; + public static Set<String> RESTRICTED_PERMISSIONS_ALL = null; + public static int MODE_FULL_INSTALL = 0; + public static int MODE_INHERIT_EXISTING = 0; + public void setAppIcon(Bitmap p0){} + public void setAppLabel(CharSequence p0){} + public void setAppPackageName(String p0){} + public void setAutoRevokePermissionsMode(boolean p0){} + public void setInstallLocation(int p0){} + public void setInstallReason(int p0){} + public void setMultiPackage(){} + public void setOriginatingUid(int p0){} + public void setOriginatingUri(Uri p0){} + public void setReferrerUri(Uri p0){} + public void setSize(long p0){} + public void setWhitelistedRestrictedPermissions(Set<String> p0){} + public void writeToParcel(Parcel p0, int p1){} + } +} diff --git a/java/ql/test/stubs/android/android/content/pm/PackageItemInfo.java b/java/ql/test/stubs/android/android/content/pm/PackageItemInfo.java new file mode 100644 index 00000000000..1d35a31f52b --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/PackageItemInfo.java @@ -0,0 +1,34 @@ +// Generated automatically from android.content.pm.PackageItemInfo for testing purposes + +package android.content.pm; + +import android.content.pm.PackageManager; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Parcel; +import android.util.Printer; + +public class PackageItemInfo +{ + protected PackageItemInfo(Parcel p0){} + protected void dumpBack(Printer p0, String p1){} + protected void dumpFront(Printer p0, String p1){} + public Bundle metaData = null; + public CharSequence loadLabel(PackageManager p0){ return null; } + public CharSequence nonLocalizedLabel = null; + public Drawable loadBanner(PackageManager p0){ return null; } + public Drawable loadIcon(PackageManager p0){ return null; } + public Drawable loadLogo(PackageManager p0){ return null; } + public Drawable loadUnbadgedIcon(PackageManager p0){ return null; } + public PackageItemInfo(){} + public PackageItemInfo(PackageItemInfo p0){} + public String name = null; + public String packageName = null; + public XmlResourceParser loadXmlMetaData(PackageManager p0, String p1){ return null; } + public int banner = 0; + public int icon = 0; + public int labelRes = 0; + public int logo = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/PackageManager.java b/java/ql/test/stubs/android/android/content/pm/PackageManager.java new file mode 100644 index 00000000000..73e82024984 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/PackageManager.java @@ -0,0 +1,331 @@ +// Generated automatically from android.content.pm.PackageManager for testing purposes + +package android.content.pm; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ChangedPackages; +import android.content.pm.FeatureInfo; +import android.content.pm.InstallSourceInfo; +import android.content.pm.InstrumentationInfo; +import android.content.pm.ModuleInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.pm.SharedLibraryInfo; +import android.content.pm.VersionedPackage; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.UserHandle; +import android.util.AndroidException; +import java.util.List; +import java.util.Set; + +abstract public class PackageManager +{ + public Bundle getSuspendedPackageAppExtras(){ return null; } + public CharSequence getBackgroundPermissionOptionLabel(){ return null; } + public InstallSourceInfo getInstallSourceInfo(String p0){ return null; } + public List<ModuleInfo> getInstalledModules(int p0){ return null; } + public ModuleInfo getModuleInfo(String p0, int p1){ return null; } + public PackageInfo getPackageArchiveInfo(String p0, int p1){ return null; } + public PackageManager(){} + public Set<String> getMimeGroup(String p0){ return null; } + public Set<String> getWhitelistedRestrictedPermissions(String p0, int p1){ return null; } + public abstract ActivityInfo getActivityInfo(ComponentName p0, int p1); + public abstract ActivityInfo getReceiverInfo(ComponentName p0, int p1); + public abstract ApplicationInfo getApplicationInfo(String p0, int p1); + public abstract ChangedPackages getChangedPackages(int p0); + public abstract CharSequence getApplicationLabel(ApplicationInfo p0); + public abstract CharSequence getText(String p0, int p1, ApplicationInfo p2); + public abstract CharSequence getUserBadgedLabel(CharSequence p0, UserHandle p1); + public abstract Drawable getActivityBanner(ComponentName p0); + public abstract Drawable getActivityBanner(Intent p0); + public abstract Drawable getActivityIcon(ComponentName p0); + public abstract Drawable getActivityIcon(Intent p0); + public abstract Drawable getActivityLogo(ComponentName p0); + public abstract Drawable getActivityLogo(Intent p0); + public abstract Drawable getApplicationBanner(ApplicationInfo p0); + public abstract Drawable getApplicationBanner(String p0); + public abstract Drawable getApplicationIcon(ApplicationInfo p0); + public abstract Drawable getApplicationIcon(String p0); + public abstract Drawable getApplicationLogo(ApplicationInfo p0); + public abstract Drawable getApplicationLogo(String p0); + public abstract Drawable getDefaultActivityIcon(); + public abstract Drawable getDrawable(String p0, int p1, ApplicationInfo p2); + public abstract Drawable getUserBadgedDrawableForDensity(Drawable p0, UserHandle p1, Rect p2, int p3); + public abstract Drawable getUserBadgedIcon(Drawable p0, UserHandle p1); + public abstract FeatureInfo[] getSystemAvailableFeatures(); + public abstract InstrumentationInfo getInstrumentationInfo(ComponentName p0, int p1); + public abstract Intent getLaunchIntentForPackage(String p0); + public abstract Intent getLeanbackLaunchIntentForPackage(String p0); + public abstract List<ApplicationInfo> getInstalledApplications(int p0); + public abstract List<InstrumentationInfo> queryInstrumentation(String p0, int p1); + public abstract List<PackageInfo> getInstalledPackages(int p0); + public abstract List<PackageInfo> getPackagesHoldingPermissions(String[] p0, int p1); + public abstract List<PackageInfo> getPreferredPackages(int p0); + public abstract List<PermissionGroupInfo> getAllPermissionGroups(int p0); + public abstract List<PermissionInfo> queryPermissionsByGroup(String p0, int p1); + public abstract List<ProviderInfo> queryContentProviders(String p0, int p1, int p2); + public abstract List<ResolveInfo> queryBroadcastReceivers(Intent p0, int p1); + public abstract List<ResolveInfo> queryIntentActivities(Intent p0, int p1); + public abstract List<ResolveInfo> queryIntentActivityOptions(ComponentName p0, Intent[] p1, Intent p2, int p3); + public abstract List<ResolveInfo> queryIntentContentProviders(Intent p0, int p1); + public abstract List<ResolveInfo> queryIntentServices(Intent p0, int p1); + public abstract List<SharedLibraryInfo> getSharedLibraries(int p0); + public abstract PackageInfo getPackageInfo(String p0, int p1); + public abstract PackageInfo getPackageInfo(VersionedPackage p0, int p1); + public abstract PackageInstaller getPackageInstaller(); + public abstract PermissionGroupInfo getPermissionGroupInfo(String p0, int p1); + public abstract PermissionInfo getPermissionInfo(String p0, int p1); + public abstract ProviderInfo getProviderInfo(ComponentName p0, int p1); + public abstract ProviderInfo resolveContentProvider(String p0, int p1); + public abstract ResolveInfo resolveActivity(Intent p0, int p1); + public abstract ResolveInfo resolveService(Intent p0, int p1); + public abstract Resources getResourcesForActivity(ComponentName p0); + public abstract Resources getResourcesForApplication(ApplicationInfo p0); + public abstract Resources getResourcesForApplication(String p0); + public abstract ServiceInfo getServiceInfo(ComponentName p0, int p1); + public abstract String getInstallerPackageName(String p0); + public abstract String getNameForUid(int p0); + public abstract String[] canonicalToCurrentPackageNames(String[] p0); + public abstract String[] currentToCanonicalPackageNames(String[] p0); + public abstract String[] getPackagesForUid(int p0); + public abstract String[] getSystemSharedLibraryNames(); + public abstract XmlResourceParser getXml(String p0, int p1, ApplicationInfo p2); + public abstract boolean addPermission(PermissionInfo p0); + public abstract boolean addPermissionAsync(PermissionInfo p0); + public abstract boolean canRequestPackageInstalls(); + public abstract boolean hasSystemFeature(String p0); + public abstract boolean hasSystemFeature(String p0, int p1); + public abstract boolean isInstantApp(); + public abstract boolean isInstantApp(String p0); + public abstract boolean isPermissionRevokedByPolicy(String p0, String p1); + public abstract boolean isSafeMode(); + public abstract byte[] getInstantAppCookie(); + public abstract int checkPermission(String p0, String p1); + public abstract int checkSignatures(String p0, String p1); + public abstract int checkSignatures(int p0, int p1); + public abstract int getApplicationEnabledSetting(String p0); + public abstract int getComponentEnabledSetting(ComponentName p0); + public abstract int getInstantAppCookieMaxBytes(); + public abstract int getPackageUid(String p0, int p1); + public abstract int getPreferredActivities(List<IntentFilter> p0, List<ComponentName> p1, String p2); + public abstract int[] getPackageGids(String p0); + public abstract int[] getPackageGids(String p0, int p1); + public abstract void addPackageToPreferred(String p0); + public abstract void addPreferredActivity(IntentFilter p0, int p1, ComponentName[] p2, ComponentName p3); + public abstract void clearInstantAppCookie(); + public abstract void clearPackagePreferredActivities(String p0); + public abstract void extendVerificationTimeout(int p0, int p1, long p2); + public abstract void removePackageFromPreferred(String p0); + public abstract void removePermission(String p0); + public abstract void setApplicationCategoryHint(String p0, int p1); + public abstract void setApplicationEnabledSetting(String p0, int p1, int p2); + public abstract void setComponentEnabledSetting(ComponentName p0, int p1, int p2); + public abstract void setInstallerPackageName(String p0, String p1); + public abstract void updateInstantAppCookie(byte[] p0); + public abstract void verifyPendingInstall(int p0, int p1); + public boolean addWhitelistedRestrictedPermission(String p0, String p1, int p2){ return false; } + public boolean getSyntheticAppDetailsActivityEnabled(String p0){ return false; } + public boolean hasSigningCertificate(String p0, byte[] p1, int p2){ return false; } + public boolean hasSigningCertificate(int p0, byte[] p1, int p2){ return false; } + public boolean isAutoRevokeWhitelisted(){ return false; } + public boolean isAutoRevokeWhitelisted(String p0){ return false; } + public boolean isDefaultApplicationIcon(Drawable p0){ return false; } + public boolean isDeviceUpgrading(){ return false; } + public boolean isPackageSuspended(){ return false; } + public boolean isPackageSuspended(String p0){ return false; } + public boolean removeWhitelistedRestrictedPermission(String p0, String p1, int p2){ return false; } + public boolean setAutoRevokeWhitelisted(String p0, boolean p1){ return false; } + public static String EXTRA_VERIFICATION_ID = null; + public static String EXTRA_VERIFICATION_RESULT = null; + public static String FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS = null; + public static String FEATURE_APP_WIDGETS = null; + public static String FEATURE_AUDIO_LOW_LATENCY = null; + public static String FEATURE_AUDIO_OUTPUT = null; + public static String FEATURE_AUDIO_PRO = null; + public static String FEATURE_AUTOFILL = null; + public static String FEATURE_AUTOMOTIVE = null; + public static String FEATURE_BACKUP = null; + public static String FEATURE_BLUETOOTH = null; + public static String FEATURE_BLUETOOTH_LE = null; + public static String FEATURE_CAMERA = null; + public static String FEATURE_CAMERA_ANY = null; + public static String FEATURE_CAMERA_AR = null; + public static String FEATURE_CAMERA_AUTOFOCUS = null; + public static String FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING = null; + public static String FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR = null; + public static String FEATURE_CAMERA_CAPABILITY_RAW = null; + public static String FEATURE_CAMERA_CONCURRENT = null; + public static String FEATURE_CAMERA_EXTERNAL = null; + public static String FEATURE_CAMERA_FLASH = null; + public static String FEATURE_CAMERA_FRONT = null; + public static String FEATURE_CAMERA_LEVEL_FULL = null; + public static String FEATURE_CANT_SAVE_STATE = null; + public static String FEATURE_COMPANION_DEVICE_SETUP = null; + public static String FEATURE_CONNECTION_SERVICE = null; + public static String FEATURE_CONSUMER_IR = null; + public static String FEATURE_CONTROLS = null; + public static String FEATURE_DEVICE_ADMIN = null; + public static String FEATURE_EMBEDDED = null; + public static String FEATURE_ETHERNET = null; + public static String FEATURE_FACE = null; + public static String FEATURE_FAKETOUCH = null; + public static String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = null; + public static String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = null; + public static String FEATURE_FINGERPRINT = null; + public static String FEATURE_FREEFORM_WINDOW_MANAGEMENT = null; + public static String FEATURE_GAMEPAD = null; + public static String FEATURE_HIFI_SENSORS = null; + public static String FEATURE_HOME_SCREEN = null; + public static String FEATURE_INPUT_METHODS = null; + public static String FEATURE_IPSEC_TUNNELS = null; + public static String FEATURE_IRIS = null; + public static String FEATURE_LEANBACK = null; + public static String FEATURE_LEANBACK_ONLY = null; + public static String FEATURE_LIVE_TV = null; + public static String FEATURE_LIVE_WALLPAPER = null; + public static String FEATURE_LOCATION = null; + public static String FEATURE_LOCATION_GPS = null; + public static String FEATURE_LOCATION_NETWORK = null; + public static String FEATURE_MANAGED_USERS = null; + public static String FEATURE_MICROPHONE = null; + public static String FEATURE_MIDI = null; + public static String FEATURE_NFC = null; + public static String FEATURE_NFC_BEAM = null; + public static String FEATURE_NFC_HOST_CARD_EMULATION = null; + public static String FEATURE_NFC_HOST_CARD_EMULATION_NFCF = null; + public static String FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE = null; + public static String FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC = null; + public static String FEATURE_OPENGLES_EXTENSION_PACK = null; + public static String FEATURE_PC = null; + public static String FEATURE_PICTURE_IN_PICTURE = null; + public static String FEATURE_PRINTING = null; + public static String FEATURE_RAM_LOW = null; + public static String FEATURE_RAM_NORMAL = null; + public static String FEATURE_SCREEN_LANDSCAPE = null; + public static String FEATURE_SCREEN_PORTRAIT = null; + public static String FEATURE_SECURELY_REMOVES_USERS = null; + public static String FEATURE_SECURE_LOCK_SCREEN = null; + public static String FEATURE_SENSOR_ACCELEROMETER = null; + public static String FEATURE_SENSOR_AMBIENT_TEMPERATURE = null; + public static String FEATURE_SENSOR_BAROMETER = null; + public static String FEATURE_SENSOR_COMPASS = null; + public static String FEATURE_SENSOR_GYROSCOPE = null; + public static String FEATURE_SENSOR_HEART_RATE = null; + public static String FEATURE_SENSOR_HEART_RATE_ECG = null; + public static String FEATURE_SENSOR_HINGE_ANGLE = null; + public static String FEATURE_SENSOR_LIGHT = null; + public static String FEATURE_SENSOR_PROXIMITY = null; + public static String FEATURE_SENSOR_RELATIVE_HUMIDITY = null; + public static String FEATURE_SENSOR_STEP_COUNTER = null; + public static String FEATURE_SENSOR_STEP_DETECTOR = null; + public static String FEATURE_SE_OMAPI_ESE = null; + public static String FEATURE_SE_OMAPI_SD = null; + public static String FEATURE_SE_OMAPI_UICC = null; + public static String FEATURE_SIP = null; + public static String FEATURE_SIP_VOIP = null; + public static String FEATURE_STRONGBOX_KEYSTORE = null; + public static String FEATURE_TELEPHONY = null; + public static String FEATURE_TELEPHONY_CDMA = null; + public static String FEATURE_TELEPHONY_EUICC = null; + public static String FEATURE_TELEPHONY_GSM = null; + public static String FEATURE_TELEPHONY_IMS = null; + public static String FEATURE_TELEPHONY_MBMS = null; + public static String FEATURE_TELEVISION = null; + public static String FEATURE_TOUCHSCREEN = null; + public static String FEATURE_TOUCHSCREEN_MULTITOUCH = null; + public static String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = null; + public static String FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND = null; + public static String FEATURE_USB_ACCESSORY = null; + public static String FEATURE_USB_HOST = null; + public static String FEATURE_VERIFIED_BOOT = null; + public static String FEATURE_VR_HEADTRACKING = null; + public static String FEATURE_VR_MODE = null; + public static String FEATURE_VR_MODE_HIGH_PERFORMANCE = null; + public static String FEATURE_VULKAN_DEQP_LEVEL = null; + public static String FEATURE_VULKAN_HARDWARE_COMPUTE = null; + public static String FEATURE_VULKAN_HARDWARE_LEVEL = null; + public static String FEATURE_VULKAN_HARDWARE_VERSION = null; + public static String FEATURE_WATCH = null; + public static String FEATURE_WEBVIEW = null; + public static String FEATURE_WIFI = null; + public static String FEATURE_WIFI_AWARE = null; + public static String FEATURE_WIFI_DIRECT = null; + public static String FEATURE_WIFI_PASSPOINT = null; + public static String FEATURE_WIFI_RTT = null; + public static int CERT_INPUT_RAW_X509 = 0; + public static int CERT_INPUT_SHA256 = 0; + public static int COMPONENT_ENABLED_STATE_DEFAULT = 0; + public static int COMPONENT_ENABLED_STATE_DISABLED = 0; + public static int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 0; + public static int COMPONENT_ENABLED_STATE_DISABLED_USER = 0; + public static int COMPONENT_ENABLED_STATE_ENABLED = 0; + public static int DONT_KILL_APP = 0; + public static int FLAG_PERMISSION_WHITELIST_INSTALLER = 0; + public static int FLAG_PERMISSION_WHITELIST_SYSTEM = 0; + public static int FLAG_PERMISSION_WHITELIST_UPGRADE = 0; + public static int GET_ACTIVITIES = 0; + public static int GET_CONFIGURATIONS = 0; + public static int GET_DISABLED_COMPONENTS = 0; + public static int GET_DISABLED_UNTIL_USED_COMPONENTS = 0; + public static int GET_GIDS = 0; + public static int GET_INSTRUMENTATION = 0; + public static int GET_INTENT_FILTERS = 0; + public static int GET_META_DATA = 0; + public static int GET_PERMISSIONS = 0; + public static int GET_PROVIDERS = 0; + public static int GET_RECEIVERS = 0; + public static int GET_RESOLVED_FILTER = 0; + public static int GET_SERVICES = 0; + public static int GET_SHARED_LIBRARY_FILES = 0; + public static int GET_SIGNATURES = 0; + public static int GET_SIGNING_CERTIFICATES = 0; + public static int GET_UNINSTALLED_PACKAGES = 0; + public static int GET_URI_PERMISSION_PATTERNS = 0; + public static int INSTALL_REASON_DEVICE_RESTORE = 0; + public static int INSTALL_REASON_DEVICE_SETUP = 0; + public static int INSTALL_REASON_POLICY = 0; + public static int INSTALL_REASON_UNKNOWN = 0; + public static int INSTALL_REASON_USER = 0; + public static int MATCH_ALL = 0; + public static int MATCH_APEX = 0; + public static int MATCH_DEFAULT_ONLY = 0; + public static int MATCH_DIRECT_BOOT_AUTO = 0; + public static int MATCH_DIRECT_BOOT_AWARE = 0; + public static int MATCH_DIRECT_BOOT_UNAWARE = 0; + public static int MATCH_DISABLED_COMPONENTS = 0; + public static int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 0; + public static int MATCH_SYSTEM_ONLY = 0; + public static int MATCH_UNINSTALLED_PACKAGES = 0; + public static int PERMISSION_DENIED = 0; + public static int PERMISSION_GRANTED = 0; + public static int SIGNATURE_FIRST_NOT_SIGNED = 0; + public static int SIGNATURE_MATCH = 0; + public static int SIGNATURE_NEITHER_SIGNED = 0; + public static int SIGNATURE_NO_MATCH = 0; + public static int SIGNATURE_SECOND_NOT_SIGNED = 0; + public static int SIGNATURE_UNKNOWN_PACKAGE = 0; + public static int SYNCHRONOUS = 0; + public static int VERIFICATION_ALLOW = 0; + public static int VERIFICATION_REJECT = 0; + public static int VERSION_CODE_HIGHEST = 0; + public static long MAXIMUM_VERIFICATION_TIMEOUT = 0; + public void setMimeGroup(String p0, Set<String> p1){} + static public class NameNotFoundException extends AndroidException + { + public NameNotFoundException(){} + public NameNotFoundException(String p0){} + } +} diff --git a/java/ql/test/stubs/android/android/content/pm/PathPermission.java b/java/ql/test/stubs/android/android/content/pm/PathPermission.java new file mode 100644 index 00000000000..455adfe5be7 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/PathPermission.java @@ -0,0 +1,18 @@ +// Generated automatically from android.content.pm.PathPermission for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; + +public class PathPermission extends PatternMatcher +{ + protected PathPermission() {} + public PathPermission(Parcel p0){} + public PathPermission(String p0, int p1, String p2, String p3){} + public String getReadPermission(){ return null; } + public String getWritePermission(){ return null; } + public static Parcelable.Creator<PathPermission> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/PermissionGroupInfo.java b/java/ql/test/stubs/android/android/content/pm/PermissionGroupInfo.java new file mode 100644 index 00000000000..a74934de52f --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/PermissionGroupInfo.java @@ -0,0 +1,24 @@ +// Generated automatically from android.content.pm.PermissionGroupInfo for testing purposes + +package android.content.pm; + +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.os.Parcel; +import android.os.Parcelable; + +public class PermissionGroupInfo extends PackageItemInfo implements Parcelable +{ + public CharSequence loadDescription(PackageManager p0){ return null; } + public CharSequence nonLocalizedDescription = null; + public PermissionGroupInfo(){} + public PermissionGroupInfo(PermissionGroupInfo p0){} + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int descriptionRes = 0; + public int flags = 0; + public int priority = 0; + public static Parcelable.Creator<PermissionGroupInfo> CREATOR = null; + public static int FLAG_PERSONAL_INFO = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/PermissionInfo.java b/java/ql/test/stubs/android/android/content/pm/PermissionInfo.java new file mode 100644 index 00000000000..2c95bb9af7a --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/PermissionInfo.java @@ -0,0 +1,48 @@ +// Generated automatically from android.content.pm.PermissionInfo for testing purposes + +package android.content.pm; + +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.os.Parcel; +import android.os.Parcelable; + +public class PermissionInfo extends PackageItemInfo implements Parcelable +{ + public CharSequence loadDescription(PackageManager p0){ return null; } + public CharSequence nonLocalizedDescription = null; + public PermissionInfo(){} + public PermissionInfo(PermissionInfo p0){} + public String group = null; + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int descriptionRes = 0; + public int flags = 0; + public int getProtection(){ return 0; } + public int getProtectionFlags(){ return 0; } + public int protectionLevel = 0; + public static Parcelable.Creator<PermissionInfo> CREATOR = null; + public static int FLAG_COSTS_MONEY = 0; + public static int FLAG_HARD_RESTRICTED = 0; + public static int FLAG_IMMUTABLY_RESTRICTED = 0; + public static int FLAG_INSTALLED = 0; + public static int FLAG_SOFT_RESTRICTED = 0; + public static int PROTECTION_DANGEROUS = 0; + public static int PROTECTION_FLAG_APPOP = 0; + public static int PROTECTION_FLAG_DEVELOPMENT = 0; + public static int PROTECTION_FLAG_INSTALLER = 0; + public static int PROTECTION_FLAG_INSTANT = 0; + public static int PROTECTION_FLAG_PRE23 = 0; + public static int PROTECTION_FLAG_PREINSTALLED = 0; + public static int PROTECTION_FLAG_PRIVILEGED = 0; + public static int PROTECTION_FLAG_RUNTIME_ONLY = 0; + public static int PROTECTION_FLAG_SETUP = 0; + public static int PROTECTION_FLAG_SYSTEM = 0; + public static int PROTECTION_FLAG_VERIFIER = 0; + public static int PROTECTION_MASK_BASE = 0; + public static int PROTECTION_MASK_FLAGS = 0; + public static int PROTECTION_NORMAL = 0; + public static int PROTECTION_SIGNATURE = 0; + public static int PROTECTION_SIGNATURE_OR_SYSTEM = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/ProviderInfo.java b/java/ql/test/stubs/android/android/content/pm/ProviderInfo.java new file mode 100644 index 00000000000..93b694cae59 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ProviderInfo.java @@ -0,0 +1,33 @@ +// Generated automatically from android.content.pm.ProviderInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ComponentInfo; +import android.content.pm.PathPermission; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; +import android.util.Printer; + +public class ProviderInfo extends ComponentInfo implements Parcelable +{ + public PathPermission[] pathPermissions = null; + public PatternMatcher[] uriPermissionPatterns = null; + public ProviderInfo(){} + public ProviderInfo(ProviderInfo p0){} + public String authority = null; + public String readPermission = null; + public String toString(){ return null; } + public String writePermission = null; + public boolean forceUriPermissions = false; + public boolean grantUriPermissions = false; + public boolean isSyncable = false; + public boolean multiprocess = false; + public int describeContents(){ return 0; } + public int flags = 0; + public int initOrder = 0; + public static Parcelable.Creator<ProviderInfo> CREATOR = null; + public static int FLAG_SINGLE_USER = 0; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/ResolveInfo.java b/java/ql/test/stubs/android/android/content/pm/ResolveInfo.java new file mode 100644 index 00000000000..3ed20df0d38 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ResolveInfo.java @@ -0,0 +1,42 @@ +// Generated automatically from android.content.pm.ResolveInfo for testing purposes + +package android.content.pm; + +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; +import android.content.pm.ServiceInfo; +import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +public class ResolveInfo implements Parcelable +{ + public ActivityInfo activityInfo = null; + public CharSequence loadLabel(PackageManager p0){ return null; } + public CharSequence nonLocalizedLabel = null; + public Drawable loadIcon(PackageManager p0){ return null; } + public IntentFilter filter = null; + public ProviderInfo providerInfo = null; + public ResolveInfo(){} + public ResolveInfo(ResolveInfo p0){} + public ServiceInfo serviceInfo = null; + public String resolvePackageName = null; + public String toString(){ return null; } + public boolean isCrossProfileIntentForwarderActivity(){ return false; } + public boolean isDefault = false; + public boolean isInstantAppAvailable = false; + public final int getIconResource(){ return 0; } + public int describeContents(){ return 0; } + public int icon = 0; + public int labelRes = 0; + public int match = 0; + public int preferredOrder = 0; + public int priority = 0; + public int specificIndex = 0; + public static Parcelable.Creator<ResolveInfo> CREATOR = null; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/ServiceInfo.java b/java/ql/test/stubs/android/android/content/pm/ServiceInfo.java new file mode 100644 index 00000000000..6044d4af7bb --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/ServiceInfo.java @@ -0,0 +1,37 @@ +// Generated automatically from android.content.pm.ServiceInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ComponentInfo; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +public class ServiceInfo extends ComponentInfo implements Parcelable +{ + public ServiceInfo(){} + public ServiceInfo(ServiceInfo p0){} + public String permission = null; + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int flags = 0; + public int getForegroundServiceType(){ return 0; } + public static Parcelable.Creator<ServiceInfo> CREATOR = null; + public static int FLAG_EXTERNAL_SERVICE = 0; + public static int FLAG_ISOLATED_PROCESS = 0; + public static int FLAG_SINGLE_USER = 0; + public static int FLAG_STOP_WITH_TASK = 0; + public static int FLAG_USE_APP_ZYGOTE = 0; + public static int FOREGROUND_SERVICE_TYPE_CAMERA = 0; + public static int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 0; + public static int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 0; + public static int FOREGROUND_SERVICE_TYPE_LOCATION = 0; + public static int FOREGROUND_SERVICE_TYPE_MANIFEST = 0; + public static int FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK = 0; + public static int FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION = 0; + public static int FOREGROUND_SERVICE_TYPE_MICROPHONE = 0; + public static int FOREGROUND_SERVICE_TYPE_NONE = 0; + public static int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 0; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/SharedLibraryInfo.java b/java/ql/test/stubs/android/android/content/pm/SharedLibraryInfo.java new file mode 100644 index 00000000000..10928af2a23 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/SharedLibraryInfo.java @@ -0,0 +1,26 @@ +// Generated automatically from android.content.pm.SharedLibraryInfo for testing purposes + +package android.content.pm; + +import android.content.pm.VersionedPackage; +import android.os.Parcel; +import android.os.Parcelable; +import java.util.List; + +public class SharedLibraryInfo implements Parcelable +{ + public List<VersionedPackage> getDependentPackages(){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public VersionedPackage getDeclaringPackage(){ return null; } + public int describeContents(){ return 0; } + public int getType(){ return 0; } + public int getVersion(){ return 0; } + public long getLongVersion(){ return 0; } + public static Parcelable.Creator<SharedLibraryInfo> CREATOR = null; + public static int TYPE_BUILTIN = 0; + public static int TYPE_DYNAMIC = 0; + public static int TYPE_STATIC = 0; + public static int VERSION_UNDEFINED = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/Signature.java b/java/ql/test/stubs/android/android/content/pm/Signature.java new file mode 100644 index 00000000000..2f26fb9636e --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/Signature.java @@ -0,0 +1,22 @@ +// Generated automatically from android.content.pm.Signature for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Signature implements Parcelable +{ + protected Signature() {} + public Signature(String p0){} + public Signature(byte[] p0){} + public String toCharsString(){ return null; } + public boolean equals(Object p0){ return false; } + public byte[] toByteArray(){ return null; } + public char[] toChars(){ return null; } + public char[] toChars(char[] p0, int[] p1){ return null; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<Signature> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/SigningInfo.java b/java/ql/test/stubs/android/android/content/pm/SigningInfo.java new file mode 100644 index 00000000000..56aadea159a --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/SigningInfo.java @@ -0,0 +1,20 @@ +// Generated automatically from android.content.pm.SigningInfo for testing purposes + +package android.content.pm; + +import android.content.pm.Signature; +import android.os.Parcel; +import android.os.Parcelable; + +public class SigningInfo implements Parcelable +{ + public Signature[] getApkContentsSigners(){ return null; } + public Signature[] getSigningCertificateHistory(){ return null; } + public SigningInfo(){} + public SigningInfo(SigningInfo p0){} + public boolean hasMultipleSigners(){ return false; } + public boolean hasPastSigningCertificates(){ return false; } + public int describeContents(){ return 0; } + public static Parcelable.Creator<SigningInfo> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/pm/VersionedPackage.java b/java/ql/test/stubs/android/android/content/pm/VersionedPackage.java new file mode 100644 index 00000000000..4d4e37f54bc --- /dev/null +++ b/java/ql/test/stubs/android/android/content/pm/VersionedPackage.java @@ -0,0 +1,22 @@ +// Generated automatically from android.content.pm.VersionedPackage for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +public class VersionedPackage implements Parcelable +{ + protected VersionedPackage() {} + public String getPackageName(){ return null; } + public String toString(){ return null; } + public VersionedPackage(String p0, int p1){} + public VersionedPackage(String p0, long p1){} + public boolean equals(Object p0){ return false; } + public int describeContents(){ return 0; } + public int getVersionCode(){ return 0; } + public int hashCode(){ return 0; } + public long getLongVersionCode(){ return 0; } + public static Parcelable.Creator<VersionedPackage> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/res/AssetFileDescriptor.java b/java/ql/test/stubs/android/android/content/res/AssetFileDescriptor.java new file mode 100644 index 00000000000..46e0266dd62 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/AssetFileDescriptor.java @@ -0,0 +1,33 @@ +// Generated automatically from android.content.res.AssetFileDescriptor for testing purposes + +package android.content.res; + +import android.os.Bundle; +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; +import java.io.Closeable; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +public class AssetFileDescriptor implements Closeable, Parcelable +{ + protected AssetFileDescriptor() {} + public AssetFileDescriptor(ParcelFileDescriptor p0, long p1, long p2){} + public AssetFileDescriptor(ParcelFileDescriptor p0, long p1, long p2, Bundle p3){} + public Bundle getExtras(){ return null; } + public FileDescriptor getFileDescriptor(){ return null; } + public FileInputStream createInputStream(){ return null; } + public FileOutputStream createOutputStream(){ return null; } + public ParcelFileDescriptor getParcelFileDescriptor(){ return null; } + public String toString(){ return null; } + public int describeContents(){ return 0; } + public long getDeclaredLength(){ return 0; } + public long getLength(){ return 0; } + public long getStartOffset(){ return 0; } + public static Parcelable.Creator<AssetFileDescriptor> CREATOR = null; + public static long UNKNOWN_LENGTH = 0; + public void close(){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/res/AssetManager.java b/java/ql/test/stubs/android/android/content/res/AssetManager.java new file mode 100644 index 00000000000..37926aa5c61 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/AssetManager.java @@ -0,0 +1,26 @@ +// Generated automatically from android.content.res.AssetManager for testing purposes + +package android.content.res; + +import android.content.res.AssetFileDescriptor; +import android.content.res.XmlResourceParser; +import java.io.InputStream; + +public class AssetManager implements AutoCloseable +{ + protected void finalize(){} + public AssetFileDescriptor openFd(String p0){ return null; } + public AssetFileDescriptor openNonAssetFd(String p0){ return null; } + public AssetFileDescriptor openNonAssetFd(int p0, String p1){ return null; } + public InputStream open(String p0){ return null; } + public InputStream open(String p0, int p1){ return null; } + public String[] getLocales(){ return null; } + public String[] list(String p0){ return null; } + public XmlResourceParser openXmlResourceParser(String p0){ return null; } + public XmlResourceParser openXmlResourceParser(int p0, String p1){ return null; } + public static int ACCESS_BUFFER = 0; + public static int ACCESS_RANDOM = 0; + public static int ACCESS_STREAMING = 0; + public static int ACCESS_UNKNOWN = 0; + public void close(){} +} diff --git a/java/ql/test/stubs/android/android/content/res/ColorStateList.java b/java/ql/test/stubs/android/android/content/res/ColorStateList.java new file mode 100644 index 00000000000..cc6a1851767 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/ColorStateList.java @@ -0,0 +1,27 @@ +// Generated automatically from android.content.res.ColorStateList for testing purposes + +package android.content.res; + +import android.content.res.Resources; +import android.os.Parcel; +import android.os.Parcelable; +import org.xmlpull.v1.XmlPullParser; + +public class ColorStateList implements Parcelable +{ + protected ColorStateList() {} + public ColorStateList withAlpha(int p0){ return null; } + public ColorStateList(int[][] p0, int[] p1){} + public String toString(){ return null; } + public boolean isOpaque(){ return false; } + public boolean isStateful(){ return false; } + public int describeContents(){ return 0; } + public int getChangingConfigurations(){ return 0; } + public int getColorForState(int[] p0, int p1){ return 0; } + public int getDefaultColor(){ return 0; } + public static ColorStateList createFromXml(Resources p0, XmlPullParser p1){ return null; } + public static ColorStateList createFromXml(Resources p0, XmlPullParser p1, Resources.Theme p2){ return null; } + public static ColorStateList valueOf(int p0){ return null; } + public static Parcelable.Creator<ColorStateList> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/res/Configuration.java b/java/ql/test/stubs/android/android/content/res/Configuration.java new file mode 100644 index 00000000000..01c3f2a7d15 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/Configuration.java @@ -0,0 +1,130 @@ +// Generated automatically from android.content.res.Configuration for testing purposes + +package android.content.res; + +import android.os.LocaleList; +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Locale; + +public class Configuration implements Comparable<Configuration>, Parcelable +{ + public Configuration(){} + public Configuration(Configuration p0){} + public Locale locale = null; + public LocaleList getLocales(){ return null; } + public String toString(){ return null; } + public boolean equals(Configuration p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isLayoutSizeAtLeast(int p0){ return false; } + public boolean isNightModeActive(){ return false; } + public boolean isScreenHdr(){ return false; } + public boolean isScreenRound(){ return false; } + public boolean isScreenWideColorGamut(){ return false; } + public float fontScale = 0; + public int colorMode = 0; + public int compareTo(Configuration p0){ return 0; } + public int densityDpi = 0; + public int describeContents(){ return 0; } + public int diff(Configuration p0){ return 0; } + public int getLayoutDirection(){ return 0; } + public int hardKeyboardHidden = 0; + public int hashCode(){ return 0; } + public int keyboard = 0; + public int keyboardHidden = 0; + public int mcc = 0; + public int mnc = 0; + public int navigation = 0; + public int navigationHidden = 0; + public int orientation = 0; + public int screenHeightDp = 0; + public int screenLayout = 0; + public int screenWidthDp = 0; + public int smallestScreenWidthDp = 0; + public int touchscreen = 0; + public int uiMode = 0; + public int updateFrom(Configuration p0){ return 0; } + public static Parcelable.Creator<Configuration> CREATOR = null; + public static boolean needNewResources(int p0, int p1){ return false; } + public static int COLOR_MODE_HDR_MASK = 0; + public static int COLOR_MODE_HDR_NO = 0; + public static int COLOR_MODE_HDR_SHIFT = 0; + public static int COLOR_MODE_HDR_UNDEFINED = 0; + public static int COLOR_MODE_HDR_YES = 0; + public static int COLOR_MODE_UNDEFINED = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0; + public static int DENSITY_DPI_UNDEFINED = 0; + public static int HARDKEYBOARDHIDDEN_NO = 0; + public static int HARDKEYBOARDHIDDEN_UNDEFINED = 0; + public static int HARDKEYBOARDHIDDEN_YES = 0; + public static int KEYBOARDHIDDEN_NO = 0; + public static int KEYBOARDHIDDEN_UNDEFINED = 0; + public static int KEYBOARDHIDDEN_YES = 0; + public static int KEYBOARD_12KEY = 0; + public static int KEYBOARD_NOKEYS = 0; + public static int KEYBOARD_QWERTY = 0; + public static int KEYBOARD_UNDEFINED = 0; + public static int MNC_ZERO = 0; + public static int NAVIGATIONHIDDEN_NO = 0; + public static int NAVIGATIONHIDDEN_UNDEFINED = 0; + public static int NAVIGATIONHIDDEN_YES = 0; + public static int NAVIGATION_DPAD = 0; + public static int NAVIGATION_NONAV = 0; + public static int NAVIGATION_TRACKBALL = 0; + public static int NAVIGATION_UNDEFINED = 0; + public static int NAVIGATION_WHEEL = 0; + public static int ORIENTATION_LANDSCAPE = 0; + public static int ORIENTATION_PORTRAIT = 0; + public static int ORIENTATION_SQUARE = 0; + public static int ORIENTATION_UNDEFINED = 0; + public static int SCREENLAYOUT_LAYOUTDIR_LTR = 0; + public static int SCREENLAYOUT_LAYOUTDIR_MASK = 0; + public static int SCREENLAYOUT_LAYOUTDIR_RTL = 0; + public static int SCREENLAYOUT_LAYOUTDIR_SHIFT = 0; + public static int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0; + public static int SCREENLAYOUT_LONG_MASK = 0; + public static int SCREENLAYOUT_LONG_NO = 0; + public static int SCREENLAYOUT_LONG_UNDEFINED = 0; + public static int SCREENLAYOUT_LONG_YES = 0; + public static int SCREENLAYOUT_ROUND_MASK = 0; + public static int SCREENLAYOUT_ROUND_NO = 0; + public static int SCREENLAYOUT_ROUND_UNDEFINED = 0; + public static int SCREENLAYOUT_ROUND_YES = 0; + public static int SCREENLAYOUT_SIZE_LARGE = 0; + public static int SCREENLAYOUT_SIZE_MASK = 0; + public static int SCREENLAYOUT_SIZE_NORMAL = 0; + public static int SCREENLAYOUT_SIZE_SMALL = 0; + public static int SCREENLAYOUT_SIZE_UNDEFINED = 0; + public static int SCREENLAYOUT_SIZE_XLARGE = 0; + public static int SCREENLAYOUT_UNDEFINED = 0; + public static int SCREEN_HEIGHT_DP_UNDEFINED = 0; + public static int SCREEN_WIDTH_DP_UNDEFINED = 0; + public static int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0; + public static int TOUCHSCREEN_FINGER = 0; + public static int TOUCHSCREEN_NOTOUCH = 0; + public static int TOUCHSCREEN_STYLUS = 0; + public static int TOUCHSCREEN_UNDEFINED = 0; + public static int UI_MODE_NIGHT_MASK = 0; + public static int UI_MODE_NIGHT_NO = 0; + public static int UI_MODE_NIGHT_UNDEFINED = 0; + public static int UI_MODE_NIGHT_YES = 0; + public static int UI_MODE_TYPE_APPLIANCE = 0; + public static int UI_MODE_TYPE_CAR = 0; + public static int UI_MODE_TYPE_DESK = 0; + public static int UI_MODE_TYPE_MASK = 0; + public static int UI_MODE_TYPE_NORMAL = 0; + public static int UI_MODE_TYPE_TELEVISION = 0; + public static int UI_MODE_TYPE_UNDEFINED = 0; + public static int UI_MODE_TYPE_VR_HEADSET = 0; + public static int UI_MODE_TYPE_WATCH = 0; + public void readFromParcel(Parcel p0){} + public void setLayoutDirection(Locale p0){} + public void setLocale(Locale p0){} + public void setLocales(LocaleList p0){} + public void setTo(Configuration p0){} + public void setToDefaults(){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/content/res/Resources.java b/java/ql/test/stubs/android/android/content/res/Resources.java new file mode 100644 index 00000000000..9277c4ee765 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/Resources.java @@ -0,0 +1,105 @@ +// Generated automatically from android.content.res.Resources for testing purposes + +package android.content.res; + +import android.content.res.AssetFileDescriptor; +import android.content.res.AssetManager; +import android.content.res.ColorStateList; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.content.res.loader.ResourcesLoader; +import android.graphics.Movie; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import java.io.InputStream; + +public class Resources +{ + protected Resources() {} + public AssetFileDescriptor openRawResourceFd(int p0){ return null; } + public CharSequence getQuantityText(int p0, int p1){ return null; } + public CharSequence getText(int p0){ return null; } + public CharSequence getText(int p0, CharSequence p1){ return null; } + public CharSequence[] getTextArray(int p0){ return null; } + public ColorStateList getColorStateList(int p0){ return null; } + public ColorStateList getColorStateList(int p0, Resources.Theme p1){ return null; } + public Configuration getConfiguration(){ return null; } + public DisplayMetrics getDisplayMetrics(){ return null; } + public Drawable getDrawable(int p0){ return null; } + public Drawable getDrawable(int p0, Resources.Theme p1){ return null; } + public Drawable getDrawableForDensity(int p0, int p1){ return null; } + public Drawable getDrawableForDensity(int p0, int p1, Resources.Theme p2){ return null; } + public InputStream openRawResource(int p0){ return null; } + public InputStream openRawResource(int p0, TypedValue p1){ return null; } + public Movie getMovie(int p0){ return null; } + public Resources(AssetManager p0, DisplayMetrics p1, Configuration p2){} + public String getQuantityString(int p0, int p1){ return null; } + public String getQuantityString(int p0, int p1, Object... p2){ return null; } + public String getResourceEntryName(int p0){ return null; } + public String getResourceName(int p0){ return null; } + public String getResourcePackageName(int p0){ return null; } + public String getResourceTypeName(int p0){ return null; } + public String getString(int p0){ return null; } + public String getString(int p0, Object... p1){ return null; } + public String[] getStringArray(int p0){ return null; } + public TypedArray obtainAttributes(AttributeSet p0, int[] p1){ return null; } + public TypedArray obtainTypedArray(int p0){ return null; } + public Typeface getFont(int p0){ return null; } + public XmlResourceParser getAnimation(int p0){ return null; } + public XmlResourceParser getLayout(int p0){ return null; } + public XmlResourceParser getXml(int p0){ return null; } + public boolean getBoolean(int p0){ return false; } + public class Theme + { + protected Theme() {} + public Drawable getDrawable(int p0){ return null; } + public Resources getResources(){ return null; } + public TypedArray obtainStyledAttributes(AttributeSet p0, int[] p1, int p2, int p3){ return null; } + public TypedArray obtainStyledAttributes(int p0, int[] p1){ return null; } + public TypedArray obtainStyledAttributes(int[] p0){ return null; } + public boolean resolveAttribute(int p0, TypedValue p1, boolean p2){ return false; } + public int getChangingConfigurations(){ return 0; } + public int getExplicitStyle(AttributeSet p0){ return 0; } + public int[] getAttributeResolutionStack(int p0, int p1, int p2){ return null; } + public void applyStyle(int p0, boolean p1){} + public void dump(int p0, String p1, String p2){} + public void rebase(){} + public void setTo(Resources.Theme p0){} + } + public final AssetManager getAssets(){ return null; } + public final Resources.Theme newTheme(){ return null; } + public final void finishPreloading(){} + public final void flushLayoutCache(){} + public float getDimension(int p0){ return 0; } + public float getFloat(int p0){ return 0; } + public float getFraction(int p0, int p1, int p2){ return 0; } + public int getColor(int p0){ return 0; } + public int getColor(int p0, Resources.Theme p1){ return 0; } + public int getDimensionPixelOffset(int p0){ return 0; } + public int getDimensionPixelSize(int p0){ return 0; } + public int getIdentifier(String p0, String p1, String p2){ return 0; } + public int getInteger(int p0){ return 0; } + public int[] getIntArray(int p0){ return null; } + public static Resources getSystem(){ return null; } + public static int ID_NULL = 0; + public static int getAttributeSetSourceResId(AttributeSet p0){ return 0; } + public void addLoaders(ResourcesLoader... p0){} + public void getValue(String p0, TypedValue p1, boolean p2){} + public void getValue(int p0, TypedValue p1, boolean p2){} + public void getValueForDensity(int p0, int p1, TypedValue p2, boolean p3){} + public void parseBundleExtra(String p0, AttributeSet p1, Bundle p2){} + public void parseBundleExtras(XmlResourceParser p0, Bundle p1){} + public void removeLoaders(ResourcesLoader... p0){} + public void updateConfiguration(Configuration p0, DisplayMetrics p1){} + static public class NotFoundException extends RuntimeException + { + public NotFoundException(){} + public NotFoundException(String p0){} + public NotFoundException(String p0, Exception p1){} + } +} diff --git a/java/ql/test/stubs/android/android/content/res/TypedArray.java b/java/ql/test/stubs/android/android/content/res/TypedArray.java new file mode 100644 index 00000000000..2b857671f88 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/TypedArray.java @@ -0,0 +1,46 @@ +// Generated automatically from android.content.res.TypedArray for testing purposes + +package android.content.res; + +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.util.TypedValue; + +public class TypedArray +{ + public CharSequence getText(int p0){ return null; } + public CharSequence[] getTextArray(int p0){ return null; } + public ColorStateList getColorStateList(int p0){ return null; } + public Drawable getDrawable(int p0){ return null; } + public Resources getResources(){ return null; } + public String getNonResourceString(int p0){ return null; } + public String getPositionDescription(){ return null; } + public String getString(int p0){ return null; } + public String toString(){ return null; } + public TypedValue peekValue(int p0){ return null; } + public Typeface getFont(int p0){ return null; } + public boolean getBoolean(int p0, boolean p1){ return false; } + public boolean getValue(int p0, TypedValue p1){ return false; } + public boolean hasValue(int p0){ return false; } + public boolean hasValueOrEmpty(int p0){ return false; } + public float getDimension(int p0, float p1){ return 0; } + public float getFloat(int p0, float p1){ return 0; } + public float getFraction(int p0, int p1, int p2, float p3){ return 0; } + public int getChangingConfigurations(){ return 0; } + public int getColor(int p0, int p1){ return 0; } + public int getDimensionPixelOffset(int p0, int p1){ return 0; } + public int getDimensionPixelSize(int p0, int p1){ return 0; } + public int getIndex(int p0){ return 0; } + public int getIndexCount(){ return 0; } + public int getInt(int p0, int p1){ return 0; } + public int getInteger(int p0, int p1){ return 0; } + public int getLayoutDimension(int p0, String p1){ return 0; } + public int getLayoutDimension(int p0, int p1){ return 0; } + public int getResourceId(int p0, int p1){ return 0; } + public int getSourceResourceId(int p0, int p1){ return 0; } + public int getType(int p0){ return 0; } + public int length(){ return 0; } + public void recycle(){} +} diff --git a/java/ql/test/stubs/android/android/content/res/XmlResourceParser.java b/java/ql/test/stubs/android/android/content/res/XmlResourceParser.java new file mode 100644 index 00000000000..61a50fe8bec --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/XmlResourceParser.java @@ -0,0 +1,12 @@ +// Generated automatically from android.content.res.XmlResourceParser for testing purposes + +package android.content.res; + +import android.util.AttributeSet; +import org.xmlpull.v1.XmlPullParser; + +public interface XmlResourceParser extends AttributeSet, AutoCloseable, XmlPullParser +{ + String getAttributeNamespace(int p0); + void close(); +} diff --git a/java/ql/test/stubs/android/android/content/res/loader/AssetsProvider.java b/java/ql/test/stubs/android/android/content/res/loader/AssetsProvider.java new file mode 100644 index 00000000000..bf99474dcb1 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/loader/AssetsProvider.java @@ -0,0 +1,10 @@ +// Generated automatically from android.content.res.loader.AssetsProvider for testing purposes + +package android.content.res.loader; + +import android.content.res.AssetFileDescriptor; + +public interface AssetsProvider +{ + default AssetFileDescriptor loadAssetFd(String p0, int p1){ return null; } +} diff --git a/java/ql/test/stubs/android/android/content/res/loader/ResourcesLoader.java b/java/ql/test/stubs/android/android/content/res/loader/ResourcesLoader.java new file mode 100644 index 00000000000..1ad577ab478 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/loader/ResourcesLoader.java @@ -0,0 +1,16 @@ +// Generated automatically from android.content.res.loader.ResourcesLoader for testing purposes + +package android.content.res.loader; + +import android.content.res.loader.ResourcesProvider; +import java.util.List; + +public class ResourcesLoader +{ + public List<ResourcesProvider> getProviders(){ return null; } + public ResourcesLoader(){} + public void addProvider(ResourcesProvider p0){} + public void clearProviders(){} + public void removeProvider(ResourcesProvider p0){} + public void setProviders(List<ResourcesProvider> p0){} +} diff --git a/java/ql/test/stubs/android/android/content/res/loader/ResourcesProvider.java b/java/ql/test/stubs/android/android/content/res/loader/ResourcesProvider.java new file mode 100644 index 00000000000..059b0961b59 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/res/loader/ResourcesProvider.java @@ -0,0 +1,21 @@ +// Generated automatically from android.content.res.loader.ResourcesProvider for testing purposes + +package android.content.res.loader; + +import android.content.Context; +import android.content.res.loader.AssetsProvider; +import android.os.ParcelFileDescriptor; +import java.io.Closeable; + +public class ResourcesProvider implements AutoCloseable, Closeable +{ + protected ResourcesProvider() {} + protected void finalize(){} + public static ResourcesProvider empty(AssetsProvider p0){ return null; } + public static ResourcesProvider loadFromApk(ParcelFileDescriptor p0){ return null; } + public static ResourcesProvider loadFromApk(ParcelFileDescriptor p0, AssetsProvider p1){ return null; } + public static ResourcesProvider loadFromDirectory(String p0, AssetsProvider p1){ return null; } + public static ResourcesProvider loadFromSplit(Context p0, String p1){ return null; } + public static ResourcesProvider loadFromTable(ParcelFileDescriptor p0, AssetsProvider p1){ return null; } + public void close(){} +} diff --git a/java/ql/test/stubs/android/android/database/CharArrayBuffer.java b/java/ql/test/stubs/android/android/database/CharArrayBuffer.java new file mode 100644 index 00000000000..b75eff88239 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/CharArrayBuffer.java @@ -0,0 +1,13 @@ +// Generated automatically from android.database.CharArrayBuffer for testing purposes + +package android.database; + + +public class CharArrayBuffer +{ + protected CharArrayBuffer() {} + public CharArrayBuffer(char[] p0){} + public CharArrayBuffer(int p0){} + public char[] data = null; + public int sizeCopied = 0; +} diff --git a/java/ql/test/stubs/android/android/database/ContentObserver.java b/java/ql/test/stubs/android/android/database/ContentObserver.java new file mode 100644 index 00000000000..f70e12dc20c --- /dev/null +++ b/java/ql/test/stubs/android/android/database/ContentObserver.java @@ -0,0 +1,22 @@ +// Generated automatically from android.database.ContentObserver for testing purposes + +package android.database; + +import android.net.Uri; +import android.os.Handler; +import java.util.Collection; + +abstract public class ContentObserver +{ + protected ContentObserver() {} + public ContentObserver(Handler p0){} + public boolean deliverSelfNotifications(){ return false; } + public final void dispatchChange(boolean p0){} + public final void dispatchChange(boolean p0, Collection<Uri> p1, int p2){} + public final void dispatchChange(boolean p0, Uri p1){} + public final void dispatchChange(boolean p0, Uri p1, int p2){} + public void onChange(boolean p0){} + public void onChange(boolean p0, Collection<Uri> p1, int p2){} + public void onChange(boolean p0, Uri p1){} + public void onChange(boolean p0, Uri p1, int p2){} +} diff --git a/java/ql/test/stubs/android/android/database/Cursor.java b/java/ql/test/stubs/android/android/database/Cursor.java index cc432b1ad06..e692f9be738 100644 --- a/java/ql/test/stubs/android/android/database/Cursor.java +++ b/java/ql/test/stubs/android/android/database/Cursor.java @@ -1,5 +1,64 @@ +// Generated automatically from android.database.Cursor for testing purposes + package android.database; -public interface Cursor { +import android.content.ContentResolver; +import android.database.CharArrayBuffer; +import android.database.ContentObserver; +import android.database.DataSetObserver; +import android.net.Uri; +import android.os.Bundle; +import java.io.Closeable; +import java.util.List; +public interface Cursor extends Closeable +{ + Bundle getExtras(); + Bundle respond(Bundle p0); + String getColumnName(int p0); + String getString(int p0); + String[] getColumnNames(); + Uri getNotificationUri(); + boolean getWantsAllOnMoveCalls(); + boolean isAfterLast(); + boolean isBeforeFirst(); + boolean isClosed(); + boolean isFirst(); + boolean isLast(); + boolean isNull(int p0); + boolean move(int p0); + boolean moveToFirst(); + boolean moveToLast(); + boolean moveToNext(); + boolean moveToPosition(int p0); + boolean moveToPrevious(); + boolean requery(); + byte[] getBlob(int p0); + default List<Uri> getNotificationUris(){ return null; } + default void setNotificationUris(ContentResolver p0, List<Uri> p1){} + double getDouble(int p0); + float getFloat(int p0); + int getColumnCount(); + int getColumnIndex(String p0); + int getColumnIndexOrThrow(String p0); + int getCount(); + int getInt(int p0); + int getPosition(); + int getType(int p0); + long getLong(int p0); + short getShort(int p0); + static int FIELD_TYPE_BLOB = 0; + static int FIELD_TYPE_FLOAT = 0; + static int FIELD_TYPE_INTEGER = 0; + static int FIELD_TYPE_NULL = 0; + static int FIELD_TYPE_STRING = 0; + void close(); + void copyStringToBuffer(int p0, CharArrayBuffer p1); + void deactivate(); + void registerContentObserver(ContentObserver p0); + void registerDataSetObserver(DataSetObserver p0); + void setExtras(Bundle p0); + void setNotificationUri(ContentResolver p0, Uri p1); + void unregisterContentObserver(ContentObserver p0); + void unregisterDataSetObserver(DataSetObserver p0); } diff --git a/java/ql/test/stubs/android/android/database/DataSetObserver.java b/java/ql/test/stubs/android/android/database/DataSetObserver.java new file mode 100644 index 00000000000..6ca449b2e95 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/DataSetObserver.java @@ -0,0 +1,11 @@ +// Generated automatically from android.database.DataSetObserver for testing purposes + +package android.database; + + +abstract public class DataSetObserver +{ + public DataSetObserver(){} + public void onChanged(){} + public void onInvalidated(){} +} diff --git a/java/ql/test/stubs/android/android/database/DatabaseErrorHandler.java b/java/ql/test/stubs/android/android/database/DatabaseErrorHandler.java new file mode 100644 index 00000000000..c52eb9698a7 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/DatabaseErrorHandler.java @@ -0,0 +1,10 @@ +// Generated automatically from android.database.DatabaseErrorHandler for testing purposes + +package android.database; + +import android.database.sqlite.SQLiteDatabase; + +public interface DatabaseErrorHandler +{ + void onCorruption(SQLiteDatabase p0); +} diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteClosable.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteClosable.java new file mode 100644 index 00000000000..8295e8d0d61 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteClosable.java @@ -0,0 +1,16 @@ +// Generated automatically from android.database.sqlite.SQLiteClosable for testing purposes + +package android.database.sqlite; + +import java.io.Closeable; + +abstract public class SQLiteClosable implements Closeable +{ + protected abstract void onAllReferencesReleased(); + protected void onAllReferencesReleasedFromContainer(){} + public SQLiteClosable(){} + public void acquireReference(){} + public void close(){} + public void releaseReference(){} + public void releaseReferenceFromContainer(){} +} diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteCursorDriver.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteCursorDriver.java new file mode 100644 index 00000000000..3d5cb99a2d0 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteCursorDriver.java @@ -0,0 +1,15 @@ +// Generated automatically from android.database.sqlite.SQLiteCursorDriver for testing purposes + +package android.database.sqlite; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +public interface SQLiteCursorDriver +{ + Cursor query(SQLiteDatabase.CursorFactory p0, String[] p1); + void cursorClosed(); + void cursorDeactivated(); + void cursorRequeried(Cursor p0); + void setBindArguments(String[] p0); +} diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteDatabase.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteDatabase.java index 6f5b6bd2eea..64b62e68d44 100644 --- a/java/ql/test/stubs/android/android/database/sqlite/SQLiteDatabase.java +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteDatabase.java @@ -1,56 +1,127 @@ +// Generated automatically from android.database.sqlite.SQLiteDatabase for testing purposes + package android.database.sqlite; import android.content.ContentValues; +import android.database.Cursor; +import android.database.DatabaseErrorHandler; +import android.database.sqlite.SQLiteClosable; +import android.database.sqlite.SQLiteCursorDriver; +import android.database.sqlite.SQLiteQuery; +import android.database.sqlite.SQLiteStatement; +import android.database.sqlite.SQLiteTransactionListener; import android.os.CancellationSignal; +import android.util.Pair; +import java.io.File; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.BinaryOperator; +import java.util.function.UnaryOperator; -public abstract class SQLiteDatabase { - public class CursorFactory { - - } - - public abstract void execPerConnectionSQL(String sql, Object[] bindArgs); - - public abstract void execSQL(String sql); - - public abstract void execSQL(String sql, Object[] bindArgs); - - public abstract void query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, - String groupBy, String having, String orderBy, String limit); - - public abstract void query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, - String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal); - - public abstract void query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, - String having, String orderBy, String limit); - - public abstract void query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, - String having, String orderBy); - - public abstract void queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, - String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, - String limit, CancellationSignal cancellationSignal); - - public abstract void queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, - String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, - String limit); - - public abstract void rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal); - - public abstract void rawQuery(String sql, String[] selectionArgs); - - public abstract void rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, - String editTable, CancellationSignal cancellationSignal); - - public abstract void rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, - String editTable); - - public abstract void compileStatement(String sql); - - public abstract void delete(String table, String whereClause, String[] whereArgs); - - public abstract void update(String table, ContentValues values, String whereClause, String[] whereArgs); - - public abstract void updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, - int conflictAlgorithm); - +public class SQLiteDatabase extends SQLiteClosable +{ + protected SQLiteDatabase() {} + protected void finalize(){} + protected void onAllReferencesReleased(){} + public Cursor query(String p0, String[] p1, String p2, String[] p3, String p4, String p5, String p6){ return null; } + public Cursor query(String p0, String[] p1, String p2, String[] p3, String p4, String p5, String p6, String p7){ return null; } + public Cursor query(boolean p0, String p1, String[] p2, String p3, String[] p4, String p5, String p6, String p7, String p8){ return null; } + public Cursor query(boolean p0, String p1, String[] p2, String p3, String[] p4, String p5, String p6, String p7, String p8, CancellationSignal p9){ return null; } + public Cursor queryWithFactory(SQLiteDatabase.CursorFactory p0, boolean p1, String p2, String[] p3, String p4, String[] p5, String p6, String p7, String p8, String p9){ return null; } + public Cursor queryWithFactory(SQLiteDatabase.CursorFactory p0, boolean p1, String p2, String[] p3, String p4, String[] p5, String p6, String p7, String p8, String p9, CancellationSignal p10){ return null; } + public Cursor rawQuery(String p0, String[] p1){ return null; } + public Cursor rawQuery(String p0, String[] p1, CancellationSignal p2){ return null; } + public Cursor rawQueryWithFactory(SQLiteDatabase.CursorFactory p0, String p1, String[] p2, String p3){ return null; } + public Cursor rawQueryWithFactory(SQLiteDatabase.CursorFactory p0, String p1, String[] p2, String p3, CancellationSignal p4){ return null; } + public List<Pair<String, String>> getAttachedDbs(){ return null; } + public Map<String, String> getSyncedTables(){ return null; } + public SQLiteStatement compileStatement(String p0){ return null; } + public String getPath(){ return null; } + public String toString(){ return null; } + public boolean enableWriteAheadLogging(){ return false; } + public boolean inTransaction(){ return false; } + public boolean isDatabaseIntegrityOk(){ return false; } + public boolean isDbLockedByCurrentThread(){ return false; } + public boolean isDbLockedByOtherThreads(){ return false; } + public boolean isOpen(){ return false; } + public boolean isReadOnly(){ return false; } + public boolean isWriteAheadLoggingEnabled(){ return false; } + public boolean needUpgrade(int p0){ return false; } + public boolean yieldIfContended(){ return false; } + public boolean yieldIfContendedSafely(){ return false; } + public boolean yieldIfContendedSafely(long p0){ return false; } + public int delete(String p0, String p1, String[] p2){ return 0; } + public int getVersion(){ return 0; } + public int update(String p0, ContentValues p1, String p2, String[] p3){ return 0; } + public int updateWithOnConflict(String p0, ContentValues p1, String p2, String[] p3, int p4){ return 0; } + public long getMaximumSize(){ return 0; } + public long getPageSize(){ return 0; } + public long insert(String p0, String p1, ContentValues p2){ return 0; } + public long insertOrThrow(String p0, String p1, ContentValues p2){ return 0; } + public long insertWithOnConflict(String p0, String p1, ContentValues p2, int p3){ return 0; } + public long replace(String p0, String p1, ContentValues p2){ return 0; } + public long replaceOrThrow(String p0, String p1, ContentValues p2){ return 0; } + public long setMaximumSize(long p0){ return 0; } + public static SQLiteDatabase create(SQLiteDatabase.CursorFactory p0){ return null; } + public static SQLiteDatabase createInMemory(SQLiteDatabase.OpenParams p0){ return null; } + public static SQLiteDatabase openDatabase(File p0, SQLiteDatabase.OpenParams p1){ return null; } + public static SQLiteDatabase openDatabase(String p0, SQLiteDatabase.CursorFactory p1, int p2){ return null; } + public static SQLiteDatabase openDatabase(String p0, SQLiteDatabase.CursorFactory p1, int p2, DatabaseErrorHandler p3){ return null; } + public static SQLiteDatabase openOrCreateDatabase(File p0, SQLiteDatabase.CursorFactory p1){ return null; } + public static SQLiteDatabase openOrCreateDatabase(String p0, SQLiteDatabase.CursorFactory p1){ return null; } + public static SQLiteDatabase openOrCreateDatabase(String p0, SQLiteDatabase.CursorFactory p1, DatabaseErrorHandler p2){ return null; } + public static String findEditTable(String p0){ return null; } + public static boolean deleteDatabase(File p0){ return false; } + public static int CONFLICT_ABORT = 0; + public static int CONFLICT_FAIL = 0; + public static int CONFLICT_IGNORE = 0; + public static int CONFLICT_NONE = 0; + public static int CONFLICT_REPLACE = 0; + public static int CONFLICT_ROLLBACK = 0; + public static int CREATE_IF_NECESSARY = 0; + public static int ENABLE_WRITE_AHEAD_LOGGING = 0; + public static int MAX_SQL_CACHE_SIZE = 0; + public static int NO_LOCALIZED_COLLATORS = 0; + public static int OPEN_READONLY = 0; + public static int OPEN_READWRITE = 0; + public static int SQLITE_MAX_LIKE_PATTERN_LENGTH = 0; + public static int releaseMemory(){ return 0; } + public void beginTransaction(){} + public void beginTransactionNonExclusive(){} + public void beginTransactionWithListener(SQLiteTransactionListener p0){} + public void beginTransactionWithListenerNonExclusive(SQLiteTransactionListener p0){} + public void disableWriteAheadLogging(){} + public void endTransaction(){} + public void execPerConnectionSQL(String p0, Object[] p1){} + public void execSQL(String p0){} + public void execSQL(String p0, Object[] p1){} + public void markTableSyncable(String p0, String p1){} + public void markTableSyncable(String p0, String p1, String p2){} + public void setCustomAggregateFunction(String p0, BinaryOperator<String> p1){} + public void setCustomScalarFunction(String p0, UnaryOperator<String> p1){} + public void setForeignKeyConstraintsEnabled(boolean p0){} + public void setLocale(Locale p0){} + public void setLockingEnabled(boolean p0){} + public void setMaxSqlCacheSize(int p0){} + public void setPageSize(long p0){} + public void setTransactionSuccessful(){} + public void setVersion(int p0){} + public void validateSql(String p0, CancellationSignal p1){} + static public class OpenParams + { + protected OpenParams() {} + public DatabaseErrorHandler getErrorHandler(){ return null; } + public SQLiteDatabase.CursorFactory getCursorFactory(){ return null; } + public String getJournalMode(){ return null; } + public String getSynchronousMode(){ return null; } + public int getLookasideSlotCount(){ return 0; } + public int getLookasideSlotSize(){ return 0; } + public int getOpenFlags(){ return 0; } + public long getIdleConnectionTimeout(){ return 0; } + } + static public interface CursorFactory + { + Cursor newCursor(SQLiteDatabase p0, SQLiteCursorDriver p1, String p2, SQLiteQuery p3); + } } diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteProgram.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteProgram.java new file mode 100644 index 00000000000..15f078a4c16 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteProgram.java @@ -0,0 +1,18 @@ +// Generated automatically from android.database.sqlite.SQLiteProgram for testing purposes + +package android.database.sqlite; + +import android.database.sqlite.SQLiteClosable; + +abstract public class SQLiteProgram extends SQLiteClosable +{ + protected void onAllReferencesReleased(){} + public final int getUniqueId(){ return 0; } + public void bindAllArgsAsStrings(String[] p0){} + public void bindBlob(int p0, byte[] p1){} + public void bindDouble(int p0, double p1){} + public void bindLong(int p0, long p1){} + public void bindNull(int p0){} + public void bindString(int p0, String p1){} + public void clearBindings(){} +} diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteQuery.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteQuery.java new file mode 100644 index 00000000000..a2169bcf238 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteQuery.java @@ -0,0 +1,10 @@ +// Generated automatically from android.database.sqlite.SQLiteQuery for testing purposes + +package android.database.sqlite; + +import android.database.sqlite.SQLiteProgram; + +public class SQLiteQuery extends SQLiteProgram +{ + public String toString(){ return null; } +} diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteStatement.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteStatement.java new file mode 100644 index 00000000000..e96a0d28725 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteStatement.java @@ -0,0 +1,17 @@ +// Generated automatically from android.database.sqlite.SQLiteStatement for testing purposes + +package android.database.sqlite; + +import android.database.sqlite.SQLiteProgram; +import android.os.ParcelFileDescriptor; + +public class SQLiteStatement extends SQLiteProgram +{ + public ParcelFileDescriptor simpleQueryForBlobFileDescriptor(){ return null; } + public String simpleQueryForString(){ return null; } + public String toString(){ return null; } + public int executeUpdateDelete(){ return 0; } + public long executeInsert(){ return 0; } + public long simpleQueryForLong(){ return 0; } + public void execute(){} +} diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteTransactionListener.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteTransactionListener.java new file mode 100644 index 00000000000..31895691b11 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteTransactionListener.java @@ -0,0 +1,11 @@ +// Generated automatically from android.database.sqlite.SQLiteTransactionListener for testing purposes + +package android.database.sqlite; + + +public interface SQLiteTransactionListener +{ + void onBegin(); + void onCommit(); + void onRollback(); +} diff --git a/java/ql/test/stubs/android/android/graphics/Bitmap.java b/java/ql/test/stubs/android/android/graphics/Bitmap.java new file mode 100644 index 00000000000..cf7a3b69176 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Bitmap.java @@ -0,0 +1,97 @@ +// Generated automatically from android.graphics.Bitmap for testing purposes + +package android.graphics; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorSpace; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Picture; +import android.hardware.HardwareBuffer; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DisplayMetrics; +import java.io.OutputStream; +import java.nio.Buffer; + +public class Bitmap implements Parcelable +{ + public Bitmap copy(Bitmap.Config p0, boolean p1){ return null; } + public Bitmap extractAlpha(){ return null; } + public Bitmap extractAlpha(Paint p0, int[] p1){ return null; } + public Bitmap.Config getConfig(){ return null; } + public Color getColor(int p0, int p1){ return null; } + public ColorSpace getColorSpace(){ return null; } + public boolean compress(Bitmap.CompressFormat p0, int p1, OutputStream p2){ return false; } + public boolean hasAlpha(){ return false; } + public boolean hasMipMap(){ return false; } + public boolean isMutable(){ return false; } + public boolean isPremultiplied(){ return false; } + public boolean isRecycled(){ return false; } + public boolean sameAs(Bitmap p0){ return false; } + public byte[] getNinePatchChunk(){ return null; } + public int describeContents(){ return 0; } + public int getAllocationByteCount(){ return 0; } + public int getByteCount(){ return 0; } + public int getDensity(){ return 0; } + public int getGenerationId(){ return 0; } + public int getHeight(){ return 0; } + public int getPixel(int p0, int p1){ return 0; } + public int getRowBytes(){ return 0; } + public int getScaledHeight(Canvas p0){ return 0; } + public int getScaledHeight(DisplayMetrics p0){ return 0; } + public int getScaledHeight(int p0){ return 0; } + public int getScaledWidth(Canvas p0){ return 0; } + public int getScaledWidth(DisplayMetrics p0){ return 0; } + public int getScaledWidth(int p0){ return 0; } + public int getWidth(){ return 0; } + public static Bitmap createBitmap(Bitmap p0){ return null; } + public static Bitmap createBitmap(Bitmap p0, int p1, int p2, int p3, int p4){ return null; } + public static Bitmap createBitmap(Bitmap p0, int p1, int p2, int p3, int p4, Matrix p5, boolean p6){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int p1, int p2, Bitmap.Config p3){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int p1, int p2, Bitmap.Config p3, boolean p4){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int p1, int p2, Bitmap.Config p3, boolean p4, ColorSpace p5){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int[] p1, int p2, int p3, Bitmap.Config p4){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int[] p1, int p2, int p3, int p4, int p5, Bitmap.Config p6){ return null; } + public static Bitmap createBitmap(Picture p0){ return null; } + public static Bitmap createBitmap(Picture p0, int p1, int p2, Bitmap.Config p3){ return null; } + public static Bitmap createBitmap(int p0, int p1, Bitmap.Config p2){ return null; } + public static Bitmap createBitmap(int p0, int p1, Bitmap.Config p2, boolean p3){ return null; } + public static Bitmap createBitmap(int p0, int p1, Bitmap.Config p2, boolean p3, ColorSpace p4){ return null; } + public static Bitmap createBitmap(int[] p0, int p1, int p2, Bitmap.Config p3){ return null; } + public static Bitmap createBitmap(int[] p0, int p1, int p2, int p3, int p4, Bitmap.Config p5){ return null; } + public static Bitmap createScaledBitmap(Bitmap p0, int p1, int p2, boolean p3){ return null; } + public static Bitmap wrapHardwareBuffer(HardwareBuffer p0, ColorSpace p1){ return null; } + public static Parcelable.Creator<Bitmap> CREATOR = null; + public static int DENSITY_NONE = 0; + public void copyPixelsFromBuffer(Buffer p0){} + public void copyPixelsToBuffer(Buffer p0){} + public void eraseColor(int p0){} + public void eraseColor(long p0){} + public void getPixels(int[] p0, int p1, int p2, int p3, int p4, int p5, int p6){} + public void prepareToDraw(){} + public void reconfigure(int p0, int p1, Bitmap.Config p2){} + public void recycle(){} + public void setColorSpace(ColorSpace p0){} + public void setConfig(Bitmap.Config p0){} + public void setDensity(int p0){} + public void setHasAlpha(boolean p0){} + public void setHasMipMap(boolean p0){} + public void setHeight(int p0){} + public void setPixel(int p0, int p1, int p2){} + public void setPixels(int[] p0, int p1, int p2, int p3, int p4, int p5, int p6){} + public void setPremultiplied(boolean p0){} + public void setWidth(int p0){} + public void writeToParcel(Parcel p0, int p1){} + static public enum CompressFormat + { + JPEG, PNG, WEBP, WEBP_LOSSLESS, WEBP_LOSSY; + private CompressFormat() {} + } + static public enum Config + { + ALPHA_8, ARGB_4444, ARGB_8888, HARDWARE, RGBA_F16, RGB_565; + private Config() {} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/BitmapFactory.java b/java/ql/test/stubs/android/android/graphics/BitmapFactory.java new file mode 100644 index 00000000000..f6e05c10de9 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/BitmapFactory.java @@ -0,0 +1,54 @@ +// Generated automatically from android.graphics.BitmapFactory for testing purposes + +package android.graphics; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.ColorSpace; +import android.graphics.Rect; +import android.util.TypedValue; +import java.io.FileDescriptor; +import java.io.InputStream; + +public class BitmapFactory +{ + public BitmapFactory(){} + public static Bitmap decodeByteArray(byte[] p0, int p1, int p2){ return null; } + public static Bitmap decodeByteArray(byte[] p0, int p1, int p2, BitmapFactory.Options p3){ return null; } + public static Bitmap decodeFile(String p0){ return null; } + public static Bitmap decodeFile(String p0, BitmapFactory.Options p1){ return null; } + public static Bitmap decodeFileDescriptor(FileDescriptor p0){ return null; } + public static Bitmap decodeFileDescriptor(FileDescriptor p0, Rect p1, BitmapFactory.Options p2){ return null; } + public static Bitmap decodeResource(Resources p0, int p1){ return null; } + public static Bitmap decodeResource(Resources p0, int p1, BitmapFactory.Options p2){ return null; } + public static Bitmap decodeResourceStream(Resources p0, TypedValue p1, InputStream p2, Rect p3, BitmapFactory.Options p4){ return null; } + public static Bitmap decodeStream(InputStream p0){ return null; } + public static Bitmap decodeStream(InputStream p0, Rect p1, BitmapFactory.Options p2){ return null; } + static public class Options + { + public Bitmap inBitmap = null; + public Bitmap.Config inPreferredConfig = null; + public Bitmap.Config outConfig = null; + public ColorSpace inPreferredColorSpace = null; + public ColorSpace outColorSpace = null; + public Options(){} + public String outMimeType = null; + public boolean inDither = false; + public boolean inInputShareable = false; + public boolean inJustDecodeBounds = false; + public boolean inMutable = false; + public boolean inPreferQualityOverSpeed = false; + public boolean inPremultiplied = false; + public boolean inPurgeable = false; + public boolean inScaled = false; + public boolean mCancel = false; + public byte[] inTempStorage = null; + public int inDensity = 0; + public int inSampleSize = 0; + public int inScreenDensity = 0; + public int inTargetDensity = 0; + public int outHeight = 0; + public int outWidth = 0; + public void requestCancelDecode(){} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/BlendMode.java b/java/ql/test/stubs/android/android/graphics/BlendMode.java new file mode 100644 index 00000000000..32510e36bdd --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/BlendMode.java @@ -0,0 +1,10 @@ +// Generated automatically from android.graphics.BlendMode for testing purposes + +package android.graphics; + + +public enum BlendMode +{ + CLEAR, COLOR, COLOR_BURN, COLOR_DODGE, DARKEN, DIFFERENCE, DST, DST_ATOP, DST_IN, DST_OUT, DST_OVER, EXCLUSION, HARD_LIGHT, HUE, LIGHTEN, LUMINOSITY, MODULATE, MULTIPLY, OVERLAY, PLUS, SATURATION, SCREEN, SOFT_LIGHT, SRC, SRC_ATOP, SRC_IN, SRC_OUT, SRC_OVER, XOR; + private BlendMode() {} +} diff --git a/java/ql/test/stubs/android/android/graphics/Canvas.java b/java/ql/test/stubs/android/android/graphics/Canvas.java new file mode 100644 index 00000000000..26c4536a2aa --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Canvas.java @@ -0,0 +1,141 @@ +// Generated automatically from android.graphics.Canvas for testing purposes + +package android.graphics; + +import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.DrawFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Picture; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; +import android.graphics.RenderNode; +import android.graphics.text.MeasuredText; + +public class Canvas +{ + public Canvas(){} + public Canvas(Bitmap p0){} + public DrawFilter getDrawFilter(){ return null; } + public boolean clipOutPath(Path p0){ return false; } + public boolean clipOutRect(Rect p0){ return false; } + public boolean clipOutRect(RectF p0){ return false; } + public boolean clipOutRect(float p0, float p1, float p2, float p3){ return false; } + public boolean clipOutRect(int p0, int p1, int p2, int p3){ return false; } + public boolean clipPath(Path p0){ return false; } + public boolean clipPath(Path p0, Region.Op p1){ return false; } + public boolean clipRect(Rect p0){ return false; } + public boolean clipRect(Rect p0, Region.Op p1){ return false; } + public boolean clipRect(RectF p0){ return false; } + public boolean clipRect(RectF p0, Region.Op p1){ return false; } + public boolean clipRect(float p0, float p1, float p2, float p3){ return false; } + public boolean clipRect(float p0, float p1, float p2, float p3, Region.Op p4){ return false; } + public boolean clipRect(int p0, int p1, int p2, int p3){ return false; } + public boolean getClipBounds(Rect p0){ return false; } + public boolean isHardwareAccelerated(){ return false; } + public boolean isOpaque(){ return false; } + public boolean quickReject(Path p0){ return false; } + public boolean quickReject(Path p0, Canvas.EdgeType p1){ return false; } + public boolean quickReject(RectF p0){ return false; } + public boolean quickReject(RectF p0, Canvas.EdgeType p1){ return false; } + public boolean quickReject(float p0, float p1, float p2, float p3){ return false; } + public boolean quickReject(float p0, float p1, float p2, float p3, Canvas.EdgeType p4){ return false; } + public final Matrix getMatrix(){ return null; } + public final Rect getClipBounds(){ return null; } + public final void rotate(float p0, float p1, float p2){} + public final void scale(float p0, float p1, float p2, float p3){} + public int getDensity(){ return 0; } + public int getHeight(){ return 0; } + public int getMaximumBitmapHeight(){ return 0; } + public int getMaximumBitmapWidth(){ return 0; } + public int getSaveCount(){ return 0; } + public int getWidth(){ return 0; } + public int save(){ return 0; } + public int saveLayer(RectF p0, Paint p1){ return 0; } + public int saveLayer(RectF p0, Paint p1, int p2){ return 0; } + public int saveLayer(float p0, float p1, float p2, float p3, Paint p4){ return 0; } + public int saveLayer(float p0, float p1, float p2, float p3, Paint p4, int p5){ return 0; } + public int saveLayerAlpha(RectF p0, int p1){ return 0; } + public int saveLayerAlpha(RectF p0, int p1, int p2){ return 0; } + public int saveLayerAlpha(float p0, float p1, float p2, float p3, int p4){ return 0; } + public int saveLayerAlpha(float p0, float p1, float p2, float p3, int p4, int p5){ return 0; } + public static int ALL_SAVE_FLAG = 0; + public void concat(Matrix p0){} + public void disableZ(){} + public void drawARGB(int p0, int p1, int p2, int p3){} + public void drawArc(RectF p0, float p1, float p2, boolean p3, Paint p4){} + public void drawArc(float p0, float p1, float p2, float p3, float p4, float p5, boolean p6, Paint p7){} + public void drawBitmap(Bitmap p0, Matrix p1, Paint p2){} + public void drawBitmap(Bitmap p0, Rect p1, Rect p2, Paint p3){} + public void drawBitmap(Bitmap p0, Rect p1, RectF p2, Paint p3){} + public void drawBitmap(Bitmap p0, float p1, float p2, Paint p3){} + public void drawBitmap(int[] p0, int p1, int p2, float p3, float p4, int p5, int p6, boolean p7, Paint p8){} + public void drawBitmap(int[] p0, int p1, int p2, int p3, int p4, int p5, int p6, boolean p7, Paint p8){} + public void drawBitmapMesh(Bitmap p0, int p1, int p2, float[] p3, int p4, int[] p5, int p6, Paint p7){} + public void drawCircle(float p0, float p1, float p2, Paint p3){} + public void drawColor(int p0){} + public void drawColor(int p0, BlendMode p1){} + public void drawColor(int p0, PorterDuff.Mode p1){} + public void drawColor(long p0){} + public void drawColor(long p0, BlendMode p1){} + public void drawDoubleRoundRect(RectF p0, float p1, float p2, RectF p3, float p4, float p5, Paint p6){} + public void drawDoubleRoundRect(RectF p0, float[] p1, RectF p2, float[] p3, Paint p4){} + public void drawLine(float p0, float p1, float p2, float p3, Paint p4){} + public void drawLines(float[] p0, Paint p1){} + public void drawLines(float[] p0, int p1, int p2, Paint p3){} + public void drawOval(RectF p0, Paint p1){} + public void drawOval(float p0, float p1, float p2, float p3, Paint p4){} + public void drawPaint(Paint p0){} + public void drawPath(Path p0, Paint p1){} + public void drawPicture(Picture p0){} + public void drawPicture(Picture p0, Rect p1){} + public void drawPicture(Picture p0, RectF p1){} + public void drawPoint(float p0, float p1, Paint p2){} + public void drawPoints(float[] p0, Paint p1){} + public void drawPoints(float[] p0, int p1, int p2, Paint p3){} + public void drawPosText(String p0, float[] p1, Paint p2){} + public void drawPosText(char[] p0, int p1, int p2, float[] p3, Paint p4){} + public void drawRGB(int p0, int p1, int p2){} + public void drawRect(Rect p0, Paint p1){} + public void drawRect(RectF p0, Paint p1){} + public void drawRect(float p0, float p1, float p2, float p3, Paint p4){} + public void drawRenderNode(RenderNode p0){} + public void drawRoundRect(RectF p0, float p1, float p2, Paint p3){} + public void drawRoundRect(float p0, float p1, float p2, float p3, float p4, float p5, Paint p6){} + public void drawText(CharSequence p0, int p1, int p2, float p3, float p4, Paint p5){} + public void drawText(String p0, float p1, float p2, Paint p3){} + public void drawText(String p0, int p1, int p2, float p3, float p4, Paint p5){} + public void drawText(char[] p0, int p1, int p2, float p3, float p4, Paint p5){} + public void drawTextOnPath(String p0, Path p1, float p2, float p3, Paint p4){} + public void drawTextOnPath(char[] p0, int p1, int p2, Path p3, float p4, float p5, Paint p6){} + public void drawTextRun(CharSequence p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public void drawTextRun(MeasuredText p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public void drawTextRun(char[] p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public void drawVertices(Canvas.VertexMode p0, int p1, float[] p2, int p3, float[] p4, int p5, int[] p6, int p7, short[] p8, int p9, int p10, Paint p11){} + public void enableZ(){} + public void getMatrix(Matrix p0){} + public void restore(){} + public void restoreToCount(int p0){} + public void rotate(float p0){} + public void scale(float p0, float p1){} + public void setBitmap(Bitmap p0){} + public void setDensity(int p0){} + public void setDrawFilter(DrawFilter p0){} + public void setMatrix(Matrix p0){} + public void skew(float p0, float p1){} + public void translate(float p0, float p1){} + static public enum EdgeType + { + AA, BW; + private EdgeType() {} + } + static public enum VertexMode + { + TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP; + private VertexMode() {} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/Color.java b/java/ql/test/stubs/android/android/graphics/Color.java new file mode 100644 index 00000000000..45f1e68548c --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Color.java @@ -0,0 +1,80 @@ +// Generated automatically from android.graphics.Color for testing purposes + +package android.graphics; + +import android.graphics.ColorSpace; + +public class Color +{ + public Color convert(ColorSpace p0){ return null; } + public Color(){} + public ColorSpace getColorSpace(){ return null; } + public ColorSpace.Model getModel(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isSrgb(){ return false; } + public boolean isWideGamut(){ return false; } + public float alpha(){ return 0; } + public float blue(){ return 0; } + public float getComponent(int p0){ return 0; } + public float green(){ return 0; } + public float luminance(){ return 0; } + public float red(){ return 0; } + public float[] getComponents(){ return null; } + public float[] getComponents(float[] p0){ return null; } + public int getComponentCount(){ return 0; } + public int hashCode(){ return 0; } + public int toArgb(){ return 0; } + public long pack(){ return 0; } + public static Color valueOf(float p0, float p1, float p2){ return null; } + public static Color valueOf(float p0, float p1, float p2, float p3){ return null; } + public static Color valueOf(float p0, float p1, float p2, float p3, ColorSpace p4){ return null; } + public static Color valueOf(float[] p0, ColorSpace p1){ return null; } + public static Color valueOf(int p0){ return null; } + public static Color valueOf(long p0){ return null; } + public static ColorSpace colorSpace(long p0){ return null; } + public static boolean isInColorSpace(long p0, ColorSpace p1){ return false; } + public static boolean isSrgb(long p0){ return false; } + public static boolean isWideGamut(long p0){ return false; } + public static float alpha(long p0){ return 0; } + public static float blue(long p0){ return 0; } + public static float green(long p0){ return 0; } + public static float luminance(int p0){ return 0; } + public static float luminance(long p0){ return 0; } + public static float red(long p0){ return 0; } + public static int BLACK = 0; + public static int BLUE = 0; + public static int CYAN = 0; + public static int DKGRAY = 0; + public static int GRAY = 0; + public static int GREEN = 0; + public static int HSVToColor(float[] p0){ return 0; } + public static int HSVToColor(int p0, float[] p1){ return 0; } + public static int LTGRAY = 0; + public static int MAGENTA = 0; + public static int RED = 0; + public static int TRANSPARENT = 0; + public static int WHITE = 0; + public static int YELLOW = 0; + public static int alpha(int p0){ return 0; } + public static int argb(float p0, float p1, float p2, float p3){ return 0; } + public static int argb(int p0, int p1, int p2, int p3){ return 0; } + public static int blue(int p0){ return 0; } + public static int green(int p0){ return 0; } + public static int parseColor(String p0){ return 0; } + public static int red(int p0){ return 0; } + public static int rgb(float p0, float p1, float p2){ return 0; } + public static int rgb(int p0, int p1, int p2){ return 0; } + public static int toArgb(long p0){ return 0; } + public static long convert(float p0, float p1, float p2, float p3, ColorSpace p4, ColorSpace p5){ return 0; } + public static long convert(float p0, float p1, float p2, float p3, ColorSpace.Connector p4){ return 0; } + public static long convert(int p0, ColorSpace p1){ return 0; } + public static long convert(long p0, ColorSpace p1){ return 0; } + public static long convert(long p0, ColorSpace.Connector p1){ return 0; } + public static long pack(float p0, float p1, float p2){ return 0; } + public static long pack(float p0, float p1, float p2, float p3){ return 0; } + public static long pack(float p0, float p1, float p2, float p3, ColorSpace p4){ return 0; } + public static long pack(int p0){ return 0; } + public static void RGBToHSV(int p0, int p1, int p2, float[] p3){} + public static void colorToHSV(int p0, float[] p1){} +} diff --git a/java/ql/test/stubs/android/android/graphics/ColorFilter.java b/java/ql/test/stubs/android/android/graphics/ColorFilter.java new file mode 100644 index 00000000000..06a565743de --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/ColorFilter.java @@ -0,0 +1,9 @@ +// Generated automatically from android.graphics.ColorFilter for testing purposes + +package android.graphics; + + +public class ColorFilter +{ + public ColorFilter(){} +} diff --git a/java/ql/test/stubs/android/android/graphics/ColorSpace.java b/java/ql/test/stubs/android/android/graphics/ColorSpace.java new file mode 100644 index 00000000000..80c1ebcbbe4 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/ColorSpace.java @@ -0,0 +1,120 @@ +// Generated automatically from android.graphics.ColorSpace for testing purposes + +package android.graphics; + +import java.util.function.DoubleUnaryOperator; + +abstract public class ColorSpace +{ + public ColorSpace.Model getModel(){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public abstract boolean isWideGamut(); + public abstract float getMaxValue(int p0); + public abstract float getMinValue(int p0); + public abstract float[] fromXyz(float[] p0); + public abstract float[] toXyz(float[] p0); + public boolean equals(Object p0){ return false; } + public boolean isSrgb(){ return false; } + public float[] fromXyz(float p0, float p1, float p2){ return null; } + public float[] toXyz(float p0, float p1, float p2){ return null; } + public int getComponentCount(){ return 0; } + public int getId(){ return 0; } + public int hashCode(){ return 0; } + public static ColorSpace adapt(ColorSpace p0, float[] p1){ return null; } + public static ColorSpace adapt(ColorSpace p0, float[] p1, ColorSpace.Adaptation p2){ return null; } + public static ColorSpace get(ColorSpace.Named p0){ return null; } + public static ColorSpace match(float[] p0, ColorSpace.Rgb.TransferParameters p1){ return null; } + public static ColorSpace.Connector connect(ColorSpace p0){ return null; } + public static ColorSpace.Connector connect(ColorSpace p0, ColorSpace p1){ return null; } + public static ColorSpace.Connector connect(ColorSpace p0, ColorSpace p1, ColorSpace.RenderIntent p2){ return null; } + public static ColorSpace.Connector connect(ColorSpace p0, ColorSpace.RenderIntent p1){ return null; } + public static float[] ILLUMINANT_A = null; + public static float[] ILLUMINANT_B = null; + public static float[] ILLUMINANT_C = null; + public static float[] ILLUMINANT_D50 = null; + public static float[] ILLUMINANT_D55 = null; + public static float[] ILLUMINANT_D60 = null; + public static float[] ILLUMINANT_D65 = null; + public static float[] ILLUMINANT_D75 = null; + public static float[] ILLUMINANT_E = null; + public static int MAX_ID = 0; + public static int MIN_ID = 0; + static public class Connector + { + public ColorSpace getDestination(){ return null; } + public ColorSpace getSource(){ return null; } + public ColorSpace.RenderIntent getRenderIntent(){ return null; } + public float[] transform(float p0, float p1, float p2){ return null; } + public float[] transform(float[] p0){ return null; } + } + static public class Rgb extends ColorSpace + { + protected Rgb() {} + public ColorSpace.Rgb.TransferParameters getTransferParameters(){ return null; } + public DoubleUnaryOperator getEotf(){ return null; } + public DoubleUnaryOperator getOetf(){ return null; } + public Rgb(String p0, float[] p1, ColorSpace.Rgb.TransferParameters p2){} + public Rgb(String p0, float[] p1, DoubleUnaryOperator p2, DoubleUnaryOperator p3){} + public Rgb(String p0, float[] p1, double p2){} + public Rgb(String p0, float[] p1, float[] p2, ColorSpace.Rgb.TransferParameters p3){} + public Rgb(String p0, float[] p1, float[] p2, DoubleUnaryOperator p3, DoubleUnaryOperator p4, float p5, float p6){} + public Rgb(String p0, float[] p1, float[] p2, double p3){} + public boolean equals(Object p0){ return false; } + public boolean isSrgb(){ return false; } + public boolean isWideGamut(){ return false; } + public float getMaxValue(int p0){ return 0; } + public float getMinValue(int p0){ return 0; } + public float[] fromLinear(float p0, float p1, float p2){ return null; } + public float[] fromLinear(float[] p0){ return null; } + public float[] fromXyz(float[] p0){ return null; } + public float[] getInverseTransform(){ return null; } + public float[] getInverseTransform(float[] p0){ return null; } + public float[] getPrimaries(){ return null; } + public float[] getPrimaries(float[] p0){ return null; } + public float[] getTransform(){ return null; } + public float[] getTransform(float[] p0){ return null; } + public float[] getWhitePoint(){ return null; } + public float[] getWhitePoint(float[] p0){ return null; } + public float[] toLinear(float p0, float p1, float p2){ return null; } + public float[] toLinear(float[] p0){ return null; } + public float[] toXyz(float[] p0){ return null; } + public int hashCode(){ return 0; } + static public class TransferParameters + { + protected TransferParameters() {} + public TransferParameters(double p0, double p1, double p2, double p3, double p4){} + public TransferParameters(double p0, double p1, double p2, double p3, double p4, double p5, double p6){} + public boolean equals(Object p0){ return false; } + public final double a = 0; + public final double b = 0; + public final double c = 0; + public final double d = 0; + public final double e = 0; + public final double f = 0; + public final double g = 0; + public int hashCode(){ return 0; } + } + } + static public enum Adaptation + { + BRADFORD, CIECAT02, VON_KRIES; + private Adaptation() {} + } + static public enum Model + { + CMYK, LAB, RGB, XYZ; + private Model() {} + public int getComponentCount(){ return 0; } + } + static public enum Named + { + ACES, ACESCG, ADOBE_RGB, BT2020, BT709, CIE_LAB, CIE_XYZ, DCI_P3, DISPLAY_P3, EXTENDED_SRGB, LINEAR_EXTENDED_SRGB, LINEAR_SRGB, NTSC_1953, PRO_PHOTO_RGB, SMPTE_C, SRGB; + private Named() {} + } + static public enum RenderIntent + { + ABSOLUTE, PERCEPTUAL, RELATIVE, SATURATION; + private RenderIntent() {} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/DrawFilter.java b/java/ql/test/stubs/android/android/graphics/DrawFilter.java new file mode 100644 index 00000000000..ed760270a81 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/DrawFilter.java @@ -0,0 +1,10 @@ +// Generated automatically from android.graphics.DrawFilter for testing purposes + +package android.graphics; + + +public class DrawFilter +{ + protected void finalize(){} + public DrawFilter(){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Insets.java b/java/ql/test/stubs/android/android/graphics/Insets.java new file mode 100644 index 00000000000..3e61e03cd68 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Insets.java @@ -0,0 +1,29 @@ +// Generated automatically from android.graphics.Insets for testing purposes + +package android.graphics; + +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; + +public class Insets implements Parcelable +{ + protected Insets() {} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final int bottom = 0; + public final int left = 0; + public final int right = 0; + public final int top = 0; + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Insets NONE = null; + public static Insets add(Insets p0, Insets p1){ return null; } + public static Insets max(Insets p0, Insets p1){ return null; } + public static Insets min(Insets p0, Insets p1){ return null; } + public static Insets of(Rect p0){ return null; } + public static Insets of(int p0, int p1, int p2, int p3){ return null; } + public static Insets subtract(Insets p0, Insets p1){ return null; } + public static Parcelable.Creator<Insets> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/graphics/MaskFilter.java b/java/ql/test/stubs/android/android/graphics/MaskFilter.java new file mode 100644 index 00000000000..0355b5c1206 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/MaskFilter.java @@ -0,0 +1,10 @@ +// Generated automatically from android.graphics.MaskFilter for testing purposes + +package android.graphics; + + +public class MaskFilter +{ + protected void finalize(){} + public MaskFilter(){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Matrix.java b/java/ql/test/stubs/android/android/graphics/Matrix.java new file mode 100644 index 00000000000..fc003bac004 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Matrix.java @@ -0,0 +1,74 @@ +// Generated automatically from android.graphics.Matrix for testing purposes + +package android.graphics; + +import android.graphics.RectF; + +public class Matrix +{ + public Matrix(){} + public Matrix(Matrix p0){} + public String toShortString(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean invert(Matrix p0){ return false; } + public boolean isAffine(){ return false; } + public boolean isIdentity(){ return false; } + public boolean mapRect(RectF p0){ return false; } + public boolean mapRect(RectF p0, RectF p1){ return false; } + public boolean postConcat(Matrix p0){ return false; } + public boolean postRotate(float p0){ return false; } + public boolean postRotate(float p0, float p1, float p2){ return false; } + public boolean postScale(float p0, float p1){ return false; } + public boolean postScale(float p0, float p1, float p2, float p3){ return false; } + public boolean postSkew(float p0, float p1){ return false; } + public boolean postSkew(float p0, float p1, float p2, float p3){ return false; } + public boolean postTranslate(float p0, float p1){ return false; } + public boolean preConcat(Matrix p0){ return false; } + public boolean preRotate(float p0){ return false; } + public boolean preRotate(float p0, float p1, float p2){ return false; } + public boolean preScale(float p0, float p1){ return false; } + public boolean preScale(float p0, float p1, float p2, float p3){ return false; } + public boolean preSkew(float p0, float p1){ return false; } + public boolean preSkew(float p0, float p1, float p2, float p3){ return false; } + public boolean preTranslate(float p0, float p1){ return false; } + public boolean rectStaysRect(){ return false; } + public boolean setConcat(Matrix p0, Matrix p1){ return false; } + public boolean setPolyToPoly(float[] p0, int p1, float[] p2, int p3, int p4){ return false; } + public boolean setRectToRect(RectF p0, RectF p1, Matrix.ScaleToFit p2){ return false; } + public float mapRadius(float p0){ return 0; } + public int hashCode(){ return 0; } + public static int MPERSP_0 = 0; + public static int MPERSP_1 = 0; + public static int MPERSP_2 = 0; + public static int MSCALE_X = 0; + public static int MSCALE_Y = 0; + public static int MSKEW_X = 0; + public static int MSKEW_Y = 0; + public static int MTRANS_X = 0; + public static int MTRANS_Y = 0; + public void getValues(float[] p0){} + public void mapPoints(float[] p0){} + public void mapPoints(float[] p0, float[] p1){} + public void mapPoints(float[] p0, int p1, float[] p2, int p3, int p4){} + public void mapVectors(float[] p0){} + public void mapVectors(float[] p0, float[] p1){} + public void mapVectors(float[] p0, int p1, float[] p2, int p3, int p4){} + public void reset(){} + public void set(Matrix p0){} + public void setRotate(float p0){} + public void setRotate(float p0, float p1, float p2){} + public void setScale(float p0, float p1){} + public void setScale(float p0, float p1, float p2, float p3){} + public void setSinCos(float p0, float p1){} + public void setSinCos(float p0, float p1, float p2, float p3){} + public void setSkew(float p0, float p1){} + public void setSkew(float p0, float p1, float p2, float p3){} + public void setTranslate(float p0, float p1){} + public void setValues(float[] p0){} + static public enum ScaleToFit + { + CENTER, END, FILL, START; + private ScaleToFit() {} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/Movie.java b/java/ql/test/stubs/android/android/graphics/Movie.java new file mode 100644 index 00000000000..dd531ba7e04 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Movie.java @@ -0,0 +1,23 @@ +// Generated automatically from android.graphics.Movie for testing purposes + +package android.graphics; + +import android.graphics.Canvas; +import android.graphics.Paint; +import java.io.InputStream; + +public class Movie +{ + protected Movie() {} + protected void finalize(){} + public boolean isOpaque(){ return false; } + public boolean setTime(int p0){ return false; } + public int duration(){ return 0; } + public int height(){ return 0; } + public int width(){ return 0; } + public static Movie decodeByteArray(byte[] p0, int p1, int p2){ return null; } + public static Movie decodeFile(String p0){ return null; } + public static Movie decodeStream(InputStream p0){ return null; } + public void draw(Canvas p0, float p1, float p2){} + public void draw(Canvas p0, float p1, float p2, Paint p3){} +} diff --git a/java/ql/test/stubs/android/android/graphics/NinePatch.java b/java/ql/test/stubs/android/android/graphics/NinePatch.java new file mode 100644 index 00000000000..0fa7bc2eb69 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/NinePatch.java @@ -0,0 +1,31 @@ +// Generated automatically from android.graphics.NinePatch for testing purposes + +package android.graphics; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; + +public class NinePatch +{ + protected NinePatch() {} + protected void finalize(){} + public Bitmap getBitmap(){ return null; } + public NinePatch(Bitmap p0, byte[] p1){} + public NinePatch(Bitmap p0, byte[] p1, String p2){} + public Paint getPaint(){ return null; } + public String getName(){ return null; } + public final Region getTransparentRegion(Rect p0){ return null; } + public final boolean hasAlpha(){ return false; } + public int getDensity(){ return 0; } + public int getHeight(){ return 0; } + public int getWidth(){ return 0; } + public static boolean isNinePatchChunk(byte[] p0){ return false; } + public void draw(Canvas p0, Rect p1){} + public void draw(Canvas p0, Rect p1, Paint p2){} + public void draw(Canvas p0, RectF p1){} + public void setPaint(Paint p0){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Outline.java b/java/ql/test/stubs/android/android/graphics/Outline.java new file mode 100644 index 00000000000..4367be91cdd --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Outline.java @@ -0,0 +1,29 @@ +// Generated automatically from android.graphics.Outline for testing purposes + +package android.graphics; + +import android.graphics.Path; +import android.graphics.Rect; + +public class Outline +{ + public Outline(){} + public Outline(Outline p0){} + public boolean canClip(){ return false; } + public boolean getRect(Rect p0){ return false; } + public boolean isEmpty(){ return false; } + public float getAlpha(){ return 0; } + public float getRadius(){ return 0; } + public void offset(int p0, int p1){} + public void set(Outline p0){} + public void setAlpha(float p0){} + public void setConvexPath(Path p0){} + public void setEmpty(){} + public void setOval(Rect p0){} + public void setOval(int p0, int p1, int p2, int p3){} + public void setPath(Path p0){} + public void setRect(Rect p0){} + public void setRect(int p0, int p1, int p2, int p3){} + public void setRoundRect(Rect p0, float p1){} + public void setRoundRect(int p0, int p1, int p2, int p3, float p4){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Paint.java b/java/ql/test/stubs/android/android/graphics/Paint.java new file mode 100644 index 00000000000..810aecc3617 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Paint.java @@ -0,0 +1,212 @@ +// Generated automatically from android.graphics.Paint for testing purposes + +package android.graphics; + +import android.graphics.BlendMode; +import android.graphics.ColorFilter; +import android.graphics.MaskFilter; +import android.graphics.Path; +import android.graphics.PathEffect; +import android.graphics.Rect; +import android.graphics.Shader; +import android.graphics.Typeface; +import android.graphics.Xfermode; +import android.os.LocaleList; +import java.util.Locale; + +public class Paint +{ + public BlendMode getBlendMode(){ return null; } + public ColorFilter getColorFilter(){ return null; } + public ColorFilter setColorFilter(ColorFilter p0){ return null; } + public Locale getTextLocale(){ return null; } + public LocaleList getTextLocales(){ return null; } + public MaskFilter getMaskFilter(){ return null; } + public MaskFilter setMaskFilter(MaskFilter p0){ return null; } + public Paint(){} + public Paint(Paint p0){} + public Paint(int p0){} + public Paint.Align getTextAlign(){ return null; } + public Paint.Cap getStrokeCap(){ return null; } + public Paint.FontMetrics getFontMetrics(){ return null; } + public Paint.FontMetricsInt getFontMetricsInt(){ return null; } + public Paint.Join getStrokeJoin(){ return null; } + public Paint.Style getStyle(){ return null; } + public PathEffect getPathEffect(){ return null; } + public PathEffect setPathEffect(PathEffect p0){ return null; } + public Shader getShader(){ return null; } + public Shader setShader(Shader p0){ return null; } + public String getFontFeatureSettings(){ return null; } + public String getFontVariationSettings(){ return null; } + public Typeface getTypeface(){ return null; } + public Typeface setTypeface(Typeface p0){ return null; } + public Xfermode getXfermode(){ return null; } + public Xfermode setXfermode(Xfermode p0){ return null; } + public boolean equalsForTextMeasurement(Paint p0){ return false; } + public boolean getFillPath(Path p0, Path p1){ return false; } + public boolean hasGlyph(String p0){ return false; } + public boolean isElegantTextHeight(){ return false; } + public boolean setFontVariationSettings(String p0){ return false; } + public final boolean isAntiAlias(){ return false; } + public final boolean isDither(){ return false; } + public final boolean isFakeBoldText(){ return false; } + public final boolean isFilterBitmap(){ return false; } + public final boolean isLinearText(){ return false; } + public final boolean isStrikeThruText(){ return false; } + public final boolean isSubpixelText(){ return false; } + public final boolean isUnderlineText(){ return false; } + public float ascent(){ return 0; } + public float descent(){ return 0; } + public float getFontMetrics(Paint.FontMetrics p0){ return 0; } + public float getFontSpacing(){ return 0; } + public float getLetterSpacing(){ return 0; } + public float getRunAdvance(CharSequence p0, int p1, int p2, int p3, int p4, boolean p5, int p6){ return 0; } + public float getRunAdvance(char[] p0, int p1, int p2, int p3, int p4, boolean p5, int p6){ return 0; } + public float getShadowLayerDx(){ return 0; } + public float getShadowLayerDy(){ return 0; } + public float getShadowLayerRadius(){ return 0; } + public float getStrikeThruPosition(){ return 0; } + public float getStrikeThruThickness(){ return 0; } + public float getStrokeMiter(){ return 0; } + public float getStrokeWidth(){ return 0; } + public float getTextRunAdvances(char[] p0, int p1, int p2, int p3, int p4, boolean p5, float[] p6, int p7){ return 0; } + public float getTextScaleX(){ return 0; } + public float getTextSize(){ return 0; } + public float getTextSkewX(){ return 0; } + public float getUnderlinePosition(){ return 0; } + public float getUnderlineThickness(){ return 0; } + public float getWordSpacing(){ return 0; } + public float measureText(CharSequence p0, int p1, int p2){ return 0; } + public float measureText(String p0){ return 0; } + public float measureText(String p0, int p1, int p2){ return 0; } + public float measureText(char[] p0, int p1, int p2){ return 0; } + public int breakText(CharSequence p0, int p1, int p2, boolean p3, float p4, float[] p5){ return 0; } + public int breakText(String p0, boolean p1, float p2, float[] p3){ return 0; } + public int breakText(char[] p0, int p1, int p2, float p3, float[] p4){ return 0; } + public int getAlpha(){ return 0; } + public int getColor(){ return 0; } + public int getEndHyphenEdit(){ return 0; } + public int getFlags(){ return 0; } + public int getFontMetricsInt(Paint.FontMetricsInt p0){ return 0; } + public int getHinting(){ return 0; } + public int getOffsetForAdvance(CharSequence p0, int p1, int p2, int p3, int p4, boolean p5, float p6){ return 0; } + public int getOffsetForAdvance(char[] p0, int p1, int p2, int p3, int p4, boolean p5, float p6){ return 0; } + public int getShadowLayerColor(){ return 0; } + public int getStartHyphenEdit(){ return 0; } + public int getTextRunCursor(CharSequence p0, int p1, int p2, boolean p3, int p4, int p5){ return 0; } + public int getTextRunCursor(char[] p0, int p1, int p2, boolean p3, int p4, int p5){ return 0; } + public int getTextWidths(CharSequence p0, int p1, int p2, float[] p3){ return 0; } + public int getTextWidths(String p0, float[] p1){ return 0; } + public int getTextWidths(String p0, int p1, int p2, float[] p3){ return 0; } + public int getTextWidths(char[] p0, int p1, int p2, float[] p3){ return 0; } + public long getColorLong(){ return 0; } + public long getShadowLayerColorLong(){ return 0; } + public static int ANTI_ALIAS_FLAG = 0; + public static int CURSOR_AFTER = 0; + public static int CURSOR_AT = 0; + public static int CURSOR_AT_OR_AFTER = 0; + public static int CURSOR_AT_OR_BEFORE = 0; + public static int CURSOR_BEFORE = 0; + public static int DEV_KERN_TEXT_FLAG = 0; + public static int DITHER_FLAG = 0; + public static int EMBEDDED_BITMAP_TEXT_FLAG = 0; + public static int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 0; + public static int END_HYPHEN_EDIT_INSERT_HYPHEN = 0; + public static int END_HYPHEN_EDIT_INSERT_MAQAF = 0; + public static int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 0; + public static int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 0; + public static int END_HYPHEN_EDIT_NO_EDIT = 0; + public static int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 0; + public static int FAKE_BOLD_TEXT_FLAG = 0; + public static int FILTER_BITMAP_FLAG = 0; + public static int HINTING_OFF = 0; + public static int HINTING_ON = 0; + public static int LINEAR_TEXT_FLAG = 0; + public static int START_HYPHEN_EDIT_INSERT_HYPHEN = 0; + public static int START_HYPHEN_EDIT_INSERT_ZWJ = 0; + public static int START_HYPHEN_EDIT_NO_EDIT = 0; + public static int STRIKE_THRU_TEXT_FLAG = 0; + public static int SUBPIXEL_TEXT_FLAG = 0; + public static int UNDERLINE_TEXT_FLAG = 0; + public void clearShadowLayer(){} + public void getTextBounds(CharSequence p0, int p1, int p2, Rect p3){} + public void getTextBounds(String p0, int p1, int p2, Rect p3){} + public void getTextBounds(char[] p0, int p1, int p2, Rect p3){} + public void getTextPath(String p0, int p1, int p2, float p3, float p4, Path p5){} + public void getTextPath(char[] p0, int p1, int p2, float p3, float p4, Path p5){} + public void reset(){} + public void set(Paint p0){} + public void setARGB(int p0, int p1, int p2, int p3){} + public void setAlpha(int p0){} + public void setAntiAlias(boolean p0){} + public void setBlendMode(BlendMode p0){} + public void setColor(int p0){} + public void setColor(long p0){} + public void setDither(boolean p0){} + public void setElegantTextHeight(boolean p0){} + public void setEndHyphenEdit(int p0){} + public void setFakeBoldText(boolean p0){} + public void setFilterBitmap(boolean p0){} + public void setFlags(int p0){} + public void setFontFeatureSettings(String p0){} + public void setHinting(int p0){} + public void setLetterSpacing(float p0){} + public void setLinearText(boolean p0){} + public void setShadowLayer(float p0, float p1, float p2, int p3){} + public void setShadowLayer(float p0, float p1, float p2, long p3){} + public void setStartHyphenEdit(int p0){} + public void setStrikeThruText(boolean p0){} + public void setStrokeCap(Paint.Cap p0){} + public void setStrokeJoin(Paint.Join p0){} + public void setStrokeMiter(float p0){} + public void setStrokeWidth(float p0){} + public void setStyle(Paint.Style p0){} + public void setSubpixelText(boolean p0){} + public void setTextAlign(Paint.Align p0){} + public void setTextLocale(Locale p0){} + public void setTextLocales(LocaleList p0){} + public void setTextScaleX(float p0){} + public void setTextSize(float p0){} + public void setTextSkewX(float p0){} + public void setUnderlineText(boolean p0){} + public void setWordSpacing(float p0){} + static public class FontMetrics + { + public FontMetrics(){} + public float ascent = 0; + public float bottom = 0; + public float descent = 0; + public float leading = 0; + public float top = 0; + } + static public class FontMetricsInt + { + public FontMetricsInt(){} + public String toString(){ return null; } + public int ascent = 0; + public int bottom = 0; + public int descent = 0; + public int leading = 0; + public int top = 0; + } + static public enum Align + { + CENTER, LEFT, RIGHT; + private Align() {} + } + static public enum Cap + { + BUTT, ROUND, SQUARE; + private Cap() {} + } + static public enum Join + { + BEVEL, MITER, ROUND; + private Join() {} + } + static public enum Style + { + FILL, FILL_AND_STROKE, STROKE; + private Style() {} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/Path.java b/java/ql/test/stubs/android/android/graphics/Path.java new file mode 100644 index 00000000000..c7164e37b01 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Path.java @@ -0,0 +1,73 @@ +// Generated automatically from android.graphics.Path for testing purposes + +package android.graphics; + +import android.graphics.Matrix; +import android.graphics.RectF; + +public class Path +{ + public Path(){} + public Path(Path p0){} + public Path.FillType getFillType(){ return null; } + public boolean isConvex(){ return false; } + public boolean isEmpty(){ return false; } + public boolean isInverseFillType(){ return false; } + public boolean isRect(RectF p0){ return false; } + public boolean op(Path p0, Path p1, Path.Op p2){ return false; } + public boolean op(Path p0, Path.Op p1){ return false; } + public float[] approximate(float p0){ return null; } + public void addArc(RectF p0, float p1, float p2){} + public void addArc(float p0, float p1, float p2, float p3, float p4, float p5){} + public void addCircle(float p0, float p1, float p2, Path.Direction p3){} + public void addOval(RectF p0, Path.Direction p1){} + public void addOval(float p0, float p1, float p2, float p3, Path.Direction p4){} + public void addPath(Path p0){} + public void addPath(Path p0, Matrix p1){} + public void addPath(Path p0, float p1, float p2){} + public void addRect(RectF p0, Path.Direction p1){} + public void addRect(float p0, float p1, float p2, float p3, Path.Direction p4){} + public void addRoundRect(RectF p0, float p1, float p2, Path.Direction p3){} + public void addRoundRect(RectF p0, float[] p1, Path.Direction p2){} + public void addRoundRect(float p0, float p1, float p2, float p3, float p4, float p5, Path.Direction p6){} + public void addRoundRect(float p0, float p1, float p2, float p3, float[] p4, Path.Direction p5){} + public void arcTo(RectF p0, float p1, float p2){} + public void arcTo(RectF p0, float p1, float p2, boolean p3){} + public void arcTo(float p0, float p1, float p2, float p3, float p4, float p5, boolean p6){} + public void close(){} + public void computeBounds(RectF p0, boolean p1){} + public void cubicTo(float p0, float p1, float p2, float p3, float p4, float p5){} + public void incReserve(int p0){} + public void lineTo(float p0, float p1){} + public void moveTo(float p0, float p1){} + public void offset(float p0, float p1){} + public void offset(float p0, float p1, Path p2){} + public void quadTo(float p0, float p1, float p2, float p3){} + public void rCubicTo(float p0, float p1, float p2, float p3, float p4, float p5){} + public void rLineTo(float p0, float p1){} + public void rMoveTo(float p0, float p1){} + public void rQuadTo(float p0, float p1, float p2, float p3){} + public void reset(){} + public void rewind(){} + public void set(Path p0){} + public void setFillType(Path.FillType p0){} + public void setLastPoint(float p0, float p1){} + public void toggleInverseFillType(){} + public void transform(Matrix p0){} + public void transform(Matrix p0, Path p1){} + static public enum Direction + { + CCW, CW; + private Direction() {} + } + static public enum FillType + { + EVEN_ODD, INVERSE_EVEN_ODD, INVERSE_WINDING, WINDING; + private FillType() {} + } + static public enum Op + { + DIFFERENCE, INTERSECT, REVERSE_DIFFERENCE, UNION, XOR; + private Op() {} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/PathEffect.java b/java/ql/test/stubs/android/android/graphics/PathEffect.java new file mode 100644 index 00000000000..c9ca9aeae86 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/PathEffect.java @@ -0,0 +1,10 @@ +// Generated automatically from android.graphics.PathEffect for testing purposes + +package android.graphics; + + +public class PathEffect +{ + protected void finalize(){} + public PathEffect(){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Picture.java b/java/ql/test/stubs/android/android/graphics/Picture.java new file mode 100644 index 00000000000..328321a2139 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Picture.java @@ -0,0 +1,18 @@ +// Generated automatically from android.graphics.Picture for testing purposes + +package android.graphics; + +import android.graphics.Canvas; + +public class Picture +{ + protected void finalize(){} + public Canvas beginRecording(int p0, int p1){ return null; } + public Picture(){} + public Picture(Picture p0){} + public boolean requiresHardwareAcceleration(){ return false; } + public int getHeight(){ return 0; } + public int getWidth(){ return 0; } + public void draw(Canvas p0){} + public void endRecording(){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Point.java b/java/ql/test/stubs/android/android/graphics/Point.java new file mode 100644 index 00000000000..0e97248f44b --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Point.java @@ -0,0 +1,26 @@ +// Generated automatically from android.graphics.Point for testing purposes + +package android.graphics; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Point implements Parcelable +{ + public Point(){} + public Point(Point p0){} + public Point(int p0, int p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final boolean equals(int p0, int p1){ return false; } + public final void negate(){} + public final void offset(int p0, int p1){} + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int x = 0; + public int y = 0; + public static Parcelable.Creator<Point> CREATOR = null; + public void readFromParcel(Parcel p0){} + public void set(int p0, int p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/graphics/PorterDuff.java b/java/ql/test/stubs/android/android/graphics/PorterDuff.java new file mode 100644 index 00000000000..39a82e655d6 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/PorterDuff.java @@ -0,0 +1,14 @@ +// Generated automatically from android.graphics.PorterDuff for testing purposes + +package android.graphics; + + +public class PorterDuff +{ + public PorterDuff(){} + static public enum Mode + { + ADD, CLEAR, DARKEN, DST, DST_ATOP, DST_IN, DST_OUT, DST_OVER, LIGHTEN, MULTIPLY, OVERLAY, SCREEN, SRC, SRC_ATOP, SRC_IN, SRC_OUT, SRC_OVER, XOR; + private Mode() {} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/RecordingCanvas.java b/java/ql/test/stubs/android/android/graphics/RecordingCanvas.java new file mode 100644 index 00000000000..1d992a53ec0 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/RecordingCanvas.java @@ -0,0 +1,82 @@ +// Generated automatically from android.graphics.RecordingCanvas for testing purposes + +package android.graphics; + +import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.NinePatch; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Picture; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.RenderNode; +import android.graphics.text.MeasuredText; + +public class RecordingCanvas extends Canvas +{ + public boolean isHardwareAccelerated(){ return false; } + public boolean isOpaque(){ return false; } + public final void drawARGB(int p0, int p1, int p2, int p3){} + public final void drawArc(RectF p0, float p1, float p2, boolean p3, Paint p4){} + public final void drawArc(float p0, float p1, float p2, float p3, float p4, float p5, boolean p6, Paint p7){} + public final void drawBitmap(Bitmap p0, Matrix p1, Paint p2){} + public final void drawBitmap(Bitmap p0, Rect p1, Rect p2, Paint p3){} + public final void drawBitmap(Bitmap p0, Rect p1, RectF p2, Paint p3){} + public final void drawBitmap(Bitmap p0, float p1, float p2, Paint p3){} + public final void drawBitmap(int[] p0, int p1, int p2, float p3, float p4, int p5, int p6, boolean p7, Paint p8){} + public final void drawBitmap(int[] p0, int p1, int p2, int p3, int p4, int p5, int p6, boolean p7, Paint p8){} + public final void drawBitmapMesh(Bitmap p0, int p1, int p2, float[] p3, int p4, int[] p5, int p6, Paint p7){} + public final void drawCircle(float p0, float p1, float p2, Paint p3){} + public final void drawColor(int p0){} + public final void drawColor(int p0, BlendMode p1){} + public final void drawColor(int p0, PorterDuff.Mode p1){} + public final void drawColor(long p0, BlendMode p1){} + public final void drawDoubleRoundRect(RectF p0, float p1, float p2, RectF p3, float p4, float p5, Paint p6){} + public final void drawDoubleRoundRect(RectF p0, float[] p1, RectF p2, float[] p3, Paint p4){} + public final void drawLine(float p0, float p1, float p2, float p3, Paint p4){} + public final void drawLines(float[] p0, Paint p1){} + public final void drawLines(float[] p0, int p1, int p2, Paint p3){} + public final void drawOval(RectF p0, Paint p1){} + public final void drawOval(float p0, float p1, float p2, float p3, Paint p4){} + public final void drawPaint(Paint p0){} + public final void drawPatch(NinePatch p0, Rect p1, Paint p2){} + public final void drawPatch(NinePatch p0, RectF p1, Paint p2){} + public final void drawPath(Path p0, Paint p1){} + public final void drawPicture(Picture p0){} + public final void drawPicture(Picture p0, Rect p1){} + public final void drawPicture(Picture p0, RectF p1){} + public final void drawPoint(float p0, float p1, Paint p2){} + public final void drawPoints(float[] p0, Paint p1){} + public final void drawPoints(float[] p0, int p1, int p2, Paint p3){} + public final void drawPosText(String p0, float[] p1, Paint p2){} + public final void drawPosText(char[] p0, int p1, int p2, float[] p3, Paint p4){} + public final void drawRGB(int p0, int p1, int p2){} + public final void drawRect(Rect p0, Paint p1){} + public final void drawRect(RectF p0, Paint p1){} + public final void drawRect(float p0, float p1, float p2, float p3, Paint p4){} + public final void drawRoundRect(RectF p0, float p1, float p2, Paint p3){} + public final void drawRoundRect(float p0, float p1, float p2, float p3, float p4, float p5, Paint p6){} + public final void drawText(CharSequence p0, int p1, int p2, float p3, float p4, Paint p5){} + public final void drawText(String p0, float p1, float p2, Paint p3){} + public final void drawText(String p0, int p1, int p2, float p3, float p4, Paint p5){} + public final void drawText(char[] p0, int p1, int p2, float p3, float p4, Paint p5){} + public final void drawTextOnPath(String p0, Path p1, float p2, float p3, Paint p4){} + public final void drawTextOnPath(char[] p0, int p1, int p2, Path p3, float p4, float p5, Paint p6){} + public final void drawTextRun(CharSequence p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public final void drawTextRun(char[] p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public final void drawVertices(Canvas.VertexMode p0, int p1, float[] p2, int p3, float[] p4, int p5, int[] p6, int p7, short[] p8, int p9, int p10, Paint p11){} + public int getHeight(){ return 0; } + public int getMaximumBitmapHeight(){ return 0; } + public int getMaximumBitmapWidth(){ return 0; } + public int getWidth(){ return 0; } + public void disableZ(){} + public void drawRenderNode(RenderNode p0){} + public void drawTextRun(MeasuredText p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public void enableZ(){} + public void setBitmap(Bitmap p0){} + public void setDensity(int p0){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Rect.java b/java/ql/test/stubs/android/android/graphics/Rect.java new file mode 100644 index 00000000000..c29950cb31d --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Rect.java @@ -0,0 +1,52 @@ +// Generated automatically from android.graphics.Rect for testing purposes + +package android.graphics; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Rect implements Parcelable +{ + public Rect(){} + public Rect(Rect p0){} + public Rect(int p0, int p1, int p2, int p3){} + public String flattenToString(){ return null; } + public String toShortString(){ return null; } + public String toString(){ return null; } + public boolean contains(Rect p0){ return false; } + public boolean contains(int p0, int p1){ return false; } + public boolean contains(int p0, int p1, int p2, int p3){ return false; } + public boolean equals(Object p0){ return false; } + public boolean intersect(Rect p0){ return false; } + public boolean intersect(int p0, int p1, int p2, int p3){ return false; } + public boolean intersects(int p0, int p1, int p2, int p3){ return false; } + public boolean isEmpty(){ return false; } + public boolean setIntersect(Rect p0, Rect p1){ return false; } + public float exactCenterX(){ return 0; } + public float exactCenterY(){ return 0; } + public int bottom = 0; + public int centerX(){ return 0; } + public int centerY(){ return 0; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int height(){ return 0; } + public int left = 0; + public int right = 0; + public int top = 0; + public int width(){ return 0; } + public static Parcelable.Creator<Rect> CREATOR = null; + public static Rect unflattenFromString(String p0){ return null; } + public static boolean intersects(Rect p0, Rect p1){ return false; } + public void inset(int p0, int p1){} + public void offset(int p0, int p1){} + public void offsetTo(int p0, int p1){} + public void readFromParcel(Parcel p0){} + public void set(Rect p0){} + public void set(int p0, int p1, int p2, int p3){} + public void setEmpty(){} + public void sort(){} + public void union(Rect p0){} + public void union(int p0, int p1){} + public void union(int p0, int p1, int p2, int p3){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/graphics/RectF.java b/java/ql/test/stubs/android/android/graphics/RectF.java new file mode 100644 index 00000000000..59489dd3f17 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/RectF.java @@ -0,0 +1,53 @@ +// Generated automatically from android.graphics.RectF for testing purposes + +package android.graphics; + +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; + +public class RectF implements Parcelable +{ + public RectF(){} + public RectF(Rect p0){} + public RectF(RectF p0){} + public RectF(float p0, float p1, float p2, float p3){} + public String toShortString(){ return null; } + public String toString(){ return null; } + public boolean contains(RectF p0){ return false; } + public boolean contains(float p0, float p1){ return false; } + public boolean contains(float p0, float p1, float p2, float p3){ return false; } + public boolean equals(Object p0){ return false; } + public boolean intersect(RectF p0){ return false; } + public boolean intersect(float p0, float p1, float p2, float p3){ return false; } + public boolean intersects(float p0, float p1, float p2, float p3){ return false; } + public boolean setIntersect(RectF p0, RectF p1){ return false; } + public final boolean isEmpty(){ return false; } + public final float centerX(){ return 0; } + public final float centerY(){ return 0; } + public final float height(){ return 0; } + public final float width(){ return 0; } + public float bottom = 0; + public float left = 0; + public float right = 0; + public float top = 0; + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<RectF> CREATOR = null; + public static boolean intersects(RectF p0, RectF p1){ return false; } + public void inset(float p0, float p1){} + public void offset(float p0, float p1){} + public void offsetTo(float p0, float p1){} + public void readFromParcel(Parcel p0){} + public void round(Rect p0){} + public void roundOut(Rect p0){} + public void set(Rect p0){} + public void set(RectF p0){} + public void set(float p0, float p1, float p2, float p3){} + public void setEmpty(){} + public void sort(){} + public void union(RectF p0){} + public void union(float p0, float p1){} + public void union(float p0, float p1, float p2, float p3){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Region.java b/java/ql/test/stubs/android/android/graphics/Region.java new file mode 100644 index 00000000000..7fbd2b4dafc --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Region.java @@ -0,0 +1,53 @@ +// Generated automatically from android.graphics.Region for testing purposes + +package android.graphics; + +import android.graphics.Path; +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; + +public class Region implements Parcelable +{ + protected void finalize(){} + public Path getBoundaryPath(){ return null; } + public Rect getBounds(){ return null; } + public Region(){} + public Region(Rect p0){} + public Region(Region p0){} + public Region(int p0, int p1, int p2, int p3){} + public String toString(){ return null; } + public boolean contains(int p0, int p1){ return false; } + public boolean equals(Object p0){ return false; } + public boolean getBoundaryPath(Path p0){ return false; } + public boolean getBounds(Rect p0){ return false; } + public boolean isComplex(){ return false; } + public boolean isEmpty(){ return false; } + public boolean isRect(){ return false; } + public boolean op(Rect p0, Region p1, Region.Op p2){ return false; } + public boolean op(Rect p0, Region.Op p1){ return false; } + public boolean op(Region p0, Region p1, Region.Op p2){ return false; } + public boolean op(Region p0, Region.Op p1){ return false; } + public boolean op(int p0, int p1, int p2, int p3, Region.Op p4){ return false; } + public boolean quickContains(Rect p0){ return false; } + public boolean quickContains(int p0, int p1, int p2, int p3){ return false; } + public boolean quickReject(Rect p0){ return false; } + public boolean quickReject(Region p0){ return false; } + public boolean quickReject(int p0, int p1, int p2, int p3){ return false; } + public boolean set(Rect p0){ return false; } + public boolean set(Region p0){ return false; } + public boolean set(int p0, int p1, int p2, int p3){ return false; } + public boolean setPath(Path p0, Region p1){ return false; } + public final boolean union(Rect p0){ return false; } + public int describeContents(){ return 0; } + public static Parcelable.Creator<Region> CREATOR = null; + public void setEmpty(){} + public void translate(int p0, int p1){} + public void translate(int p0, int p1, Region p2){} + public void writeToParcel(Parcel p0, int p1){} + static public enum Op + { + DIFFERENCE, INTERSECT, REPLACE, REVERSE_DIFFERENCE, UNION, XOR; + private Op() {} + } +} diff --git a/java/ql/test/stubs/android/android/graphics/RenderNode.java b/java/ql/test/stubs/android/android/graphics/RenderNode.java new file mode 100644 index 00000000000..9384cd4cd4e --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/RenderNode.java @@ -0,0 +1,82 @@ +// Generated automatically from android.graphics.RenderNode for testing purposes + +package android.graphics; + +import android.graphics.Matrix; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.RecordingCanvas; +import android.graphics.Rect; + +public class RenderNode +{ + protected RenderNode() {} + public RecordingCanvas beginRecording(){ return null; } + public RecordingCanvas beginRecording(int p0, int p1){ return null; } + public RenderNode(String p0){} + public boolean getClipToBounds(){ return false; } + public boolean getClipToOutline(){ return false; } + public boolean getUseCompositingLayer(){ return false; } + public boolean hasDisplayList(){ return false; } + public boolean hasIdentityMatrix(){ return false; } + public boolean hasOverlappingRendering(){ return false; } + public boolean hasShadow(){ return false; } + public boolean isForceDarkAllowed(){ return false; } + public boolean isPivotExplicitlySet(){ return false; } + public boolean offsetLeftAndRight(int p0){ return false; } + public boolean offsetTopAndBottom(int p0){ return false; } + public boolean resetPivot(){ return false; } + public boolean setAlpha(float p0){ return false; } + public boolean setAmbientShadowColor(int p0){ return false; } + public boolean setCameraDistance(float p0){ return false; } + public boolean setClipRect(Rect p0){ return false; } + public boolean setClipToBounds(boolean p0){ return false; } + public boolean setClipToOutline(boolean p0){ return false; } + public boolean setElevation(float p0){ return false; } + public boolean setForceDarkAllowed(boolean p0){ return false; } + public boolean setHasOverlappingRendering(boolean p0){ return false; } + public boolean setOutline(Outline p0){ return false; } + public boolean setPivotX(float p0){ return false; } + public boolean setPivotY(float p0){ return false; } + public boolean setPosition(Rect p0){ return false; } + public boolean setPosition(int p0, int p1, int p2, int p3){ return false; } + public boolean setProjectBackwards(boolean p0){ return false; } + public boolean setProjectionReceiver(boolean p0){ return false; } + public boolean setRotationX(float p0){ return false; } + public boolean setRotationY(float p0){ return false; } + public boolean setRotationZ(float p0){ return false; } + public boolean setScaleX(float p0){ return false; } + public boolean setScaleY(float p0){ return false; } + public boolean setSpotShadowColor(int p0){ return false; } + public boolean setTranslationX(float p0){ return false; } + public boolean setTranslationY(float p0){ return false; } + public boolean setTranslationZ(float p0){ return false; } + public boolean setUseCompositingLayer(boolean p0, Paint p1){ return false; } + public float getAlpha(){ return 0; } + public float getCameraDistance(){ return 0; } + public float getElevation(){ return 0; } + public float getPivotX(){ return 0; } + public float getPivotY(){ return 0; } + public float getRotationX(){ return 0; } + public float getRotationY(){ return 0; } + public float getRotationZ(){ return 0; } + public float getScaleX(){ return 0; } + public float getScaleY(){ return 0; } + public float getTranslationX(){ return 0; } + public float getTranslationY(){ return 0; } + public float getTranslationZ(){ return 0; } + public int getAmbientShadowColor(){ return 0; } + public int getBottom(){ return 0; } + public int getHeight(){ return 0; } + public int getLeft(){ return 0; } + public int getRight(){ return 0; } + public int getSpotShadowColor(){ return 0; } + public int getTop(){ return 0; } + public int getWidth(){ return 0; } + public long computeApproximateMemoryUsage(){ return 0; } + public long getUniqueId(){ return 0; } + public void discardDisplayList(){} + public void endRecording(){} + public void getInverseMatrix(Matrix p0){} + public void getMatrix(Matrix p0){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Shader.java b/java/ql/test/stubs/android/android/graphics/Shader.java new file mode 100644 index 00000000000..3e845aa0c0a --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Shader.java @@ -0,0 +1,12 @@ +// Generated automatically from android.graphics.Shader for testing purposes + +package android.graphics; + +import android.graphics.Matrix; + +public class Shader +{ + public Shader(){} + public boolean getLocalMatrix(Matrix p0){ return false; } + public void setLocalMatrix(Matrix p0){} +} diff --git a/java/ql/test/stubs/android/android/graphics/Typeface.java b/java/ql/test/stubs/android/android/graphics/Typeface.java new file mode 100644 index 00000000000..a2ab630e8d0 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Typeface.java @@ -0,0 +1,33 @@ +// Generated automatically from android.graphics.Typeface for testing purposes + +package android.graphics; + +import android.content.res.AssetManager; +import java.io.File; + +public class Typeface +{ + protected Typeface() {} + public boolean equals(Object p0){ return false; } + public final boolean isBold(){ return false; } + public final boolean isItalic(){ return false; } + public int getStyle(){ return 0; } + public int getWeight(){ return 0; } + public int hashCode(){ return 0; } + public static Typeface DEFAULT = null; + public static Typeface DEFAULT_BOLD = null; + public static Typeface MONOSPACE = null; + public static Typeface SANS_SERIF = null; + public static Typeface SERIF = null; + public static Typeface create(String p0, int p1){ return null; } + public static Typeface create(Typeface p0, int p1){ return null; } + public static Typeface create(Typeface p0, int p1, boolean p2){ return null; } + public static Typeface createFromAsset(AssetManager p0, String p1){ return null; } + public static Typeface createFromFile(File p0){ return null; } + public static Typeface createFromFile(String p0){ return null; } + public static Typeface defaultFromStyle(int p0){ return null; } + public static int BOLD = 0; + public static int BOLD_ITALIC = 0; + public static int ITALIC = 0; + public static int NORMAL = 0; +} diff --git a/java/ql/test/stubs/android/android/graphics/Xfermode.java b/java/ql/test/stubs/android/android/graphics/Xfermode.java new file mode 100644 index 00000000000..7b6e5ade001 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/Xfermode.java @@ -0,0 +1,9 @@ +// Generated automatically from android.graphics.Xfermode for testing purposes + +package android.graphics; + + +public class Xfermode +{ + public Xfermode(){} +} diff --git a/java/ql/test/stubs/android/android/graphics/drawable/Drawable.java b/java/ql/test/stubs/android/android/graphics/drawable/Drawable.java new file mode 100644 index 00000000000..5bb5b00f898 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/drawable/Drawable.java @@ -0,0 +1,111 @@ +// Generated automatically from android.graphics.drawable.Drawable for testing purposes + +package android.graphics.drawable; + +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.graphics.BitmapFactory; +import android.graphics.BlendMode; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Insets; +import android.graphics.Outline; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.Region; +import android.util.AttributeSet; +import android.util.TypedValue; +import java.io.InputStream; +import org.xmlpull.v1.XmlPullParser; + +abstract public class Drawable +{ + abstract static public class ConstantState + { + public ConstantState(){} + public Drawable newDrawable(Resources p0){ return null; } + public Drawable newDrawable(Resources p0, Resources.Theme p1){ return null; } + public abstract Drawable newDrawable(); + public abstract int getChangingConfigurations(); + public boolean canApplyTheme(){ return false; } + } + protected boolean onLevelChange(int p0){ return false; } + protected boolean onStateChange(int[] p0){ return false; } + protected void onBoundsChange(Rect p0){} + public ColorFilter getColorFilter(){ return null; } + public Drawable getCurrent(){ return null; } + public Drawable mutate(){ return null; } + public Drawable(){} + public Drawable.Callback getCallback(){ return null; } + public Drawable.ConstantState getConstantState(){ return null; } + public Insets getOpticalInsets(){ return null; } + public Rect getDirtyBounds(){ return null; } + public Region getTransparentRegion(){ return null; } + public abstract int getOpacity(); + public abstract void draw(Canvas p0); + public abstract void setAlpha(int p0); + public abstract void setColorFilter(ColorFilter p0); + public boolean canApplyTheme(){ return false; } + public boolean getPadding(Rect p0){ return false; } + public boolean isAutoMirrored(){ return false; } + public boolean isFilterBitmap(){ return false; } + public boolean isProjected(){ return false; } + public boolean isStateful(){ return false; } + public boolean onLayoutDirectionChanged(int p0){ return false; } + public boolean setState(int[] p0){ return false; } + public boolean setVisible(boolean p0, boolean p1){ return false; } + public final Rect copyBounds(){ return null; } + public final Rect getBounds(){ return null; } + public final boolean isVisible(){ return false; } + public final boolean setLayoutDirection(int p0){ return false; } + public final boolean setLevel(int p0){ return false; } + public final int getLevel(){ return 0; } + public final void copyBounds(Rect p0){} + public final void setCallback(Drawable.Callback p0){} + public int getAlpha(){ return 0; } + public int getChangingConfigurations(){ return 0; } + public int getIntrinsicHeight(){ return 0; } + public int getIntrinsicWidth(){ return 0; } + public int getLayoutDirection(){ return 0; } + public int getMinimumHeight(){ return 0; } + public int getMinimumWidth(){ return 0; } + public int[] getState(){ return null; } + public static Drawable createFromPath(String p0){ return null; } + public static Drawable createFromResourceStream(Resources p0, TypedValue p1, InputStream p2, String p3){ return null; } + public static Drawable createFromResourceStream(Resources p0, TypedValue p1, InputStream p2, String p3, BitmapFactory.Options p4){ return null; } + public static Drawable createFromStream(InputStream p0, String p1){ return null; } + public static Drawable createFromXml(Resources p0, XmlPullParser p1){ return null; } + public static Drawable createFromXml(Resources p0, XmlPullParser p1, Resources.Theme p2){ return null; } + public static Drawable createFromXmlInner(Resources p0, XmlPullParser p1, AttributeSet p2){ return null; } + public static Drawable createFromXmlInner(Resources p0, XmlPullParser p1, AttributeSet p2, Resources.Theme p3){ return null; } + public static int resolveOpacity(int p0, int p1){ return 0; } + public void applyTheme(Resources.Theme p0){} + public void clearColorFilter(){} + public void getHotspotBounds(Rect p0){} + public void getOutline(Outline p0){} + public void inflate(Resources p0, XmlPullParser p1, AttributeSet p2){} + public void inflate(Resources p0, XmlPullParser p1, AttributeSet p2, Resources.Theme p3){} + public void invalidateSelf(){} + public void jumpToCurrentState(){} + public void scheduleSelf(Runnable p0, long p1){} + public void setAutoMirrored(boolean p0){} + public void setBounds(Rect p0){} + public void setBounds(int p0, int p1, int p2, int p3){} + public void setChangingConfigurations(int p0){} + public void setColorFilter(int p0, PorterDuff.Mode p1){} + public void setDither(boolean p0){} + public void setFilterBitmap(boolean p0){} + public void setHotspot(float p0, float p1){} + public void setHotspotBounds(int p0, int p1, int p2, int p3){} + public void setTint(int p0){} + public void setTintBlendMode(BlendMode p0){} + public void setTintList(ColorStateList p0){} + public void setTintMode(PorterDuff.Mode p0){} + public void unscheduleSelf(Runnable p0){} + static public interface Callback + { + void invalidateDrawable(Drawable p0); + void scheduleDrawable(Drawable p0, Runnable p1, long p2); + void unscheduleDrawable(Drawable p0, Runnable p1); + } +} diff --git a/java/ql/test/stubs/android/android/graphics/drawable/Icon.java b/java/ql/test/stubs/android/android/graphics/drawable/Icon.java new file mode 100644 index 00000000000..fcfeb2b7109 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/drawable/Icon.java @@ -0,0 +1,55 @@ +// Generated automatically from android.graphics.drawable.Icon for testing purposes + +package android.graphics.drawable; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; + +public class Icon implements Parcelable +{ + protected Icon() {} + public Drawable loadDrawable(Context p0){ return null; } + public Icon setTint(int p0){ return null; } + public Icon setTintBlendMode(BlendMode p0){ return null; } + public Icon setTintList(ColorStateList p0){ return null; } + public Icon setTintMode(PorterDuff.Mode p0){ return null; } + public String getResPackage(){ return null; } + public String toString(){ return null; } + public Uri getUri(){ return null; } + public int describeContents(){ return 0; } + public int getResId(){ return 0; } + public int getType(){ return 0; } + public static Icon createWithAdaptiveBitmap(Bitmap p0){ return null; } + public static Icon createWithAdaptiveBitmapContentUri(String p0){ return null; } + public static Icon createWithAdaptiveBitmapContentUri(Uri p0){ return null; } + public static Icon createWithBitmap(Bitmap p0){ return null; } + public static Icon createWithContentUri(String p0){ return null; } + public static Icon createWithContentUri(Uri p0){ return null; } + public static Icon createWithData(byte[] p0, int p1, int p2){ return null; } + public static Icon createWithFilePath(String p0){ return null; } + public static Icon createWithResource(Context p0, int p1){ return null; } + public static Icon createWithResource(String p0, int p1){ return null; } + public static Parcelable.Creator<Icon> CREATOR = null; + public static int TYPE_ADAPTIVE_BITMAP = 0; + public static int TYPE_BITMAP = 0; + public static int TYPE_DATA = 0; + public static int TYPE_RESOURCE = 0; + public static int TYPE_URI = 0; + public static int TYPE_URI_ADAPTIVE_BITMAP = 0; + public void loadDrawableAsync(Context p0, Icon.OnDrawableLoadedListener p1, Handler p2){} + public void loadDrawableAsync(Context p0, Message p1){} + public void writeToParcel(Parcel p0, int p1){} + static public interface OnDrawableLoadedListener + { + void onDrawableLoaded(Drawable p0); + } +} diff --git a/java/ql/test/stubs/android/android/graphics/text/MeasuredText.java b/java/ql/test/stubs/android/android/graphics/text/MeasuredText.java new file mode 100644 index 00000000000..c737bd5dfc1 --- /dev/null +++ b/java/ql/test/stubs/android/android/graphics/text/MeasuredText.java @@ -0,0 +1,13 @@ +// Generated automatically from android.graphics.text.MeasuredText for testing purposes + +package android.graphics.text; + +import android.graphics.Rect; + +public class MeasuredText +{ + protected MeasuredText() {} + public float getCharWidthAt(int p0){ return 0; } + public float getWidth(int p0, int p1){ return 0; } + public void getBounds(int p0, int p1, Rect p2){} +} diff --git a/java/ql/test/stubs/android/android/hardware/HardwareBuffer.java b/java/ql/test/stubs/android/android/hardware/HardwareBuffer.java new file mode 100644 index 00000000000..0f4e5888a21 --- /dev/null +++ b/java/ql/test/stubs/android/android/hardware/HardwareBuffer.java @@ -0,0 +1,50 @@ +// Generated automatically from android.hardware.HardwareBuffer for testing purposes + +package android.hardware; + +import android.os.Parcel; +import android.os.Parcelable; + +public class HardwareBuffer implements AutoCloseable, Parcelable +{ + protected HardwareBuffer() {} + protected void finalize(){} + public boolean isClosed(){ return false; } + public int describeContents(){ return 0; } + public int getFormat(){ return 0; } + public int getHeight(){ return 0; } + public int getLayers(){ return 0; } + public int getWidth(){ return 0; } + public long getUsage(){ return 0; } + public static HardwareBuffer create(int p0, int p1, int p2, int p3, long p4){ return null; } + public static Parcelable.Creator<HardwareBuffer> CREATOR = null; + public static boolean isSupported(int p0, int p1, int p2, int p3, long p4){ return false; } + public static int BLOB = 0; + public static int DS_24UI8 = 0; + public static int DS_FP32UI8 = 0; + public static int D_16 = 0; + public static int D_24 = 0; + public static int D_FP32 = 0; + public static int RGBA_1010102 = 0; + public static int RGBA_8888 = 0; + public static int RGBA_FP16 = 0; + public static int RGBX_8888 = 0; + public static int RGB_565 = 0; + public static int RGB_888 = 0; + public static int S_UI8 = 0; + public static int YCBCR_420_888 = 0; + public static long USAGE_CPU_READ_OFTEN = 0; + public static long USAGE_CPU_READ_RARELY = 0; + public static long USAGE_CPU_WRITE_OFTEN = 0; + public static long USAGE_CPU_WRITE_RARELY = 0; + public static long USAGE_GPU_COLOR_OUTPUT = 0; + public static long USAGE_GPU_CUBE_MAP = 0; + public static long USAGE_GPU_DATA_BUFFER = 0; + public static long USAGE_GPU_MIPMAP_COMPLETE = 0; + public static long USAGE_GPU_SAMPLED_IMAGE = 0; + public static long USAGE_PROTECTED_CONTENT = 0; + public static long USAGE_SENSOR_DIRECT_DATA = 0; + public static long USAGE_VIDEO_ENCODE = 0; + public void close(){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/icu/util/ULocale.java b/java/ql/test/stubs/android/android/icu/util/ULocale.java new file mode 100644 index 00000000000..1e1ea662c22 --- /dev/null +++ b/java/ql/test/stubs/android/android/icu/util/ULocale.java @@ -0,0 +1,138 @@ +// Generated automatically from android.icu.util.ULocale for testing purposes + +package android.icu.util; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; + +public class ULocale implements Comparable<ULocale>, Serializable +{ + protected ULocale() {} + public Iterator<String> getKeywords(){ return null; } + public Locale toLocale(){ return null; } + public Object clone(){ return null; } + public Set<Character> getExtensionKeys(){ return null; } + public Set<String> getUnicodeLocaleAttributes(){ return null; } + public Set<String> getUnicodeLocaleKeys(){ return null; } + public String getBaseName(){ return null; } + public String getCharacterOrientation(){ return null; } + public String getCountry(){ return null; } + public String getDisplayCountry(){ return null; } + public String getDisplayCountry(ULocale p0){ return null; } + public String getDisplayKeywordValue(String p0){ return null; } + public String getDisplayKeywordValue(String p0, ULocale p1){ return null; } + public String getDisplayLanguage(){ return null; } + public String getDisplayLanguage(ULocale p0){ return null; } + public String getDisplayLanguageWithDialect(){ return null; } + public String getDisplayLanguageWithDialect(ULocale p0){ return null; } + public String getDisplayName(){ return null; } + public String getDisplayName(ULocale p0){ return null; } + public String getDisplayNameWithDialect(){ return null; } + public String getDisplayNameWithDialect(ULocale p0){ return null; } + public String getDisplayScript(){ return null; } + public String getDisplayScript(ULocale p0){ return null; } + public String getDisplayVariant(){ return null; } + public String getDisplayVariant(ULocale p0){ return null; } + public String getExtension(char p0){ return null; } + public String getISO3Country(){ return null; } + public String getISO3Language(){ return null; } + public String getKeywordValue(String p0){ return null; } + public String getLanguage(){ return null; } + public String getLineOrientation(){ return null; } + public String getName(){ return null; } + public String getScript(){ return null; } + public String getUnicodeLocaleType(String p0){ return null; } + public String getVariant(){ return null; } + public String toLanguageTag(){ return null; } + public String toString(){ return null; } + public ULocale getFallback(){ return null; } + public ULocale setKeywordValue(String p0, String p1){ return null; } + public ULocale(String p0){} + public ULocale(String p0, String p1){} + public ULocale(String p0, String p1, String p2){} + public boolean equals(Object p0){ return false; } + public boolean isRightToLeft(){ return false; } + public int compareTo(ULocale p0){ return 0; } + public int hashCode(){ return 0; } + public static Iterator<String> getKeywords(String p0){ return null; } + public static String canonicalize(String p0){ return null; } + public static String getBaseName(String p0){ return null; } + public static String getCountry(String p0){ return null; } + public static String getDisplayCountry(String p0, String p1){ return null; } + public static String getDisplayCountry(String p0, ULocale p1){ return null; } + public static String getDisplayKeyword(String p0){ return null; } + public static String getDisplayKeyword(String p0, String p1){ return null; } + public static String getDisplayKeyword(String p0, ULocale p1){ return null; } + public static String getDisplayKeywordValue(String p0, String p1, String p2){ return null; } + public static String getDisplayKeywordValue(String p0, String p1, ULocale p2){ return null; } + public static String getDisplayLanguage(String p0, String p1){ return null; } + public static String getDisplayLanguage(String p0, ULocale p1){ return null; } + public static String getDisplayLanguageWithDialect(String p0, String p1){ return null; } + public static String getDisplayLanguageWithDialect(String p0, ULocale p1){ return null; } + public static String getDisplayName(String p0, String p1){ return null; } + public static String getDisplayName(String p0, ULocale p1){ return null; } + public static String getDisplayNameWithDialect(String p0, String p1){ return null; } + public static String getDisplayNameWithDialect(String p0, ULocale p1){ return null; } + public static String getDisplayScript(String p0, String p1){ return null; } + public static String getDisplayScript(String p0, ULocale p1){ return null; } + public static String getDisplayVariant(String p0, String p1){ return null; } + public static String getDisplayVariant(String p0, ULocale p1){ return null; } + public static String getFallback(String p0){ return null; } + public static String getISO3Country(String p0){ return null; } + public static String getISO3Language(String p0){ return null; } + public static String getKeywordValue(String p0, String p1){ return null; } + public static String getLanguage(String p0){ return null; } + public static String getName(String p0){ return null; } + public static String getScript(String p0){ return null; } + public static String getVariant(String p0){ return null; } + public static String setKeywordValue(String p0, String p1, String p2){ return null; } + public static String toLegacyKey(String p0){ return null; } + public static String toLegacyType(String p0, String p1){ return null; } + public static String toUnicodeLocaleKey(String p0){ return null; } + public static String toUnicodeLocaleType(String p0, String p1){ return null; } + public static String[] getISOCountries(){ return null; } + public static String[] getISOLanguages(){ return null; } + public static ULocale CANADA = null; + public static ULocale CANADA_FRENCH = null; + public static ULocale CHINA = null; + public static ULocale CHINESE = null; + public static ULocale ENGLISH = null; + public static ULocale FRANCE = null; + public static ULocale FRENCH = null; + public static ULocale GERMAN = null; + public static ULocale GERMANY = null; + public static ULocale ITALIAN = null; + public static ULocale ITALY = null; + public static ULocale JAPAN = null; + public static ULocale JAPANESE = null; + public static ULocale KOREA = null; + public static ULocale KOREAN = null; + public static ULocale PRC = null; + public static ULocale ROOT = null; + public static ULocale SIMPLIFIED_CHINESE = null; + public static ULocale TAIWAN = null; + public static ULocale TRADITIONAL_CHINESE = null; + public static ULocale UK = null; + public static ULocale US = null; + public static ULocale acceptLanguage(String p0, ULocale[] p1, boolean[] p2){ return null; } + public static ULocale acceptLanguage(String p0, boolean[] p1){ return null; } + public static ULocale acceptLanguage(ULocale[] p0, ULocale[] p1, boolean[] p2){ return null; } + public static ULocale acceptLanguage(ULocale[] p0, boolean[] p1){ return null; } + public static ULocale addLikelySubtags(ULocale p0){ return null; } + public static ULocale createCanonical(String p0){ return null; } + public static ULocale forLanguageTag(String p0){ return null; } + public static ULocale forLocale(Locale p0){ return null; } + public static ULocale getDefault(){ return null; } + public static ULocale getDefault(ULocale.Category p0){ return null; } + public static ULocale minimizeSubtags(ULocale p0){ return null; } + public static ULocale[] getAvailableLocales(){ return null; } + public static char PRIVATE_USE_EXTENSION = '0'; + public static char UNICODE_LOCALE_EXTENSION = '0'; + static public enum Category + { + DISPLAY, FORMAT; + private Category() {} + } +} diff --git a/java/ql/test/stubs/android/android/net/Uri.java b/java/ql/test/stubs/android/android/net/Uri.java index 371dab3cc97..ec3e601b7bb 100644 --- a/java/ql/test/stubs/android/android/net/Uri.java +++ b/java/ql/test/stubs/android/android/net/Uri.java @@ -1,5 +1,76 @@ +// Generated automatically from android.net.Uri for testing purposes + package android.net; -public class Uri { +import android.os.Parcel; +import android.os.Parcelable; +import java.io.File; +import java.util.List; +import java.util.Set; +abstract public class Uri implements Comparable<Uri>, Parcelable +{ + protected Uri() {} + public List<String> getQueryParameters(String p0){ return null; } + public Set<String> getQueryParameterNames(){ return null; } + public String getQueryParameter(String p0){ return null; } + public Uri normalizeScheme(){ return null; } + public abstract List<String> getPathSegments(); + public abstract String getAuthority(); + public abstract String getEncodedAuthority(); + public abstract String getEncodedFragment(); + public abstract String getEncodedPath(); + public abstract String getEncodedQuery(); + public abstract String getEncodedSchemeSpecificPart(); + public abstract String getEncodedUserInfo(); + public abstract String getFragment(); + public abstract String getHost(); + public abstract String getLastPathSegment(); + public abstract String getPath(); + public abstract String getQuery(); + public abstract String getScheme(); + public abstract String getSchemeSpecificPart(); + public abstract String getUserInfo(); + public abstract String toString(); + public abstract Uri.Builder buildUpon(); + public abstract boolean isHierarchical(); + public abstract boolean isRelative(); + public abstract int getPort(); + public boolean equals(Object p0){ return false; } + public boolean getBooleanQueryParameter(String p0, boolean p1){ return false; } + public boolean isAbsolute(){ return false; } + public boolean isOpaque(){ return false; } + public int compareTo(Uri p0){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<Uri> CREATOR = null; + public static String decode(String p0){ return null; } + public static String encode(String p0){ return null; } + public static String encode(String p0, String p1){ return null; } + public static Uri EMPTY = null; + public static Uri fromFile(File p0){ return null; } + public static Uri fromParts(String p0, String p1, String p2){ return null; } + public static Uri parse(String p0){ return null; } + public static Uri withAppendedPath(Uri p0, String p1){ return null; } + public static void writeToParcel(Parcel p0, Uri p1){} + static public class Builder + { + public Builder(){} + public String toString(){ return null; } + public Uri build(){ return null; } + public Uri.Builder appendEncodedPath(String p0){ return null; } + public Uri.Builder appendPath(String p0){ return null; } + public Uri.Builder appendQueryParameter(String p0, String p1){ return null; } + public Uri.Builder authority(String p0){ return null; } + public Uri.Builder clearQuery(){ return null; } + public Uri.Builder encodedAuthority(String p0){ return null; } + public Uri.Builder encodedFragment(String p0){ return null; } + public Uri.Builder encodedOpaquePart(String p0){ return null; } + public Uri.Builder encodedPath(String p0){ return null; } + public Uri.Builder encodedQuery(String p0){ return null; } + public Uri.Builder fragment(String p0){ return null; } + public Uri.Builder opaquePart(String p0){ return null; } + public Uri.Builder path(String p0){ return null; } + public Uri.Builder query(String p0){ return null; } + public Uri.Builder scheme(String p0){ return null; } + } } diff --git a/java/ql/test/stubs/android/android/os/BaseBundle.java b/java/ql/test/stubs/android/android/os/BaseBundle.java new file mode 100644 index 00000000000..3cc3c310c38 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/BaseBundle.java @@ -0,0 +1,43 @@ +// Generated automatically from android.os.BaseBundle for testing purposes + +package android.os; + +import android.os.PersistableBundle; +import java.util.Set; + +public class BaseBundle +{ + public Object get(String p0){ return null; } + public Set<String> keySet(){ return null; } + public String getString(String p0){ return null; } + public String getString(String p0, String p1){ return null; } + public String[] getStringArray(String p0){ return null; } + public boolean containsKey(String p0){ return false; } + public boolean getBoolean(String p0){ return false; } + public boolean getBoolean(String p0, boolean p1){ return false; } + public boolean isEmpty(){ return false; } + public boolean[] getBooleanArray(String p0){ return null; } + public double getDouble(String p0){ return 0; } + public double getDouble(String p0, double p1){ return 0; } + public double[] getDoubleArray(String p0){ return null; } + public int getInt(String p0){ return 0; } + public int getInt(String p0, int p1){ return 0; } + public int size(){ return 0; } + public int[] getIntArray(String p0){ return null; } + public long getLong(String p0){ return 0; } + public long getLong(String p0, long p1){ return 0; } + public long[] getLongArray(String p0){ return null; } + public void clear(){} + public void putAll(PersistableBundle p0){} + public void putBoolean(String p0, boolean p1){} + public void putBooleanArray(String p0, boolean[] p1){} + public void putDouble(String p0, double p1){} + public void putDoubleArray(String p0, double[] p1){} + public void putInt(String p0, int p1){} + public void putIntArray(String p0, int[] p1){} + public void putLong(String p0, long p1){} + public void putLongArray(String p0, long[] p1){} + public void putString(String p0, String p1){} + public void putStringArray(String p0, String[] p1){} + public void remove(String p0){} +} diff --git a/java/ql/test/stubs/android/android/os/Bundle.java b/java/ql/test/stubs/android/android/os/Bundle.java index fa49a640f30..4beb1cf5dee 100644 --- a/java/ql/test/stubs/android/android/os/Bundle.java +++ b/java/ql/test/stubs/android/android/os/Bundle.java @@ -1,87 +1,86 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.os.Bundle for testing purposes package android.os; -public final class Bundle { - public Bundle() { - } - - public Bundle(ClassLoader loader) { - } - - public Bundle(int capacity) { - } - - public Bundle(Bundle b) { - } - - public static Bundle forPair(String key, String value) { - return null; - } - - public boolean setAllowFds(boolean allowFds) { - return false; - } - - public void setDefusable(boolean defusable) { - } - - public static Bundle setDefusable(Bundle bundle, boolean defusable) { - return null; - } - - @Override - public Object clone() { - return null; - } - - public Bundle deepCopy() { - return null; - } - - public void remove(String key) { - } - - public void putAll(Bundle bundle) { - } - - public int getSize() { - return 0; - } - - public boolean hasFileDescriptors() { - return false; - } - - public Bundle filterValues() { - return null; - } - - @Override - public synchronized String toString() { - return null; - } - - public synchronized String toShortString() { - return null; - } - - public String getString(String string) { - return null; - } +import android.os.BaseBundle; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; +import android.util.Size; +import android.util.SizeF; +import android.util.SparseArray; +import java.io.Serializable; +import java.util.ArrayList; +public class Bundle extends BaseBundle implements Cloneable, Parcelable +{ + public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String p0){ return null; } + public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(String p0){ return null; } + public <T extends Parcelable> T getParcelable(String p0){ return null; } + public ArrayList<CharSequence> getCharSequenceArrayList(String p0){ return null; } + public ArrayList<Integer> getIntegerArrayList(String p0){ return null; } + public ArrayList<String> getStringArrayList(String p0){ return null; } + public Bundle deepCopy(){ return null; } + public Bundle getBundle(String p0){ return null; } + public Bundle(){} + public Bundle(Bundle p0){} + public Bundle(ClassLoader p0){} + public Bundle(PersistableBundle p0){} + public Bundle(int p0){} + public Byte getByte(String p0, byte p1){ return null; } + public CharSequence getCharSequence(String p0){ return null; } + public CharSequence getCharSequence(String p0, CharSequence p1){ return null; } + public CharSequence[] getCharSequenceArray(String p0){ return null; } + public ClassLoader getClassLoader(){ return null; } + public IBinder getBinder(String p0){ return null; } + public Object clone(){ return null; } + public Parcelable[] getParcelableArray(String p0){ return null; } + public Serializable getSerializable(String p0){ return null; } + public Size getSize(String p0){ return null; } + public SizeF getSizeF(String p0){ return null; } + public String toString(){ return null; } + public boolean hasFileDescriptors(){ return false; } + public byte getByte(String p0){ return 0; } + public byte[] getByteArray(String p0){ return null; } + public char getChar(String p0){ return '0'; } + public char getChar(String p0, char p1){ return '0'; } + public char[] getCharArray(String p0){ return null; } + public float getFloat(String p0){ return 0; } + public float getFloat(String p0, float p1){ return 0; } + public float[] getFloatArray(String p0){ return null; } + public int describeContents(){ return 0; } + public short getShort(String p0){ return 0; } + public short getShort(String p0, short p1){ return 0; } + public short[] getShortArray(String p0){ return null; } + public static Bundle EMPTY = null; + public static Parcelable.Creator<Bundle> CREATOR = null; + public void clear(){} + public void putAll(Bundle p0){} + public void putBinder(String p0, IBinder p1){} + public void putBundle(String p0, Bundle p1){} + public void putByte(String p0, byte p1){} + public void putByteArray(String p0, byte[] p1){} + public void putChar(String p0, char p1){} + public void putCharArray(String p0, char[] p1){} + public void putCharSequence(String p0, CharSequence p1){} + public void putCharSequenceArray(String p0, CharSequence[] p1){} + public void putCharSequenceArrayList(String p0, ArrayList<CharSequence> p1){} + public void putFloat(String p0, float p1){} + public void putFloatArray(String p0, float[] p1){} + public void putIntegerArrayList(String p0, ArrayList<Integer> p1){} + public void putParcelable(String p0, Parcelable p1){} + public void putParcelableArray(String p0, Parcelable[] p1){} + public void putParcelableArrayList(String p0, ArrayList<? extends Parcelable> p1){} + public void putSerializable(String p0, Serializable p1){} + public void putShort(String p0, short p1){} + public void putShortArray(String p0, short[] p1){} + public void putSize(String p0, Size p1){} + public void putSizeF(String p0, SizeF p1){} + public void putSparseParcelableArray(String p0, SparseArray<? extends Parcelable> p1){} + public void putStringArrayList(String p0, ArrayList<String> p1){} + public void readFromParcel(Parcel p0){} + public void remove(String p0){} + public void setClassLoader(ClassLoader p0){} + public void writeToParcel(Parcel p0, int p1){} } diff --git a/java/ql/test/stubs/android/android/os/CancellationSignal.java b/java/ql/test/stubs/android/android/os/CancellationSignal.java index 212e605a819..5112eb46595 100644 --- a/java/ql/test/stubs/android/android/os/CancellationSignal.java +++ b/java/ql/test/stubs/android/android/os/CancellationSignal.java @@ -1,5 +1,17 @@ +// Generated automatically from android.os.CancellationSignal for testing purposes + package android.os; -public class CancellationSignal { +public class CancellationSignal +{ + public CancellationSignal(){} + public boolean isCanceled(){ return false; } + public void cancel(){} + public void setOnCancelListener(CancellationSignal.OnCancelListener p0){} + public void throwIfCanceled(){} + static public interface OnCancelListener + { + void onCancel(); + } } diff --git a/java/ql/test/stubs/android/android/os/Handler.java b/java/ql/test/stubs/android/android/os/Handler.java new file mode 100644 index 00000000000..5d1ae91db88 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/Handler.java @@ -0,0 +1,53 @@ +// Generated automatically from android.os.Handler for testing purposes + +package android.os; + +import android.os.Looper; +import android.os.Message; +import android.util.Printer; + +public class Handler +{ + public Handler(){} + public Handler(Handler.Callback p0){} + public Handler(Looper p0){} + public Handler(Looper p0, Handler.Callback p1){} + public String getMessageName(Message p0){ return null; } + public String toString(){ return null; } + public boolean sendMessageAtTime(Message p0, long p1){ return false; } + public final Looper getLooper(){ return null; } + public final Message obtainMessage(){ return null; } + public final Message obtainMessage(int p0){ return null; } + public final Message obtainMessage(int p0, Object p1){ return null; } + public final Message obtainMessage(int p0, int p1, int p2){ return null; } + public final Message obtainMessage(int p0, int p1, int p2, Object p3){ return null; } + public final boolean hasCallbacks(Runnable p0){ return false; } + public final boolean hasMessages(int p0){ return false; } + public final boolean hasMessages(int p0, Object p1){ return false; } + public final boolean post(Runnable p0){ return false; } + public final boolean postAtFrontOfQueue(Runnable p0){ return false; } + public final boolean postAtTime(Runnable p0, Object p1, long p2){ return false; } + public final boolean postAtTime(Runnable p0, long p1){ return false; } + public final boolean postDelayed(Runnable p0, Object p1, long p2){ return false; } + public final boolean postDelayed(Runnable p0, long p1){ return false; } + public final boolean sendEmptyMessage(int p0){ return false; } + public final boolean sendEmptyMessageAtTime(int p0, long p1){ return false; } + public final boolean sendEmptyMessageDelayed(int p0, long p1){ return false; } + public final boolean sendMessage(Message p0){ return false; } + public final boolean sendMessageAtFrontOfQueue(Message p0){ return false; } + public final boolean sendMessageDelayed(Message p0, long p1){ return false; } + public final void dump(Printer p0, String p1){} + public final void removeCallbacks(Runnable p0){} + public final void removeCallbacks(Runnable p0, Object p1){} + public final void removeCallbacksAndMessages(Object p0){} + public final void removeMessages(int p0){} + public final void removeMessages(int p0, Object p1){} + public static Handler createAsync(Looper p0){ return null; } + public static Handler createAsync(Looper p0, Handler.Callback p1){ return null; } + public void dispatchMessage(Message p0){} + public void handleMessage(Message p0){} + static public interface Callback + { + boolean handleMessage(Message p0); + } +} diff --git a/java/ql/test/stubs/android/android/os/IBinder.java b/java/ql/test/stubs/android/android/os/IBinder.java new file mode 100644 index 00000000000..4441468b00f --- /dev/null +++ b/java/ql/test/stubs/android/android/os/IBinder.java @@ -0,0 +1,33 @@ +// Generated automatically from android.os.IBinder for testing purposes + +package android.os; + +import android.os.IInterface; +import android.os.Parcel; +import java.io.FileDescriptor; + +public interface IBinder +{ + IInterface queryLocalInterface(String p0); + String getInterfaceDescriptor(); + boolean isBinderAlive(); + boolean pingBinder(); + boolean transact(int p0, Parcel p1, Parcel p2, int p3); + boolean unlinkToDeath(IBinder.DeathRecipient p0, int p1); + static int DUMP_TRANSACTION = 0; + static int FIRST_CALL_TRANSACTION = 0; + static int FLAG_ONEWAY = 0; + static int INTERFACE_TRANSACTION = 0; + static int LAST_CALL_TRANSACTION = 0; + static int LIKE_TRANSACTION = 0; + static int PING_TRANSACTION = 0; + static int TWEET_TRANSACTION = 0; + static int getSuggestedMaxIpcSizeBytes(){ return 0; } + static public interface DeathRecipient + { + void binderDied(); + } + void dump(FileDescriptor p0, String[] p1); + void dumpAsync(FileDescriptor p0, String[] p1); + void linkToDeath(IBinder.DeathRecipient p0, int p1); +} diff --git a/java/ql/test/stubs/android/android/os/IInterface.java b/java/ql/test/stubs/android/android/os/IInterface.java new file mode 100644 index 00000000000..ccc3ae0a62d --- /dev/null +++ b/java/ql/test/stubs/android/android/os/IInterface.java @@ -0,0 +1,10 @@ +// Generated automatically from android.os.IInterface for testing purposes + +package android.os; + +import android.os.IBinder; + +public interface IInterface +{ + IBinder asBinder(); +} diff --git a/java/ql/test/stubs/android/android/os/LocaleList.java b/java/ql/test/stubs/android/android/os/LocaleList.java new file mode 100644 index 00000000000..113f5910a49 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/LocaleList.java @@ -0,0 +1,32 @@ +// Generated automatically from android.os.LocaleList for testing purposes + +package android.os; + +import android.icu.util.ULocale; +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Locale; + +public class LocaleList implements Parcelable +{ + protected LocaleList() {} + public Locale get(int p0){ return null; } + public Locale getFirstMatch(String[] p0){ return null; } + public LocaleList(Locale... p0){} + public String toLanguageTags(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int indexOf(Locale p0){ return 0; } + public int size(){ return 0; } + public static LocaleList forLanguageTags(String p0){ return null; } + public static LocaleList getAdjustedDefault(){ return null; } + public static LocaleList getDefault(){ return null; } + public static LocaleList getEmptyLocaleList(){ return null; } + public static Parcelable.Creator<LocaleList> CREATOR = null; + public static boolean isPseudoLocale(ULocale p0){ return false; } + public static void setDefault(LocaleList p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/os/Looper.java b/java/ql/test/stubs/android/android/os/Looper.java new file mode 100644 index 00000000000..bc7076c2125 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/Looper.java @@ -0,0 +1,25 @@ +// Generated automatically from android.os.Looper for testing purposes + +package android.os; + +import android.os.MessageQueue; +import android.util.Printer; + +public class Looper +{ + protected Looper() {} + public MessageQueue getQueue(){ return null; } + public String toString(){ return null; } + public Thread getThread(){ return null; } + public boolean isCurrentThread(){ return false; } + public static Looper getMainLooper(){ return null; } + public static Looper myLooper(){ return null; } + public static MessageQueue myQueue(){ return null; } + public static void loop(){} + public static void prepare(){} + public static void prepareMainLooper(){} + public void dump(Printer p0, String p1){} + public void quit(){} + public void quitSafely(){} + public void setMessageLogging(Printer p0){} +} diff --git a/java/ql/test/stubs/android/android/os/Message.java b/java/ql/test/stubs/android/android/os/Message.java new file mode 100644 index 00000000000..b6f98d43430 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/Message.java @@ -0,0 +1,44 @@ +// Generated automatically from android.os.Message for testing purposes + +package android.os; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Messenger; +import android.os.Parcel; +import android.os.Parcelable; + +public class Message implements Parcelable +{ + public Bundle getData(){ return null; } + public Bundle peekData(){ return null; } + public Handler getTarget(){ return null; } + public Message(){} + public Messenger replyTo = null; + public Object obj = null; + public Runnable getCallback(){ return null; } + public String toString(){ return null; } + public boolean isAsynchronous(){ return false; } + public int arg1 = 0; + public int arg2 = 0; + public int describeContents(){ return 0; } + public int sendingUid = 0; + public int what = 0; + public long getWhen(){ return 0; } + public static Message obtain(){ return null; } + public static Message obtain(Handler p0){ return null; } + public static Message obtain(Handler p0, Runnable p1){ return null; } + public static Message obtain(Handler p0, int p1){ return null; } + public static Message obtain(Handler p0, int p1, Object p2){ return null; } + public static Message obtain(Handler p0, int p1, int p2, int p3){ return null; } + public static Message obtain(Handler p0, int p1, int p2, int p3, Object p4){ return null; } + public static Message obtain(Message p0){ return null; } + public static Parcelable.Creator<Message> CREATOR = null; + public void copyFrom(Message p0){} + public void recycle(){} + public void sendToTarget(){} + public void setAsynchronous(boolean p0){} + public void setData(Bundle p0){} + public void setTarget(Handler p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/os/MessageQueue.java b/java/ql/test/stubs/android/android/os/MessageQueue.java new file mode 100644 index 00000000000..71d1e4b9fdd --- /dev/null +++ b/java/ql/test/stubs/android/android/os/MessageQueue.java @@ -0,0 +1,26 @@ +// Generated automatically from android.os.MessageQueue for testing purposes + +package android.os; + +import java.io.FileDescriptor; + +public class MessageQueue +{ + protected void finalize(){} + public boolean isIdle(){ return false; } + public void addIdleHandler(MessageQueue.IdleHandler p0){} + public void addOnFileDescriptorEventListener(FileDescriptor p0, int p1, MessageQueue.OnFileDescriptorEventListener p2){} + public void removeIdleHandler(MessageQueue.IdleHandler p0){} + public void removeOnFileDescriptorEventListener(FileDescriptor p0){} + static public interface IdleHandler + { + boolean queueIdle(); + } + static public interface OnFileDescriptorEventListener + { + int onFileDescriptorEvents(FileDescriptor p0, int p1); + static int EVENT_ERROR = 0; + static int EVENT_INPUT = 0; + static int EVENT_OUTPUT = 0; + } +} diff --git a/java/ql/test/stubs/android/android/os/Messenger.java b/java/ql/test/stubs/android/android/os/Messenger.java new file mode 100644 index 00000000000..08d2a975153 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/Messenger.java @@ -0,0 +1,25 @@ +// Generated automatically from android.os.Messenger for testing purposes + +package android.os; + +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; + +public class Messenger implements Parcelable +{ + protected Messenger() {} + public IBinder getBinder(){ return null; } + public Messenger(Handler p0){} + public Messenger(IBinder p0){} + public boolean equals(Object p0){ return false; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Messenger readMessengerOrNullFromParcel(Parcel p0){ return null; } + public static Parcelable.Creator<Messenger> CREATOR = null; + public static void writeMessengerOrNullToParcel(Messenger p0, Parcel p1){} + public void send(Message p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/os/Parcel.java b/java/ql/test/stubs/android/android/os/Parcel.java new file mode 100644 index 00000000000..ef6dcdeb085 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/Parcel.java @@ -0,0 +1,146 @@ +// Generated automatically from android.os.Parcel for testing purposes + +package android.os; + +import android.os.Bundle; +import android.os.IBinder; +import android.os.IInterface; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; +import android.os.PersistableBundle; +import android.util.ArrayMap; +import android.util.Size; +import android.util.SizeF; +import android.util.SparseArray; +import android.util.SparseBooleanArray; +import java.io.FileDescriptor; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Parcel +{ + protected Parcel() {} + protected void finalize(){} + public <T extends Parcelable> ArrayMap<String, T> createTypedArrayMap(Parcelable.Creator<T> p0){ return null; } + public <T extends Parcelable> List<T> readParcelableList(List<T> p0, ClassLoader p1){ return null; } + public <T extends Parcelable> SparseArray<T> createTypedSparseArray(Parcelable.Creator<T> p0){ return null; } + public <T extends Parcelable> T readParcelable(ClassLoader p0){ return null; } + public <T extends Parcelable> void writeParcelableArray(T[] p0, int p1){} + public <T extends Parcelable> void writeParcelableList(List<T> p0, int p1){} + public <T extends Parcelable> void writeTypedArray(T[] p0, int p1){} + public <T extends Parcelable> void writeTypedArrayMap(ArrayMap<String, T> p0, int p1){} + public <T extends Parcelable> void writeTypedList(List<T> p0){} + public <T extends Parcelable> void writeTypedObject(T p0, int p1){} + public <T extends Parcelable> void writeTypedSparseArray(SparseArray<T> p0, int p1){} + public <T> ArrayList<T> createTypedArrayList(Parcelable.Creator<T> p0){ return null; } + public <T> SparseArray<T> readSparseArray(ClassLoader p0){ return null; } + public <T> T readTypedObject(Parcelable.Creator<T> p0){ return null; } + public <T> T[] createTypedArray(Parcelable.Creator<T> p0){ return null; } + public <T> void readTypedArray(T[] p0, Parcelable.Creator<T> p1){} + public <T> void readTypedList(List<T> p0, Parcelable.Creator<T> p1){} + public <T> void writeSparseArray(SparseArray<T> p0){} + public ArrayList readArrayList(ClassLoader p0){ return null; } + public ArrayList<IBinder> createBinderArrayList(){ return null; } + public ArrayList<String> createStringArrayList(){ return null; } + public Bundle readBundle(){ return null; } + public Bundle readBundle(ClassLoader p0){ return null; } + public HashMap readHashMap(ClassLoader p0){ return null; } + public IBinder readStrongBinder(){ return null; } + public IBinder[] createBinderArray(){ return null; } + public Object readValue(ClassLoader p0){ return null; } + public Object[] readArray(ClassLoader p0){ return null; } + public ParcelFileDescriptor readFileDescriptor(){ return null; } + public Parcelable.Creator<? extends Object> readParcelableCreator(ClassLoader p0){ return null; } + public Parcelable[] readParcelableArray(ClassLoader p0){ return null; } + public PersistableBundle readPersistableBundle(){ return null; } + public PersistableBundle readPersistableBundle(ClassLoader p0){ return null; } + public Serializable readSerializable(){ return null; } + public Size readSize(){ return null; } + public SizeF readSizeF(){ return null; } + public SparseBooleanArray readSparseBooleanArray(){ return null; } + public String readString(){ return null; } + public String[] createStringArray(){ return null; } + public boolean hasFileDescriptors(){ return false; } + public boolean readBoolean(){ return false; } + public boolean[] createBooleanArray(){ return null; } + public byte readByte(){ return 0; } + public byte[] createByteArray(){ return null; } + public byte[] marshall(){ return null; } + public char[] createCharArray(){ return null; } + public double readDouble(){ return 0; } + public double[] createDoubleArray(){ return null; } + public float readFloat(){ return 0; } + public float[] createFloatArray(){ return null; } + public int dataAvail(){ return 0; } + public int dataCapacity(){ return 0; } + public int dataPosition(){ return 0; } + public int dataSize(){ return 0; } + public int readInt(){ return 0; } + public int[] createIntArray(){ return null; } + public long readLong(){ return 0; } + public long[] createLongArray(){ return null; } + public static Parcel obtain(){ return null; } + public static Parcelable.Creator<String> STRING_CREATOR = null; + public void appendFrom(Parcel p0, int p1, int p2){} + public void enforceInterface(String p0){} + public void readBinderArray(IBinder[] p0){} + public void readBinderList(List<IBinder> p0){} + public void readBooleanArray(boolean[] p0){} + public void readByteArray(byte[] p0){} + public void readCharArray(char[] p0){} + public void readDoubleArray(double[] p0){} + public void readException(){} + public void readException(int p0, String p1){} + public void readFloatArray(float[] p0){} + public void readIntArray(int[] p0){} + public void readList(List p0, ClassLoader p1){} + public void readLongArray(long[] p0){} + public void readMap(Map p0, ClassLoader p1){} + public void readStringArray(String[] p0){} + public void readStringList(List<String> p0){} + public void recycle(){} + public void setDataCapacity(int p0){} + public void setDataPosition(int p0){} + public void setDataSize(int p0){} + public void unmarshall(byte[] p0, int p1, int p2){} + public void writeArray(Object[] p0){} + public void writeBinderArray(IBinder[] p0){} + public void writeBinderList(List<IBinder> p0){} + public void writeBoolean(boolean p0){} + public void writeBooleanArray(boolean[] p0){} + public void writeBundle(Bundle p0){} + public void writeByte(byte p0){} + public void writeByteArray(byte[] p0){} + public void writeByteArray(byte[] p0, int p1, int p2){} + public void writeCharArray(char[] p0){} + public void writeDouble(double p0){} + public void writeDoubleArray(double[] p0){} + public void writeException(Exception p0){} + public void writeFileDescriptor(FileDescriptor p0){} + public void writeFloat(float p0){} + public void writeFloatArray(float[] p0){} + public void writeInt(int p0){} + public void writeIntArray(int[] p0){} + public void writeInterfaceToken(String p0){} + public void writeList(List p0){} + public void writeLong(long p0){} + public void writeLongArray(long[] p0){} + public void writeMap(Map p0){} + public void writeNoException(){} + public void writeParcelable(Parcelable p0, int p1){} + public void writeParcelableCreator(Parcelable p0){} + public void writePersistableBundle(PersistableBundle p0){} + public void writeSerializable(Serializable p0){} + public void writeSize(Size p0){} + public void writeSizeF(SizeF p0){} + public void writeSparseBooleanArray(SparseBooleanArray p0){} + public void writeString(String p0){} + public void writeStringArray(String[] p0){} + public void writeStringList(List<String> p0){} + public void writeStrongBinder(IBinder p0){} + public void writeStrongInterface(IInterface p0){} + public void writeValue(Object p0){} +} diff --git a/java/ql/test/stubs/android/android/os/ParcelFileDescriptor.java b/java/ql/test/stubs/android/android/os/ParcelFileDescriptor.java index 757872bb457..05b41873d41 100644 --- a/java/ql/test/stubs/android/android/os/ParcelFileDescriptor.java +++ b/java/ql/test/stubs/android/android/os/ParcelFileDescriptor.java @@ -1,5 +1,58 @@ +// Generated automatically from android.os.ParcelFileDescriptor for testing purposes + package android.os; -public class ParcelFileDescriptor { +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; +import java.io.Closeable; +import java.io.File; +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.Socket; +public class ParcelFileDescriptor implements Closeable, Parcelable +{ + protected ParcelFileDescriptor() {} + protected void finalize(){} + public FileDescriptor getFileDescriptor(){ return null; } + public ParcelFileDescriptor dup(){ return null; } + public ParcelFileDescriptor(ParcelFileDescriptor p0){} + public String toString(){ return null; } + public boolean canDetectErrors(){ return false; } + public int describeContents(){ return 0; } + public int detachFd(){ return 0; } + public int getFd(){ return 0; } + public long getStatSize(){ return 0; } + public static ParcelFileDescriptor adoptFd(int p0){ return null; } + public static ParcelFileDescriptor dup(FileDescriptor p0){ return null; } + public static ParcelFileDescriptor fromDatagramSocket(DatagramSocket p0){ return null; } + public static ParcelFileDescriptor fromFd(int p0){ return null; } + public static ParcelFileDescriptor fromSocket(Socket p0){ return null; } + public static ParcelFileDescriptor open(File p0, int p1){ return null; } + public static ParcelFileDescriptor open(File p0, int p1, Handler p2, ParcelFileDescriptor.OnCloseListener p3){ return null; } + public static ParcelFileDescriptor wrap(ParcelFileDescriptor p0, Handler p1, ParcelFileDescriptor.OnCloseListener p2){ return null; } + public static ParcelFileDescriptor[] createPipe(){ return null; } + public static ParcelFileDescriptor[] createReliablePipe(){ return null; } + public static ParcelFileDescriptor[] createReliableSocketPair(){ return null; } + public static ParcelFileDescriptor[] createSocketPair(){ return null; } + public static Parcelable.Creator<ParcelFileDescriptor> CREATOR = null; + public static int MODE_APPEND = 0; + public static int MODE_CREATE = 0; + public static int MODE_READ_ONLY = 0; + public static int MODE_READ_WRITE = 0; + public static int MODE_TRUNCATE = 0; + public static int MODE_WORLD_READABLE = 0; + public static int MODE_WORLD_WRITEABLE = 0; + public static int MODE_WRITE_ONLY = 0; + public static int parseMode(String p0){ return 0; } + public void checkError(){} + public void close(){} + public void closeWithError(String p0){} + public void writeToParcel(Parcel p0, int p1){} + static public interface OnCloseListener + { + void onClose(IOException p0); + } } diff --git a/java/ql/test/stubs/android/android/os/Parcelable.java b/java/ql/test/stubs/android/android/os/Parcelable.java new file mode 100644 index 00000000000..626061a6799 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/Parcelable.java @@ -0,0 +1,18 @@ +// Generated automatically from android.os.Parcelable for testing purposes + +package android.os; + +import android.os.Parcel; + +public interface Parcelable +{ + int describeContents(); + static int CONTENTS_FILE_DESCRIPTOR = 0; + static int PARCELABLE_WRITE_RETURN_VALUE = 0; + static public interface Creator<T> + { + T createFromParcel(Parcel p0); + T[] newArray(int p0); + } + void writeToParcel(Parcel p0, int p1); +} diff --git a/java/ql/test/stubs/android/android/os/PatternMatcher.java b/java/ql/test/stubs/android/android/os/PatternMatcher.java new file mode 100644 index 00000000000..d23c55aefd1 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/PatternMatcher.java @@ -0,0 +1,24 @@ +// Generated automatically from android.os.PatternMatcher for testing purposes + +package android.os; + +import android.os.Parcel; +import android.os.Parcelable; + +public class PatternMatcher implements Parcelable +{ + protected PatternMatcher() {} + public PatternMatcher(Parcel p0){} + public PatternMatcher(String p0, int p1){} + public String toString(){ return null; } + public boolean match(String p0){ return false; } + public final String getPath(){ return null; } + public final int getType(){ return 0; } + public int describeContents(){ return 0; } + public static Parcelable.Creator<PatternMatcher> CREATOR = null; + public static int PATTERN_ADVANCED_GLOB = 0; + public static int PATTERN_LITERAL = 0; + public static int PATTERN_PREFIX = 0; + public static int PATTERN_SIMPLE_GLOB = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/os/PersistableBundle.java b/java/ql/test/stubs/android/android/os/PersistableBundle.java new file mode 100644 index 00000000000..45354eb5b53 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/PersistableBundle.java @@ -0,0 +1,27 @@ +// Generated automatically from android.os.PersistableBundle for testing purposes + +package android.os; + +import android.os.BaseBundle; +import android.os.Parcel; +import android.os.Parcelable; +import java.io.InputStream; +import java.io.OutputStream; + +public class PersistableBundle extends BaseBundle implements Cloneable, Parcelable +{ + public Object clone(){ return null; } + public PersistableBundle deepCopy(){ return null; } + public PersistableBundle getPersistableBundle(String p0){ return null; } + public PersistableBundle(){} + public PersistableBundle(PersistableBundle p0){} + public PersistableBundle(int p0){} + public String toString(){ return null; } + public int describeContents(){ return 0; } + public static Parcelable.Creator<PersistableBundle> CREATOR = null; + public static PersistableBundle EMPTY = null; + public static PersistableBundle readFromStream(InputStream p0){ return null; } + public void putPersistableBundle(String p0, PersistableBundle p1){} + public void writeToParcel(Parcel p0, int p1){} + public void writeToStream(OutputStream p0){} +} diff --git a/java/ql/test/stubs/android/android/os/UserHandle.java b/java/ql/test/stubs/android/android/os/UserHandle.java new file mode 100644 index 00000000000..a2e4d596054 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/UserHandle.java @@ -0,0 +1,21 @@ +// Generated automatically from android.os.UserHandle for testing purposes + +package android.os; + +import android.os.Parcel; +import android.os.Parcelable; + +public class UserHandle implements Parcelable +{ + protected UserHandle() {} + public String toString(){ return null; } + public UserHandle(Parcel p0){} + public boolean equals(Object p0){ return false; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<UserHandle> CREATOR = null; + public static UserHandle getUserHandleForUid(int p0){ return null; } + public static UserHandle readFromParcel(Parcel p0){ return null; } + public static void writeToParcel(UserHandle p0, Parcel p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/android/android/util/AndroidException.java b/java/ql/test/stubs/android/android/util/AndroidException.java new file mode 100644 index 00000000000..aee2fef29f7 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/AndroidException.java @@ -0,0 +1,12 @@ +// Generated automatically from android.util.AndroidException for testing purposes + +package android.util; + + +public class AndroidException extends Exception +{ + public AndroidException(){} + public AndroidException(Exception p0){} + public AndroidException(String p0){} + public AndroidException(String p0, Throwable p1){} +} diff --git a/java/ql/test/stubs/android/android/util/ArrayMap.java b/java/ql/test/stubs/android/android/util/ArrayMap.java new file mode 100644 index 00000000000..55c7adebea7 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/ArrayMap.java @@ -0,0 +1,40 @@ +// Generated automatically from android.util.ArrayMap for testing purposes + +package android.util; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +public class ArrayMap<K, V> implements Map<K, V> +{ + public ArrayMap(){} + public ArrayMap(ArrayMap<K, V> p0){} + public ArrayMap(int p0){} + public Collection<V> values(){ return null; } + public K keyAt(int p0){ return null; } + public Set<K> keySet(){ return null; } + public Set<Map.Entry<K, V>> entrySet(){ return null; } + public String toString(){ return null; } + public V get(Object p0){ return null; } + public V put(K p0, V p1){ return null; } + public V remove(Object p0){ return null; } + public V removeAt(int p0){ return null; } + public V setValueAt(int p0, V p1){ return null; } + public V valueAt(int p0){ return null; } + public boolean containsAll(Collection<? extends Object> p0){ return false; } + public boolean containsKey(Object p0){ return false; } + public boolean containsValue(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public boolean removeAll(Collection<? extends Object> p0){ return false; } + public boolean retainAll(Collection<? extends Object> p0){ return false; } + public int hashCode(){ return 0; } + public int indexOfKey(Object p0){ return 0; } + public int indexOfValue(Object p0){ return 0; } + public int size(){ return 0; } + public void clear(){} + public void ensureCapacity(int p0){} + public void putAll(ArrayMap<? extends K, ? extends V> p0){} + public void putAll(Map<? extends K, ? extends V> p0){} +} diff --git a/java/ql/test/stubs/android/android/util/AttributeSet.java b/java/ql/test/stubs/android/android/util/AttributeSet.java index 27159b91485..04bdbe6b8d2 100644 --- a/java/ql/test/stubs/android/android/util/AttributeSet.java +++ b/java/ql/test/stubs/android/android/util/AttributeSet.java @@ -1,74 +1,31 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.util.AttributeSet for testing purposes package android.util; -public interface AttributeSet { - public int getAttributeCount(); - - default String getAttributeNamespace (int index) { - return null; - } - - public String getAttributeName(int index); - - public String getAttributeValue(int index); - - public String getAttributeValue(String namespace, String name); - - public String getPositionDescription(); - - public int getAttributeNameResource(int index); - - public int getAttributeListValue(String namespace, String attribute, - String[] options, int defaultValue); - - public boolean getAttributeBooleanValue(String namespace, String attribute, - boolean defaultValue); - - public int getAttributeResourceValue(String namespace, String attribute, - int defaultValue); - - public int getAttributeIntValue(String namespace, String attribute, - int defaultValue); - - public int getAttributeUnsignedIntValue(String namespace, String attribute, - int defaultValue); - - public float getAttributeFloatValue(String namespace, String attribute, - float defaultValue); - - public int getAttributeListValue(int index, String[] options, int defaultValue); - - public boolean getAttributeBooleanValue(int index, boolean defaultValue); - - public int getAttributeResourceValue(int index, int defaultValue); - - public int getAttributeIntValue(int index, int defaultValue); - - public int getAttributeUnsignedIntValue(int index, int defaultValue); - - public float getAttributeFloatValue(int index, float defaultValue); - - public String getIdAttribute(); - - public String getClassAttribute(); - - public int getIdAttributeResourceValue(int defaultValue); - - public int getStyleAttribute(); +public interface AttributeSet +{ + String getAttributeName(int p0); + String getAttributeValue(String p0, String p1); + String getAttributeValue(int p0); + String getClassAttribute(); + String getIdAttribute(); + String getPositionDescription(); + boolean getAttributeBooleanValue(String p0, String p1, boolean p2); + boolean getAttributeBooleanValue(int p0, boolean p1); + default String getAttributeNamespace(int p0){ return null; } + float getAttributeFloatValue(String p0, String p1, float p2); + float getAttributeFloatValue(int p0, float p1); + int getAttributeCount(); + int getAttributeIntValue(String p0, String p1, int p2); + int getAttributeIntValue(int p0, int p1); + int getAttributeListValue(String p0, String p1, String[] p2, int p3); + int getAttributeListValue(int p0, String[] p1, int p2); + int getAttributeNameResource(int p0); + int getAttributeResourceValue(String p0, String p1, int p2); + int getAttributeResourceValue(int p0, int p1); + int getAttributeUnsignedIntValue(String p0, String p1, int p2); + int getAttributeUnsignedIntValue(int p0, int p1); + int getIdAttributeResourceValue(int p0); + int getStyleAttribute(); } diff --git a/java/ql/test/stubs/android/android/util/DisplayMetrics.java b/java/ql/test/stubs/android/android/util/DisplayMetrics.java new file mode 100644 index 00000000000..fe64b670921 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/DisplayMetrics.java @@ -0,0 +1,46 @@ +// Generated automatically from android.util.DisplayMetrics for testing purposes + +package android.util; + + +public class DisplayMetrics +{ + public DisplayMetrics(){} + public String toString(){ return null; } + public boolean equals(DisplayMetrics p0){ return false; } + public boolean equals(Object p0){ return false; } + public float density = 0; + public float scaledDensity = 0; + public float xdpi = 0; + public float ydpi = 0; + public int densityDpi = 0; + public int hashCode(){ return 0; } + public int heightPixels = 0; + public int widthPixels = 0; + public static int DENSITY_140 = 0; + public static int DENSITY_180 = 0; + public static int DENSITY_200 = 0; + public static int DENSITY_220 = 0; + public static int DENSITY_260 = 0; + public static int DENSITY_280 = 0; + public static int DENSITY_300 = 0; + public static int DENSITY_340 = 0; + public static int DENSITY_360 = 0; + public static int DENSITY_400 = 0; + public static int DENSITY_420 = 0; + public static int DENSITY_440 = 0; + public static int DENSITY_450 = 0; + public static int DENSITY_560 = 0; + public static int DENSITY_600 = 0; + public static int DENSITY_DEFAULT = 0; + public static int DENSITY_DEVICE_STABLE = 0; + public static int DENSITY_HIGH = 0; + public static int DENSITY_LOW = 0; + public static int DENSITY_MEDIUM = 0; + public static int DENSITY_TV = 0; + public static int DENSITY_XHIGH = 0; + public static int DENSITY_XXHIGH = 0; + public static int DENSITY_XXXHIGH = 0; + public void setTo(DisplayMetrics p0){} + public void setToDefaults(){} +} diff --git a/java/ql/test/stubs/android/android/util/Pair.java b/java/ql/test/stubs/android/android/util/Pair.java new file mode 100644 index 00000000000..84a73730e05 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/Pair.java @@ -0,0 +1,16 @@ +// Generated automatically from android.util.Pair for testing purposes + +package android.util; + + +public class Pair<F, S> +{ + protected Pair() {} + public Pair(F p0, S p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final F first = null; + public final S second = null; + public int hashCode(){ return 0; } + public static <A, B> Pair<A, B> create(A p0, B p1){ return null; } +} diff --git a/java/ql/test/stubs/android/android/util/Printer.java b/java/ql/test/stubs/android/android/util/Printer.java new file mode 100644 index 00000000000..e6b67a13572 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/Printer.java @@ -0,0 +1,9 @@ +// Generated automatically from android.util.Printer for testing purposes + +package android.util; + + +public interface Printer +{ + void println(String p0); +} diff --git a/java/ql/test/stubs/android/android/util/Size.java b/java/ql/test/stubs/android/android/util/Size.java new file mode 100644 index 00000000000..9cd6edc8555 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/Size.java @@ -0,0 +1,16 @@ +// Generated automatically from android.util.Size for testing purposes + +package android.util; + + +public class Size +{ + protected Size() {} + public Size(int p0, int p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int getHeight(){ return 0; } + public int getWidth(){ return 0; } + public int hashCode(){ return 0; } + public static Size parseSize(String p0){ return null; } +} diff --git a/java/ql/test/stubs/android/android/util/SizeF.java b/java/ql/test/stubs/android/android/util/SizeF.java new file mode 100644 index 00000000000..16558fd17e6 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/SizeF.java @@ -0,0 +1,16 @@ +// Generated automatically from android.util.SizeF for testing purposes + +package android.util; + + +public class SizeF +{ + protected SizeF() {} + public SizeF(float p0, float p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public float getHeight(){ return 0; } + public float getWidth(){ return 0; } + public int hashCode(){ return 0; } + public static SizeF parseSizeF(String p0){ return null; } +} diff --git a/java/ql/test/stubs/android/android/util/SparseArray.java b/java/ql/test/stubs/android/android/util/SparseArray.java new file mode 100644 index 00000000000..11f3ffa5427 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/SparseArray.java @@ -0,0 +1,28 @@ +// Generated automatically from android.util.SparseArray for testing purposes + +package android.util; + + +public class SparseArray<E> implements Cloneable +{ + public E get(int p0){ return null; } + public E get(int p0, E p1){ return null; } + public E valueAt(int p0){ return null; } + public SparseArray(){} + public SparseArray(int p0){} + public SparseArray<E> clone(){ return null; } + public String toString(){ return null; } + public boolean contains(int p0){ return false; } + public int indexOfKey(int p0){ return 0; } + public int indexOfValue(E p0){ return 0; } + public int keyAt(int p0){ return 0; } + public int size(){ return 0; } + public void append(int p0, E p1){} + public void clear(){} + public void delete(int p0){} + public void put(int p0, E p1){} + public void remove(int p0){} + public void removeAt(int p0){} + public void removeAtRange(int p0, int p1){} + public void setValueAt(int p0, E p1){} +} diff --git a/java/ql/test/stubs/android/android/util/SparseBooleanArray.java b/java/ql/test/stubs/android/android/util/SparseBooleanArray.java new file mode 100644 index 00000000000..3c84c18e71b --- /dev/null +++ b/java/ql/test/stubs/android/android/util/SparseBooleanArray.java @@ -0,0 +1,27 @@ +// Generated automatically from android.util.SparseBooleanArray for testing purposes + +package android.util; + + +public class SparseBooleanArray implements Cloneable +{ + public SparseBooleanArray clone(){ return null; } + public SparseBooleanArray(){} + public SparseBooleanArray(int p0){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean get(int p0){ return false; } + public boolean get(int p0, boolean p1){ return false; } + public boolean valueAt(int p0){ return false; } + public int hashCode(){ return 0; } + public int indexOfKey(int p0){ return 0; } + public int indexOfValue(boolean p0){ return 0; } + public int keyAt(int p0){ return 0; } + public int size(){ return 0; } + public void append(int p0, boolean p1){} + public void clear(){} + public void delete(int p0){} + public void put(int p0, boolean p1){} + public void removeAt(int p0){} + public void setValueAt(int p0, boolean p1){} +} diff --git a/java/ql/test/stubs/android/android/util/TypedValue.java b/java/ql/test/stubs/android/android/util/TypedValue.java new file mode 100644 index 00000000000..269ab8bcf67 --- /dev/null +++ b/java/ql/test/stubs/android/android/util/TypedValue.java @@ -0,0 +1,73 @@ +// Generated automatically from android.util.TypedValue for testing purposes + +package android.util; + +import android.util.DisplayMetrics; + +public class TypedValue +{ + public CharSequence string = null; + public String toString(){ return null; } + public TypedValue(){} + public boolean isColorType(){ return false; } + public final CharSequence coerceToString(){ return null; } + public final float getFloat(){ return 0; } + public float getDimension(DisplayMetrics p0){ return 0; } + public float getFraction(float p0, float p1){ return 0; } + public int assetCookie = 0; + public int changingConfigurations = 0; + public int data = 0; + public int density = 0; + public int getComplexUnit(){ return 0; } + public int resourceId = 0; + public int sourceResourceId = 0; + public int type = 0; + public static String coerceToString(int p0, int p1){ return null; } + public static float applyDimension(int p0, float p1, DisplayMetrics p2){ return 0; } + public static float complexToDimension(int p0, DisplayMetrics p1){ return 0; } + public static float complexToFloat(int p0){ return 0; } + public static float complexToFraction(int p0, float p1, float p2){ return 0; } + public static int COMPLEX_MANTISSA_MASK = 0; + public static int COMPLEX_MANTISSA_SHIFT = 0; + public static int COMPLEX_RADIX_0p23 = 0; + public static int COMPLEX_RADIX_16p7 = 0; + public static int COMPLEX_RADIX_23p0 = 0; + public static int COMPLEX_RADIX_8p15 = 0; + public static int COMPLEX_RADIX_MASK = 0; + public static int COMPLEX_RADIX_SHIFT = 0; + public static int COMPLEX_UNIT_DIP = 0; + public static int COMPLEX_UNIT_FRACTION = 0; + public static int COMPLEX_UNIT_FRACTION_PARENT = 0; + public static int COMPLEX_UNIT_IN = 0; + public static int COMPLEX_UNIT_MASK = 0; + public static int COMPLEX_UNIT_MM = 0; + public static int COMPLEX_UNIT_PT = 0; + public static int COMPLEX_UNIT_PX = 0; + public static int COMPLEX_UNIT_SHIFT = 0; + public static int COMPLEX_UNIT_SP = 0; + public static int DATA_NULL_EMPTY = 0; + public static int DATA_NULL_UNDEFINED = 0; + public static int DENSITY_DEFAULT = 0; + public static int DENSITY_NONE = 0; + public static int TYPE_ATTRIBUTE = 0; + public static int TYPE_DIMENSION = 0; + public static int TYPE_FIRST_COLOR_INT = 0; + public static int TYPE_FIRST_INT = 0; + public static int TYPE_FLOAT = 0; + public static int TYPE_FRACTION = 0; + public static int TYPE_INT_BOOLEAN = 0; + public static int TYPE_INT_COLOR_ARGB4 = 0; + public static int TYPE_INT_COLOR_ARGB8 = 0; + public static int TYPE_INT_COLOR_RGB4 = 0; + public static int TYPE_INT_COLOR_RGB8 = 0; + public static int TYPE_INT_DEC = 0; + public static int TYPE_INT_HEX = 0; + public static int TYPE_LAST_COLOR_INT = 0; + public static int TYPE_LAST_INT = 0; + public static int TYPE_NULL = 0; + public static int TYPE_REFERENCE = 0; + public static int TYPE_STRING = 0; + public static int complexToDimensionPixelOffset(int p0, DisplayMetrics p1){ return 0; } + public static int complexToDimensionPixelSize(int p0, DisplayMetrics p1){ return 0; } + public void setTo(TypedValue p0){} +} diff --git a/java/ql/test/stubs/android/android/view/Display.java b/java/ql/test/stubs/android/android/view/Display.java new file mode 100644 index 00000000000..8c8061f00cb --- /dev/null +++ b/java/ql/test/stubs/android/android/view/Display.java @@ -0,0 +1,89 @@ +// Generated automatically from android.view.Display for testing purposes + +package android.view; + +import android.graphics.ColorSpace; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DisplayMetrics; +import android.view.DisplayCutout; + +public class Display +{ + public ColorSpace getPreferredWideGamutColorSpace(){ return null; } + public Display.HdrCapabilities getHdrCapabilities(){ return null; } + public Display.Mode getMode(){ return null; } + public Display.Mode[] getSupportedModes(){ return null; } + public DisplayCutout getCutout(){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public boolean isHdr(){ return false; } + public boolean isMinimalPostProcessingSupported(){ return false; } + public boolean isValid(){ return false; } + public boolean isWideColorGamut(){ return false; } + public float getRefreshRate(){ return 0; } + public float[] getSupportedRefreshRates(){ return null; } + public int getDisplayId(){ return 0; } + public int getFlags(){ return 0; } + public int getHeight(){ return 0; } + public int getOrientation(){ return 0; } + public int getPixelFormat(){ return 0; } + public int getRotation(){ return 0; } + public int getState(){ return 0; } + public int getWidth(){ return 0; } + public long getAppVsyncOffsetNanos(){ return 0; } + public long getPresentationDeadlineNanos(){ return 0; } + public static int DEFAULT_DISPLAY = 0; + public static int FLAG_PRESENTATION = 0; + public static int FLAG_PRIVATE = 0; + public static int FLAG_ROUND = 0; + public static int FLAG_SECURE = 0; + public static int FLAG_SUPPORTS_PROTECTED_BUFFERS = 0; + public static int INVALID_DISPLAY = 0; + public static int STATE_DOZE = 0; + public static int STATE_DOZE_SUSPEND = 0; + public static int STATE_OFF = 0; + public static int STATE_ON = 0; + public static int STATE_ON_SUSPEND = 0; + public static int STATE_UNKNOWN = 0; + public static int STATE_VR = 0; + public void getCurrentSizeRange(Point p0, Point p1){} + public void getMetrics(DisplayMetrics p0){} + public void getRealMetrics(DisplayMetrics p0){} + public void getRealSize(Point p0){} + public void getRectSize(Rect p0){} + public void getSize(Point p0){} + static public class HdrCapabilities implements Parcelable + { + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public float getDesiredMaxAverageLuminance(){ return 0; } + public float getDesiredMaxLuminance(){ return 0; } + public float getDesiredMinLuminance(){ return 0; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int[] getSupportedHdrTypes(){ return null; } + public static Parcelable.Creator<Display.HdrCapabilities> CREATOR = null; + public static float INVALID_LUMINANCE = 0; + public static int HDR_TYPE_DOLBY_VISION = 0; + public static int HDR_TYPE_HDR10 = 0; + public static int HDR_TYPE_HDR10_PLUS = 0; + public static int HDR_TYPE_HLG = 0; + public void writeToParcel(Parcel p0, int p1){} + } + static public class Mode implements Parcelable + { + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public float getRefreshRate(){ return 0; } + public int describeContents(){ return 0; } + public int getModeId(){ return 0; } + public int getPhysicalHeight(){ return 0; } + public int getPhysicalWidth(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<Display.Mode> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} + } +} diff --git a/java/ql/test/stubs/android/android/view/DisplayCutout.java b/java/ql/test/stubs/android/android/view/DisplayCutout.java new file mode 100644 index 00000000000..90d3ecf0b44 --- /dev/null +++ b/java/ql/test/stubs/android/android/view/DisplayCutout.java @@ -0,0 +1,28 @@ +// Generated automatically from android.view.DisplayCutout for testing purposes + +package android.view; + +import android.graphics.Insets; +import android.graphics.Rect; +import java.util.List; + +public class DisplayCutout +{ + protected DisplayCutout() {} + public DisplayCutout(Insets p0, Rect p1, Rect p2, Rect p3, Rect p4){} + public DisplayCutout(Insets p0, Rect p1, Rect p2, Rect p3, Rect p4, Insets p5){} + public DisplayCutout(Rect p0, List<Rect> p1){} + public Insets getWaterfallInsets(){ return null; } + public List<Rect> getBoundingRects(){ return null; } + public Rect getBoundingRectBottom(){ return null; } + public Rect getBoundingRectLeft(){ return null; } + public Rect getBoundingRectRight(){ return null; } + public Rect getBoundingRectTop(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int getSafeInsetBottom(){ return 0; } + public int getSafeInsetLeft(){ return 0; } + public int getSafeInsetRight(){ return 0; } + public int getSafeInsetTop(){ return 0; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/android/org/xmlpull/v1/XmlPullParser.java b/java/ql/test/stubs/android/org/xmlpull/v1/XmlPullParser.java new file mode 100644 index 00000000000..c693a5f6289 --- /dev/null +++ b/java/ql/test/stubs/android/org/xmlpull/v1/XmlPullParser.java @@ -0,0 +1,64 @@ +// Generated automatically from org.xmlpull.v1.XmlPullParser for testing purposes + +package org.xmlpull.v1; + +import java.io.InputStream; +import java.io.Reader; + +public interface XmlPullParser +{ + Object getProperty(String p0); + String getAttributeName(int p0); + String getAttributeNamespace(int p0); + String getAttributePrefix(int p0); + String getAttributeType(int p0); + String getAttributeValue(String p0, String p1); + String getAttributeValue(int p0); + String getInputEncoding(); + String getName(); + String getNamespace(); + String getNamespace(String p0); + String getNamespacePrefix(int p0); + String getNamespaceUri(int p0); + String getPositionDescription(); + String getPrefix(); + String getText(); + String nextText(); + boolean getFeature(String p0); + boolean isAttributeDefault(int p0); + boolean isEmptyElementTag(); + boolean isWhitespace(); + char[] getTextCharacters(int[] p0); + int getAttributeCount(); + int getColumnNumber(); + int getDepth(); + int getEventType(); + int getLineNumber(); + int getNamespaceCount(int p0); + int next(); + int nextTag(); + int nextToken(); + static String FEATURE_PROCESS_DOCDECL = null; + static String FEATURE_PROCESS_NAMESPACES = null; + static String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = null; + static String FEATURE_VALIDATION = null; + static String NO_NAMESPACE = null; + static String[] TYPES = null; + static int CDSECT = 0; + static int COMMENT = 0; + static int DOCDECL = 0; + static int END_DOCUMENT = 0; + static int END_TAG = 0; + static int ENTITY_REF = 0; + static int IGNORABLE_WHITESPACE = 0; + static int PROCESSING_INSTRUCTION = 0; + static int START_DOCUMENT = 0; + static int START_TAG = 0; + static int TEXT = 0; + void defineEntityReplacementText(String p0, String p1); + void require(int p0, String p1, String p2); + void setFeature(String p0, boolean p1); + void setInput(InputStream p0, String p1); + void setInput(Reader p0); + void setProperty(String p0, Object p1); +} diff --git a/java/ql/test/stubs/android/org/xmlpull/v1/XmlSerializer.java b/java/ql/test/stubs/android/org/xmlpull/v1/XmlSerializer.java new file mode 100644 index 00000000000..f0a985adebe --- /dev/null +++ b/java/ql/test/stubs/android/org/xmlpull/v1/XmlSerializer.java @@ -0,0 +1,35 @@ +// Generated automatically from org.xmlpull.v1.XmlSerializer for testing purposes + +package org.xmlpull.v1; + +import java.io.OutputStream; +import java.io.Writer; + +public interface XmlSerializer +{ + Object getProperty(String p0); + String getName(); + String getNamespace(); + String getPrefix(String p0, boolean p1); + XmlSerializer attribute(String p0, String p1, String p2); + XmlSerializer endTag(String p0, String p1); + XmlSerializer startTag(String p0, String p1); + XmlSerializer text(String p0); + XmlSerializer text(char[] p0, int p1, int p2); + boolean getFeature(String p0); + int getDepth(); + void cdsect(String p0); + void comment(String p0); + void docdecl(String p0); + void endDocument(); + void entityRef(String p0); + void flush(); + void ignorableWhitespace(String p0); + void processingInstruction(String p0); + void setFeature(String p0, boolean p1); + void setOutput(OutputStream p0, String p1); + void setOutput(Writer p0); + void setPrefix(String p0, String p1); + void setProperty(String p0, Object p1); + void startDocument(String p0, Boolean p1); +} From 447eb23356e872282203b011381a5c252c0f1af0 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Wed, 29 Sep 2021 16:01:08 +0100 Subject: [PATCH 078/361] Java: Fix for tc magic issue with subtyping. --- .../code/java/frameworks/android/Android.qll | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index 34064b3190e..4bcaa3734a7 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -6,19 +6,29 @@ import java import semmle.code.java.dataflow.ExternalFlow import semmle.code.xml.AndroidManifest +/** + * Gets a transitive superType avoiding magic optimisation + */ +pragma[nomagic] +private RefType getASuperTypePlus(RefType t) { result = t.getASupertype+() } + +/** + * Gets a reflexive/transitive superType avoiding magic optimisation + */ +pragma[inline] +private RefType getASuperTypeStar(RefType t) { result = getASuperTypePlus(t) or result = t } + /** * An Android component. That is, either an activity, a service, * a broadcast receiver, or a content provider. */ class AndroidComponent extends Class { AndroidComponent() { - // The casts here are due to misoptimisation if they are missing - // but are not needed semantically. - this.(Class).getASupertype*().hasQualifiedName("android.app", "Activity") or - this.(Class).getASupertype*().hasQualifiedName("android.app", "Service") or - this.(Class).getASupertype*().hasQualifiedName("android.content", "BroadcastReceiver") or - this.(Class).getASupertype*().hasQualifiedName("android.content", "ContentProvider") or - this.(Class).getASupertype*().hasQualifiedName("android.content", "ContentResolver") + getASuperTypeStar(this).hasQualifiedName("android.app", "Activity") or + getASuperTypeStar(this).hasQualifiedName("android.app", "Service") or + getASuperTypeStar(this).hasQualifiedName("android.content", "BroadcastReceiver") or + getASuperTypeStar(this).hasQualifiedName("android.content", "ContentProvider") or + getASuperTypeStar(this).hasQualifiedName("android.content", "ContentResolver") } /** The XML element corresponding to this Android component. */ @@ -52,32 +62,32 @@ class ExportableAndroidComponent extends AndroidComponent { /** An Android activity. */ class AndroidActivity extends ExportableAndroidComponent { - AndroidActivity() { this.getASupertype*().hasQualifiedName("android.app", "Activity") } + AndroidActivity() { getASuperTypeStar(this).hasQualifiedName("android.app", "Activity") } } /** An Android service. */ class AndroidService extends ExportableAndroidComponent { - AndroidService() { this.getASupertype*().hasQualifiedName("android.app", "Service") } + AndroidService() { getASuperTypeStar(this).hasQualifiedName("android.app", "Service") } } /** An Android broadcast receiver. */ class AndroidBroadcastReceiver extends ExportableAndroidComponent { AndroidBroadcastReceiver() { - this.getASupertype*().hasQualifiedName("android.content", "BroadcastReceiver") + getASuperTypeStar(this).hasQualifiedName("android.content", "BroadcastReceiver") } } /** An Android content provider. */ class AndroidContentProvider extends ExportableAndroidComponent { AndroidContentProvider() { - this.getASupertype*().hasQualifiedName("android.content", "ContentProvider") + getASuperTypeStar(this).hasQualifiedName("android.content", "ContentProvider") } } /** An Android content resolver. */ class AndroidContentResolver extends AndroidComponent { AndroidContentResolver() { - this.getASupertype*().hasQualifiedName("android.content", "ContentResolver") + getASuperTypeStar(this).hasQualifiedName("android.content", "ContentResolver") } } From 02e91b3902476d7d049a7462c2e6171e67be83eb Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 30 Sep 2021 13:36:24 +0200 Subject: [PATCH 079/361] Python: Model functions that will raise on non-existing files. --- .../lib/semmle/python/frameworks/Stdlib.qll | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 46f0349de77..0239b726cef 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -196,23 +196,36 @@ private module StdlibPrivate { } /** - * A call to `os.path.exists` or `os.path.lexists` will check if a file exists on the file system. - * The `os.path` module offers e number of methods for checking if a file exists and/or has certain + * The `os.path` module offers a number of methods for checking if a file exists and/or has certain * properties, leading to a file system access. + * A call to `os.path.exists` or `os.path.lexists` will check if a file exists on the file system. * (Although, on some platforms, the check may return `false` due to missing permissions.) + * A call to `os.path.getatime` will raise `OSError` if the file does not exist or is inaccessible. * See: - * - https://docs.python.org/3/library/os.path.html#os.path.exists - * - https://docs.python.org/3/library/os.path.html#os.path.lexists - * - https://docs.python.org/3/library/os.path.html#os.path.isfile - * - https://docs.python.org/3/library/os.path.html#os.path.isdir - * - https://docs.python.org/3/library/os.path.html#os.path.islink - * - https://docs.python.org/3/library/os.path.html#os.path.ismount + * - https://docs.python.org/3/library/os.path.html#os.path.exists + * - https://docs.python.org/3/library/os.path.html#os.path.lexists + * - https://docs.python.org/3/library/os.path.html#os.path.isfile + * - https://docs.python.org/3/library/os.path.html#os.path.isdir + * - https://docs.python.org/3/library/os.path.html#os.path.islink + * - https://docs.python.org/3/library/os.path.html#os.path.ismount + * - https://docs.python.org/3/library/os.path.html#os.path.getatime + * - https://docs.python.org/3/library/os.path.html#os.path.getmtime + * - https://docs.python.org/3/library/os.path.html#os.path.getctime + * - https://docs.python.org/3/library/os.path.html#os.path.getsize + * - https://docs.python.org/3/library/os.path.html#os.path.realpath */ private class OsPathProbingCall extends FileSystemAccess::Range, DataFlow::CallCfgNode { OsPathProbingCall() { this = os::path() - .getMember(["exists", "lexists", "isfile", "isdir", "islink", "ismount"]) + .getMember([ + // these check if the file exists + "exists", "lexists", "isfile", "isdir", "islink", "ismount", + // these raise errors if the file does not exist + "getatime", "getmtime", "getctime", "getsize", + // this will resolve symlinks + "realpath" + ]) .getACall() } @@ -221,6 +234,17 @@ private module StdlibPrivate { } } + /** A call to `os.path.samefile` will raise an exception if an `os.stat()` call on either pathname fails. */ + private class OsPathSamefileCall extends FileSystemAccess::Range, DataFlow::CallCfgNode { + OsPathSamefileCall() { this = os::path().getMember("samefile").getACall() } + + override DataFlow::Node getAPathArgument() { + result in [ + this.getArg(0), this.getArgByName("path1"), this.getArg(1), this.getArgByName("path2") + ] + } + } + /** * A call to `os.path.normpath`. * See https://docs.python.org/3/library/os.path.html#os.path.normpath From 46e62cd963fd9b1977131795de4cdb70e5511410 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Thu, 30 Sep 2021 14:00:18 +0200 Subject: [PATCH 080/361] Apply suggestions from code review Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> --- python/ql/lib/semmle/python/Concepts.qll | 4 ++-- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index 66caaa3c877..b26aad650af 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -366,8 +366,8 @@ class RegexExecution extends DataFlow::Node { RegexExecution() { this = range } - /** Gets the data flow node for the regex being compiled by this node. */ - DataFlow::Node getRegexNode() { result = range.getRegexNode() } + /** Gets the data flow node for the regex being executed by this node. */ + DataFlow::Node getRegex() { result = range.getRegex() } /** Gets a dataflow node for the string to be searched or matched against. */ DataFlow::Node getString() { result = range.getString() } diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 76c2f144e09..4b2a4b338c3 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1525,7 +1525,7 @@ int stringArg(RegexExecutionMethod method) { * * See `RegexExecutionMethods` */ -private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range { +private class DirectRegexExecution extends DataFlow::CallCfgNode, RegexExecution::Range { RegexExecutionMethod method; DirectRegex() { this = API::moduleImport("re").getMember(method).getACall() } @@ -1611,7 +1611,7 @@ private import CompiledRegexes * * See https://docs.python.org/3/library/re.html#regular-expression-objects */ -private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range { +private class CompiledRegexExecution extends DataFlow::CallCfgNode, RegexExecution::Range { DataFlow::Node regexNode; RegexExecutionMethod method; @@ -1640,14 +1640,13 @@ private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range * See https://docs.python.org/3/library/re.html#re.escape */ private class ReEscapeCall extends Escaping::Range, DataFlow::CallCfgNode { - DataFlow::Node regexNode; - ReEscapeCall() { - this = API::moduleImport("re").getMember("escape").getACall() and - regexNode in [this.getArg(0), this.getArgByName("pattern")] + this = API::moduleImport("re").getMember("escape").getACall() } - override DataFlow::Node getAnInput() { result = regexNode } + override DataFlow::Node getAnInput() { + result in [this.getArg(0), this.getArgByName("pattern")] + } override DataFlow::Node getOutput() { result = this } From d19d37bf9b91b8e62beb7d1fa1a2b630d6410ebb Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 30 Sep 2021 14:36:26 +0200 Subject: [PATCH 081/361] Python: more suggestions from review --- python/ql/lib/semmle/python/Concepts.qll | 4 +- .../lib/semmle/python/frameworks/Stdlib.qll | 274 +++++++++--------- 2 files changed, 137 insertions(+), 141 deletions(-) diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index b26aad650af..a61734f1b3e 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -388,8 +388,8 @@ module RegexExecution { * extend `RegexExecution` instead. */ abstract class Range extends DataFlow::Node { - /** Gets the data flow node for the regex being compiled by this node. */ - abstract DataFlow::Node getRegexNode(); + /** Gets the data flow node for the regex being executed by this node. */ + abstract DataFlow::Node getRegex(); /** Gets a dataflow node for the string to be searched or matched against. */ abstract DataFlow::Node getString(); diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 4b2a4b338c3..697a154ab94 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1495,162 +1495,158 @@ private module StdlibPrivate { result = this.getArg(any(int i | i >= msgIndex)) } } -} -// --------------------------------------------------------------------------- -// re -// --------------------------------------------------------------------------- -/** - * List of methods in the `re` module immediately executing a regular expression. - * - * See https://docs.python.org/3/library/re.html#module-contents - */ -private class RegexExecutionMethod extends string { - RegexExecutionMethod() { - this in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"] - } -} - -/** Gets the index of the argument representing the string to be searched by a regex. */ -int stringArg(RegexExecutionMethod method) { - method in ["match", "fullmatch", "search", "split", "findall", "finditer"] and - result = 1 - or - method in ["sub", "subn"] and - result = 2 -} - -/** - * A a call to a method from the `re` module immediately executing a regular expression. - * - * See `RegexExecutionMethods` - */ -private class DirectRegexExecution extends DataFlow::CallCfgNode, RegexExecution::Range { - RegexExecutionMethod method; - - DirectRegex() { this = API::moduleImport("re").getMember(method).getACall() } - - override DataFlow::Node getRegexNode() { - result in [this.getArg(0), this.getArgByName("pattern")] - } - - override DataFlow::Node getString() { - result in [this.getArg(stringArg(method)), this.getArgByName("string")] - } - - override string getName() { result = "re." + method } -} - -/** Helper module for tracking compiled regexes. */ -private module CompiledRegexes { - private import semmle.python.dataflow.new.DataFlow4 - private import semmle.python.RegexTreeView - - // TODO: This module should be refactored once API graphs are more expressive. - // For now it uses data flow, so we pick the verion with least change of collision (4) . - /** A configuration for finding uses of compiled regexes. */ - class RegexDefinitionConfiguration extends DataFlow4::Configuration { - RegexDefinitionConfiguration() { this = "RegexDefinitionConfiguration" } - - override predicate isSource(DataFlow::Node source) { source instanceof RegexDefinitonSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof RegexDefinitionSink } - } - - /** A regex compilation. */ - class RegexDefinitonSource extends DataFlow::CallCfgNode { - DataFlow::Node regexNode; - - RegexDefinitonSource() { - this = API::moduleImport("re").getMember("compile").getACall() and - regexNode in [this.getArg(0), this.getArgByName("pattern")] + // --------------------------------------------------------------------------- + // re + // --------------------------------------------------------------------------- + /** + * List of methods in the `re` module immediately executing a regular expression. + * + * See https://docs.python.org/3/library/re.html#module-contents + */ + private class RegexExecutionMethod extends string { + RegexExecutionMethod() { + this in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"] } - - /** Gets the data flow node for the regex being compiled by this node. */ - DataFlow::Node getRegexNode() { result = regexNode } } - /** A use of a compiled regex. */ - class RegexDefinitionSink extends DataFlow::Node { + /** Gets the index of the argument representing the string to be searched by a regex. */ + int getStringArgIndex(RegexExecutionMethod method) { + method in ["match", "fullmatch", "search", "split", "findall", "finditer"] and + result = 1 + or + method in ["sub", "subn"] and + result = 2 + } + + /** + * A a call to a method from the `re` module immediately executing a regular expression. + * + * See `RegexExecutionMethods` + */ + private class DirectRegexExecution extends DataFlow::CallCfgNode, RegexExecution::Range { RegexExecutionMethod method; - DataFlow::CallCfgNode executingCall; - RegexDefinitionSink() { - executingCall = - API::moduleImport("re").getMember("compile").getReturn().getMember(method).getACall() and - this = executingCall.getFunction().(DataFlow::AttrRead).getObject() + DirectRegexExecution() { this = API::moduleImport("re").getMember(method).getACall() } + + override DataFlow::Node getRegex() { result in [this.getArg(0), this.getArgByName("pattern")] } + + override DataFlow::Node getString() { + result in [this.getArg(getStringArgIndex(method)), this.getArgByName("string")] } - /** Gets the method used to execute the regex. */ - RegexExecutionMethod getMethod() { result = method } - - /** Gets the data flow node for the executing call. */ - DataFlow::CallCfgNode getExecutingCall() { result = executingCall } - } -} - -private import CompiledRegexes - -/** - * A call on compiled regular expression (obtained via `re.compile`) executing a - * regular expression. - * - * Given the following example: - * - * ```py - * pattern = re.compile(input) - * pattern.match(s) - * ``` - * - * This class will identify that `re.compile` compiles `input` and afterwards - * executes `re`'s `match`. As a result, `this` will refer to `pattern.match(s)` - * and `this.getRegexNode()` will return the node for `input` (`re.compile`'s first argument). - * - * - * See `RegexExecutionMethods` - * - * See https://docs.python.org/3/library/re.html#regular-expression-objects - */ -private class CompiledRegexExecution extends DataFlow::CallCfgNode, RegexExecution::Range { - DataFlow::Node regexNode; - RegexExecutionMethod method; - - CompiledRegex() { - exists( - RegexDefinitionConfiguration conf, RegexDefinitonSource source, RegexDefinitionSink sink - | - conf.hasFlow(source, sink) and - regexNode = source.getRegexNode() and - method = sink.getMethod() and - this = sink.getExecutingCall() - ) + override string getName() { result = "re." + method } } - override DataFlow::Node getRegexNode() { result = regexNode } + /** Helper module for tracking compiled regexes. */ + private module CompiledRegexes { + private import semmle.python.dataflow.new.DataFlow4 + private import semmle.python.RegexTreeView - override DataFlow::Node getString() { - result in [this.getArg(stringArg(method) - 1), this.getArgByName("string")] + // TODO: This module should be refactored once API graphs are more expressive. + // For now it uses data flow, so we pick the verion with least change of collision (4) . + /** A configuration for finding uses of compiled regexes. */ + class RegexDefinitionConfiguration extends DataFlow4::Configuration { + RegexDefinitionConfiguration() { this = "RegexDefinitionConfiguration" } + + override predicate isSource(DataFlow::Node source) { source instanceof RegexDefinitonSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof RegexDefinitionSink } + } + + /** A regex compilation. */ + class RegexDefinitonSource extends DataFlow::CallCfgNode { + DataFlow::Node regexNode; + + RegexDefinitonSource() { + this = API::moduleImport("re").getMember("compile").getACall() and + regexNode in [this.getArg(0), this.getArgByName("pattern")] + } + + /** Gets the data flow node for the regex being compiled by this node. */ + DataFlow::Node getRegexNode() { result = regexNode } + } + + /** A use of a compiled regex. */ + class RegexDefinitionSink extends DataFlow::Node { + RegexExecutionMethod method; + DataFlow::CallCfgNode executingCall; + + RegexDefinitionSink() { + executingCall = + API::moduleImport("re").getMember("compile").getReturn().getMember(method).getACall() and + this = executingCall.getFunction().(DataFlow::AttrRead).getObject() + } + + /** Gets the method used to execute the regex. */ + RegexExecutionMethod getMethod() { result = method } + + /** Gets the data flow node for the executing call. */ + DataFlow::CallCfgNode getExecutingCall() { result = executingCall } + } } - override string getName() { result = "re." + method } -} + private import CompiledRegexes -/** - * A call to 're.escape'. - * See https://docs.python.org/3/library/re.html#re.escape - */ -private class ReEscapeCall extends Escaping::Range, DataFlow::CallCfgNode { - ReEscapeCall() { - this = API::moduleImport("re").getMember("escape").getACall() + /** + * A call on compiled regular expression (obtained via `re.compile`) executing a + * regular expression. + * + * Given the following example: + * + * ```py + * pattern = re.compile(input) + * pattern.match(s) + * ``` + * + * This class will identify that `re.compile` compiles `input` and afterwards + * executes `re`'s `match`. As a result, `this` will refer to `pattern.match(s)` + * and `this.getRegexNode()` will return the node for `input` (`re.compile`'s first argument). + * + * + * See `RegexExecutionMethods` + * + * See https://docs.python.org/3/library/re.html#regular-expression-objects + */ + private class CompiledRegexExecution extends DataFlow::CallCfgNode, RegexExecution::Range { + DataFlow::Node regexNode; + RegexExecutionMethod method; + + CompiledRegexExecution() { + exists( + RegexDefinitionConfiguration conf, RegexDefinitonSource source, RegexDefinitionSink sink + | + conf.hasFlow(source, sink) and + regexNode = source.getRegexNode() and + method = sink.getMethod() and + this = sink.getExecutingCall() + ) + } + + override DataFlow::Node getRegex() { result = regexNode } + + override DataFlow::Node getString() { + result in [this.getArg(getStringArgIndex(method) - 1), this.getArgByName("string")] + } + + override string getName() { result = "re." + method } } - override DataFlow::Node getAnInput() { - result in [this.getArg(0), this.getArgByName("pattern")] + /** + * A call to 're.escape'. + * See https://docs.python.org/3/library/re.html#re.escape + */ + private class ReEscapeCall extends Escaping::Range, DataFlow::CallCfgNode { + ReEscapeCall() { this = API::moduleImport("re").getMember("escape").getACall() } + + override DataFlow::Node getAnInput() { + result in [this.getArg(0), this.getArgByName("pattern")] + } + + override DataFlow::Node getOutput() { result = this } + + override string getKind() { result = Escaping::getRegexKind() } } - - override DataFlow::Node getOutput() { result = this } - - override string getKind() { result = Escaping::getRegexKind() } } // --------------------------------------------------------------------------- From f3fc56a167f7b3d463774323dee861027e883581 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 30 Sep 2021 14:39:05 +0200 Subject: [PATCH 082/361] Python: typos --- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 697a154ab94..60db928a162 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1544,7 +1544,7 @@ private module StdlibPrivate { private import semmle.python.RegexTreeView // TODO: This module should be refactored once API graphs are more expressive. - // For now it uses data flow, so we pick the verion with least change of collision (4) . + // For now it uses data flow, so we pick the verison with least chance of collision (4) . /** A configuration for finding uses of compiled regexes. */ class RegexDefinitionConfiguration extends DataFlow4::Configuration { RegexDefinitionConfiguration() { this = "RegexDefinitionConfiguration" } From 35d9005eae51194bb59d8a79d71ee24f96923203 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 30 Sep 2021 14:39:44 +0200 Subject: [PATCH 083/361] Python: typo again.. --- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 60db928a162..5f66bc31b27 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1544,7 +1544,7 @@ private module StdlibPrivate { private import semmle.python.RegexTreeView // TODO: This module should be refactored once API graphs are more expressive. - // For now it uses data flow, so we pick the verison with least chance of collision (4) . + // For now it uses data flow, so we pick the version with least chance of collision (4) . /** A configuration for finding uses of compiled regexes. */ class RegexDefinitionConfiguration extends DataFlow4::Configuration { RegexDefinitionConfiguration() { this = "RegexDefinitionConfiguration" } From 3d61c81456444973cfb8cc01f4447d1dde73eace Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 00:09:22 +0000 Subject: [PATCH 084/361] Add changed framework coverage reports --- java/documentation/library-coverage/coverage.csv | 2 ++ java/documentation/library-coverage/coverage.rst | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index c338b6252ac..08c55d973dd 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -4,6 +4,7 @@ android.database,59,,30,,,,,,,,,,,,,59,,,,,,,,30, android.net,,,60,,,,,,,,,,,,,,,,,,,,,45,15 android.util,,16,,,,,,,,,,,,,,,,,,,,,16,, android.webkit,3,2,,,,,,,,,,,,,,,,,,,3,,2,, +cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,1, com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,1, com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,1, com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,1, @@ -61,6 +62,7 @@ org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,2, org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,18,6 org.apache.http,27,3,70,,,,,,,,,,,25,,,,,,,2,,3,62,8 org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,6,,,,,,,,, +org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,1, org.apache.shiro.jndi,1,,,,,,,,,1,,,,,,,,,,,,,,, org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,, org.dom4j,20,,,,,,,,,,,,,,,,,,20,,,,,, diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index a2c235248a1..a39dba6452b 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -18,6 +18,6 @@ Java framework & library support Java Standard Library,``java.*``,3,426,30,13,,,7,,,10 Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2 `Spring <https://spring.io/>`_,``org.springframework.*``,29,469,91,,,,19,14,,29 - Others,"``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,26,151,,,,14,18,, - Totals,,143,4984,408,13,6,10,107,33,1,66 + Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,28,151,,,,14,18,, + Totals,,143,4986,408,13,6,10,107,33,1,66 From 175a06fe73cd569f6c1662d3f09ece8762f302ee Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Fri, 1 Oct 2021 10:33:42 +0200 Subject: [PATCH 085/361] Python: Fix compile error due to predicate rename --- .../python/security/dataflow/PolynomialReDoSCustomizations.qll | 2 +- .../python/security/injection/RegexInjectionCustomizations.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll index 33d88c5d0ed..b92ff341ec8 100644 --- a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll @@ -61,7 +61,7 @@ module PolynomialReDoS { RegexExecutionAsSink() { exists(RegexExecution re | - re.getRegexNode().asExpr() = t.getRegex() and + re.getRegex().asExpr() = t.getRegex() and this = re.getString() ) and t.isRootTerm() diff --git a/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll index a44b4c5c19e..c26bae1c1b4 100644 --- a/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll @@ -28,7 +28,7 @@ module RegexInjection { class Sink extends DataFlow::Node { RegexExecution regexExecution; - Sink() { this = regexExecution.getRegexNode() } + Sink() { this = regexExecution.getRegex() } /** Gets the call that executes the regular expression marked by this sink. */ RegexExecution getRegexExecution() { result = regexExecution } From 679b0f9b730478c576f63654706e974f5e2029dd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 09:40:16 +0100 Subject: [PATCH 086/361] C++: Autoformat. --- cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll | 4 +--- cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll index de4d470ce1f..0551185ba14 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll @@ -86,7 +86,5 @@ private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, description = "Buffer read by " + this.getName() } - override predicate hasSocketInput(FunctionInput input) { - input.isParameter(0) - } + override predicate hasSocketInput(FunctionInput input) { input.isParameter(0) } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll index e747d8182b7..d871bad68af 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll @@ -61,7 +61,5 @@ private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, Rem input.isParameterDeref(1) and description = "Buffer sent by " + this.getName() } - override predicate hasSocketInput(FunctionInput input) { - input.isParameter(0) - } + override predicate hasSocketInput(FunctionInput input) { input.isParameter(0) } } From af1b04de9cccc58c2212f76235cf3b573e88b448 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 1 Oct 2021 11:42:03 +0200 Subject: [PATCH 087/361] JS: Restrict what property names that are considered public exports --- .../lib/semmle/javascript/PackageExports.qll | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/PackageExports.qll b/javascript/ql/lib/semmle/javascript/PackageExports.qll index 97009adc065..17510bc214f 100644 --- a/javascript/ql/lib/semmle/javascript/PackageExports.qll +++ b/javascript/ql/lib/semmle/javascript/PackageExports.qll @@ -30,7 +30,11 @@ private DataFlow::Node getAValueExportedByPackage() { getAnExportFromModule(any(PackageJSON pack | exists(pack.getPackageName())).getMainModule()) or // module.exports.bar.baz = result; - result = getAValueExportedByPackage().(DataFlow::PropWrite).getRhs() + exists(DataFlow::PropWrite write | + write = getAValueExportedByPackage() and + write.getPropertyName() = publicPropertyName() and + result = write.getRhs() + ) or // class Foo { // bar() {} // <- result @@ -39,15 +43,15 @@ private DataFlow::Node getAValueExportedByPackage() { exists(DataFlow::SourceNode callee | callee = getAValueExportedByPackage().(DataFlow::NewNode).getCalleeNode().getALocalSource() | - result = callee.getAPropertyRead("prototype").getAPropertyWrite().getRhs() + result = callee.getAPropertyRead("prototype").getAPropertyWrite(publicPropertyName()).getRhs() or - result = callee.(DataFlow::ClassNode).getAnInstanceMethod() + result = callee.(DataFlow::ClassNode).getInstanceMethod(publicPropertyName()) ) or result = getAValueExportedByPackage().getALocalSource() or // Nested property reads. - result = getAValueExportedByPackage().(DataFlow::SourceNode).getAPropertyReference() + result = getAValueExportedByPackage().(DataFlow::SourceNode).getAPropertyReference(publicPropertyName()) or // module.exports.foo = require("./other-module.js"); exists(Module mod | @@ -62,8 +66,8 @@ private DataFlow::Node getAValueExportedByPackage() { // constructor() {} // <- result // }; exists(DataFlow::ClassNode cla | cla = getAValueExportedByPackage() | - result = cla.getAnInstanceMethod() or - result = cla.getAStaticMethod() or + result = cla.getInstanceMethod(publicPropertyName()) or + result = cla.getStaticMethod(publicPropertyName()) or result = cla.getConstructor() ) or @@ -120,7 +124,8 @@ private DataFlow::Node getAValueExportedByPackage() { or // Object.defineProperty exists(CallToObjectDefineProperty call | - [call, call.getBaseObject()] = getAValueExportedByPackage() + [call, call.getBaseObject()] = getAValueExportedByPackage() and + call.getPropertyName() = publicPropertyName() | result = call.getPropertyDescriptor().getALocalSource().getAPropertyReference("value") or @@ -164,9 +169,19 @@ private DataFlow::Node getAValueExportedByPackage() { * Gets an exported node from the module `mod`. */ private DataFlow::Node getAnExportFromModule(Module mod) { - result = mod.getAnExportedValue(_) + result = mod.getAnExportedValue(publicPropertyName()) or result = mod.getABulkExportedNode() or result.analyze().getAValue() = TAbstractModuleObject(mod) } + +/** + * Gets a property name that we consider to be public. + * + * This only allows properties whose first character is a letter or number. + */ +bindingset[result] +private string publicPropertyName() { + result.regexpMatch("[a-zA-Z0-9].*") +} From 600e5bad0d719348f3cd1ca499c60a90f7214528 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 1 Oct 2021 11:46:32 +0200 Subject: [PATCH 088/361] JS: Exclude methods declared private/protected --- .../lib/semmle/javascript/PackageExports.qll | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/PackageExports.qll b/javascript/ql/lib/semmle/javascript/PackageExports.qll index 17510bc214f..b8375489e15 100644 --- a/javascript/ql/lib/semmle/javascript/PackageExports.qll +++ b/javascript/ql/lib/semmle/javascript/PackageExports.qll @@ -45,7 +45,8 @@ private DataFlow::Node getAValueExportedByPackage() { | result = callee.getAPropertyRead("prototype").getAPropertyWrite(publicPropertyName()).getRhs() or - result = callee.(DataFlow::ClassNode).getInstanceMethod(publicPropertyName()) + result = callee.(DataFlow::ClassNode).getInstanceMethod(publicPropertyName()) and + not isPrivateMethodDeclaration(result) ) or result = getAValueExportedByPackage().getALocalSource() @@ -65,7 +66,10 @@ private DataFlow::Node getAValueExportedByPackage() { // static baz() {} // <- result // constructor() {} // <- result // }; - exists(DataFlow::ClassNode cla | cla = getAValueExportedByPackage() | + exists(DataFlow::ClassNode cla | + cla = getAValueExportedByPackage() and + not isPrivateMethodDeclaration(result) + | result = cla.getInstanceMethod(publicPropertyName()) or result = cla.getStaticMethod(publicPropertyName()) or result = cla.getConstructor() @@ -185,3 +189,17 @@ bindingset[result] private string publicPropertyName() { result.regexpMatch("[a-zA-Z0-9].*") } + +/** + * Holds if the given function is part of a private (or protected) method declaration. + */ +private predicate isPrivateMethodDeclaration(DataFlow::FunctionNode func) { + exists(MethodDeclaration decl | + decl.getBody() = func.getFunction() and + ( + decl.isPrivate() + or + decl.isProtected() + ) + ) +} From c8e7df79006012344452e9f9422cc6b7ebadcee6 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 1 Oct 2021 12:02:40 +0200 Subject: [PATCH 089/361] JS: Add test case --- .../ql/test/library-tests/PackageExports/notPublic.ts | 11 +++++++++++ .../test/library-tests/PackageExports/tests.expected | 1 + 2 files changed, 12 insertions(+) create mode 100644 javascript/ql/test/library-tests/PackageExports/notPublic.ts diff --git a/javascript/ql/test/library-tests/PackageExports/notPublic.ts b/javascript/ql/test/library-tests/PackageExports/notPublic.ts new file mode 100644 index 00000000000..b5ca23574b1 --- /dev/null +++ b/javascript/ql/test/library-tests/PackageExports/notPublic.ts @@ -0,0 +1,11 @@ +export class PublicClass { + protected constructor(p) {} + private privateMethod(p) {} + protected protectedMethod(p) {} + _kindaPrivateMethod(p) {} + $kindaPrivateMethod(p) {} + #esPrivateMethod(p) {} + + _kindaPrivateFieldMethod = (p) => {}; + private privateFieldMethod = (p) => {}; +} diff --git a/javascript/ql/test/library-tests/PackageExports/tests.expected b/javascript/ql/test/library-tests/PackageExports/tests.expected index 1d46e149521..e4ed532c708 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.expected +++ b/javascript/ql/test/library-tests/PackageExports/tests.expected @@ -15,3 +15,4 @@ getAnExportedValue | lib1/reexport/a.js:1:1:3:1 | <toplevel> | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | | lib1/reexport/b.js:1:1:6:1 | <toplevel> | base | lib1/reexport/b.js:4:11:4:28 | function base() {} | | lib1/reexport/b.js:1:1:6:1 | <toplevel> | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | +| notPublic.ts:1:1:12:0 | <toplevel> | PublicClass | notPublic.ts:1:8:11:1 | class P ... > {};\\n} | From d4f1a9602fc6501cb6d3bdbf3e2f45d3d158f300 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Fri, 1 Oct 2021 13:03:50 +0200 Subject: [PATCH 090/361] Dataflow: Force high precision of certain Contents. --- .../java/dataflow/internal/DataFlowImpl.qll | 18 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 7 +++++++ .../java/dataflow/internal/DataFlowPrivate.qll | 6 ++++++ 3 files changed, 24 insertions(+), 7 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 e04d3b0edc6..4ca06c93362 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** 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 f588a25a176..e8ebb3f5e96 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -1236,6 +1236,13 @@ class TypedContent extends MkTypedContent { /** Gets a textual representation of this content. */ string toString() { result = c.toString() } + + /** + * Holds if accesspaths with this `TypedContent` at their head always should + * be tracked at high precision. This disables adaptive accesspath precision + * for such accesspaths. + */ + predicate forceHighPrecision() { forceHighPrecision(c) } } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 1d24e027869..a2bc204591d 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -308,6 +308,12 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { int accessPathLimit() { result = 5 } +/** + * Holds if accesspaths with `c` at their head always should be tracked at high + * precision. This disables adaptive accesspath precision for such accesspaths. + */ +predicate forceHighPrecision(Content c) { c instanceof ArrayContent or c instanceof CollectionContent } + /** * Holds if `n` does not require a `PostUpdateNode` as it either cannot be * modified or its modification cannot be observed, for example if it is a From 490df2027be9a6c80a7ee0c93ff58f9589c7ee2f Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Fri, 1 Oct 2021 13:11:14 +0200 Subject: [PATCH 091/361] Dataflow: Add language-specific predicate forceHighPrecision(). --- .../semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll | 6 ++++++ .../code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 6 ++++++ .../code/csharp/dataflow/internal/DataFlowPrivate.qll | 6 ++++++ .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index e64f8277528..338aa73ce86 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -240,6 +240,12 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl int accessPathLimit() { result = 5 } +/** + * Holds if accesspaths with `c` at their head always should be tracked at high + * precision. This disables adaptive accesspath precision for such accesspaths. + */ +predicate forceHighPrecision(Content c) { none() } + /** The unit type. */ private newtype TUnit = TMkUnit() 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 73bf72a3643..945ee2766fb 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 @@ -466,6 +466,12 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl int accessPathLimit() { result = 5 } +/** + * Holds if accesspaths with `c` at their head always should be tracked at high + * precision. This disables adaptive accesspath precision for such accesspaths. + */ +predicate forceHighPrecision(Content c) { none() } + /** The unit type. */ private newtype TUnit = TMkUnit() diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index ca4d0fa98e7..a164008e402 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1918,6 +1918,12 @@ private predicate viableConstantBooleanParamArg( int accessPathLimit() { result = 5 } +/** + * Holds if accesspaths with `c` at their head always should be tracked at high + * precision. This disables adaptive accesspath precision for such accesspaths. + */ +predicate forceHighPrecision(Content c) { c instanceof ElementContent } + /** The unit type. */ private newtype TUnit = TMkUnit() 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 44c64234b75..7c662b6249a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1620,6 +1620,12 @@ predicate isImmutableOrUnobservable(Node n) { none() } int accessPathLimit() { result = 5 } +/** + * Holds if accesspaths with `c` at their head always should be tracked at high + * precision. This disables adaptive accesspath precision for such accesspaths. + */ +predicate forceHighPrecision(Content c) { none() } + /** Holds if `n` should be hidden from path explanations. */ predicate nodeIsHidden(Node n) { none() } From 98f68cb053bdb4f9ad6999113b42627e6f111712 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Fri, 1 Oct 2021 13:11:43 +0200 Subject: [PATCH 092/361] Dataflow: Sync. --- .../cpp/dataflow/internal/DataFlowImpl.qll | 18 +++++++++++------- .../cpp/dataflow/internal/DataFlowImpl2.qll | 18 +++++++++++------- .../cpp/dataflow/internal/DataFlowImpl3.qll | 18 +++++++++++------- .../cpp/dataflow/internal/DataFlowImpl4.qll | 18 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 7 +++++++ .../dataflow/internal/DataFlowImplLocal.qll | 18 +++++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 18 +++++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl2.qll | 18 +++++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl3.qll | 18 +++++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl4.qll | 18 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 7 +++++++ .../csharp/dataflow/internal/DataFlowImpl.qll | 18 +++++++++++------- .../csharp/dataflow/internal/DataFlowImpl2.qll | 18 +++++++++++------- .../csharp/dataflow/internal/DataFlowImpl3.qll | 18 +++++++++++------- .../csharp/dataflow/internal/DataFlowImpl4.qll | 18 +++++++++++------- .../csharp/dataflow/internal/DataFlowImpl5.qll | 18 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 7 +++++++ .../java/dataflow/internal/DataFlowImpl2.qll | 18 +++++++++++------- .../java/dataflow/internal/DataFlowImpl3.qll | 18 +++++++++++------- .../java/dataflow/internal/DataFlowImpl4.qll | 18 +++++++++++------- .../java/dataflow/internal/DataFlowImpl5.qll | 18 +++++++++++------- .../java/dataflow/internal/DataFlowImpl6.qll | 18 +++++++++++------- .../DataFlowImplForSerializability.qll | 18 +++++++++++------- .../dataflow/new/internal/DataFlowImpl.qll | 18 +++++++++++------- .../dataflow/new/internal/DataFlowImpl2.qll | 18 +++++++++++------- .../dataflow/new/internal/DataFlowImpl3.qll | 18 +++++++++++------- .../dataflow/new/internal/DataFlowImpl4.qll | 18 +++++++++++------- .../new/internal/DataFlowImplCommon.qll | 7 +++++++ 28 files changed, 292 insertions(+), 168 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 e04d3b0edc6..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index e04d3b0edc6..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index e04d3b0edc6..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index e04d3b0edc6..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** 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 f588a25a176..e8ebb3f5e96 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -1236,6 +1236,13 @@ class TypedContent extends MkTypedContent { /** Gets a textual representation of this content. */ string toString() { result = c.toString() } + + /** + * Holds if accesspaths with this `TypedContent` at their head always should + * be tracked at high precision. This disables adaptive accesspath precision + * for such accesspaths. + */ + predicate forceHighPrecision() { forceHighPrecision(c) } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index e04d3b0edc6..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** 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 e04d3b0edc6..4ca06c93362 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 @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index e04d3b0edc6..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index e04d3b0edc6..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index e04d3b0edc6..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** 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 f588a25a176..e8ebb3f5e96 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 @@ -1236,6 +1236,13 @@ class TypedContent extends MkTypedContent { /** Gets a textual representation of this content. */ string toString() { result = c.toString() } + + /** + * Holds if accesspaths with this `TypedContent` at their head always should + * be tracked at high precision. This disables adaptive accesspath precision + * for such accesspaths. + */ + predicate forceHighPrecision() { forceHighPrecision(c) } } /** 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 e04d3b0edc6..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index e04d3b0edc6..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index e04d3b0edc6..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index e04d3b0edc6..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index e04d3b0edc6..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** 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 f588a25a176..e8ebb3f5e96 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -1236,6 +1236,13 @@ class TypedContent extends MkTypedContent { /** Gets a textual representation of this content. */ string toString() { result = c.toString() } + + /** + * Holds if accesspaths with this `TypedContent` at their head always should + * be tracked at high precision. This disables adaptive accesspath precision + * for such accesspaths. + */ + predicate forceHighPrecision() { forceHighPrecision(c) } } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index e04d3b0edc6..4ca06c93362 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index e04d3b0edc6..4ca06c93362 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index e04d3b0edc6..4ca06c93362 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index e04d3b0edc6..4ca06c93362 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index e04d3b0edc6..4ca06c93362 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index e04d3b0edc6..4ca06c93362 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** 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 e04d3b0edc6..4ca06c93362 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index e04d3b0edc6..4ca06c93362 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index e04d3b0edc6..4ca06c93362 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index e04d3b0edc6..4ca06c93362 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and - tupleLimit < (tails - 1) * nodes + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } @@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } /** 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 f588a25a176..e8ebb3f5e96 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -1236,6 +1236,13 @@ class TypedContent extends MkTypedContent { /** Gets a textual representation of this content. */ string toString() { result = c.toString() } + + /** + * Holds if accesspaths with this `TypedContent` at their head always should + * be tracked at high precision. This disables adaptive accesspath precision + * for such accesspaths. + */ + predicate forceHighPrecision() { forceHighPrecision(c) } } /** From 6359c44622efee45273285af80baa9fa97db4a47 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Fri, 1 Oct 2021 14:05:47 +0200 Subject: [PATCH 093/361] Java: Autoformat. --- .../semmle/code/java/dataflow/internal/DataFlowPrivate.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index a2bc204591d..0e21aaa64cd 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -312,7 +312,9 @@ int accessPathLimit() { result = 5 } * Holds if accesspaths with `c` at their head always should be tracked at high * precision. This disables adaptive accesspath precision for such accesspaths. */ -predicate forceHighPrecision(Content c) { c instanceof ArrayContent or c instanceof CollectionContent } +predicate forceHighPrecision(Content c) { + c instanceof ArrayContent or c instanceof CollectionContent +} /** * Holds if `n` does not require a `PostUpdateNode` as it either cannot be From 74957dcb2edbd4a6b144b4fb29277d354febfbfa Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 10:30:07 +0100 Subject: [PATCH 094/361] C++: Test spacing. --- .../ImproperNullTermination.expected | 48 ++++++++-------- .../ImproperNullTerminationTainted.expected | 4 +- .../ImproperNullTermination/test.cpp | 56 +++++++++++++++++++ 3 files changed, 82 insertions(+), 26 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected index b8f5c71e8e2..4ffa8b7ebe9 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected @@ -1,25 +1,25 @@ -| test.cpp:25:10:25:16 | buffer1 | Variable $@ may not be null terminated. | test.cpp:22:8:22:14 | buffer1 | buffer1 | -| test.cpp:26:10:26:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:23:8:23:14 | buffer2 | buffer2 | -| test.cpp:39:10:39:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:35:8:35:14 | buffer2 | buffer2 | -| test.cpp:59:10:59:13 | ptr1 | Variable $@ may not be null terminated. | test.cpp:56:9:56:12 | ptr1 | ptr1 | -| test.cpp:69:10:69:16 | buffer1 | Variable $@ may not be null terminated. | test.cpp:64:8:64:14 | buffer1 | buffer1 | -| test.cpp:70:10:70:12 | ptr | Variable $@ may not be null terminated. | test.cpp:64:8:64:14 | buffer1 | buffer1 | -| test.cpp:81:10:81:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:65:8:65:14 | buffer2 | buffer2 | -| test.cpp:82:10:82:12 | ptr | Variable $@ may not be null terminated. | test.cpp:65:8:65:14 | buffer2 | buffer2 | -| test.cpp:93:10:93:15 | buffer | Variable $@ may not be null terminated. | test.cpp:86:8:86:13 | buffer | buffer | -| test.cpp:116:10:116:15 | buffer | Variable $@ may not be null terminated. | test.cpp:109:8:109:13 | buffer | buffer | -| test.cpp:130:14:130:19 | buffer | Variable $@ may not be null terminated. | test.cpp:127:7:127:12 | buffer | buffer | -| test.cpp:139:10:139:15 | buffer | Variable $@ may not be null terminated. | test.cpp:136:8:136:13 | buffer | buffer | -| test.cpp:147:14:147:19 | buffer | Variable $@ may not be null terminated. | test.cpp:143:8:143:13 | buffer | buffer | -| test.cpp:182:10:182:15 | buffer | Variable $@ may not be null terminated. | test.cpp:178:8:178:13 | buffer | buffer | -| test.cpp:234:10:234:15 | buffer | Variable $@ may not be null terminated. | test.cpp:232:8:232:13 | buffer | buffer | -| test.cpp:262:10:262:15 | buffer | Variable $@ may not be null terminated. | test.cpp:259:8:259:13 | buffer | buffer | -| test.cpp:283:10:283:15 | buffer | Variable $@ may not be null terminated. | test.cpp:280:8:280:13 | buffer | buffer | -| test.cpp:300:10:300:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:295:8:295:14 | buffer2 | buffer2 | -| test.cpp:312:10:312:15 | buffer | Variable $@ may not be null terminated. | test.cpp:308:8:308:13 | buffer | buffer | -| test.cpp:327:18:327:23 | buffer | Variable $@ may not be null terminated. | test.cpp:326:8:326:13 | buffer | buffer | -| test.cpp:346:11:346:16 | buffer | Variable $@ may not be null terminated. | test.cpp:341:8:341:13 | buffer | buffer | +| test.cpp:26:10:26:16 | buffer1 | Variable $@ may not be null terminated. | test.cpp:23:8:23:14 | buffer1 | buffer1 | +| test.cpp:27:10:27:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:24:8:24:14 | buffer2 | buffer2 | +| test.cpp:40:10:40:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:36:8:36:14 | buffer2 | buffer2 | +| test.cpp:60:10:60:13 | ptr1 | Variable $@ may not be null terminated. | test.cpp:57:9:57:12 | ptr1 | ptr1 | +| test.cpp:70:10:70:16 | buffer1 | Variable $@ may not be null terminated. | test.cpp:65:8:65:14 | buffer1 | buffer1 | +| test.cpp:71:10:71:12 | ptr | Variable $@ may not be null terminated. | test.cpp:65:8:65:14 | buffer1 | buffer1 | +| test.cpp:82:10:82:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:66:8:66:14 | buffer2 | buffer2 | +| test.cpp:83:10:83:12 | ptr | Variable $@ may not be null terminated. | test.cpp:66:8:66:14 | buffer2 | buffer2 | +| test.cpp:94:10:94:15 | buffer | Variable $@ may not be null terminated. | test.cpp:87:8:87:13 | buffer | buffer | +| test.cpp:117:10:117:15 | buffer | Variable $@ may not be null terminated. | test.cpp:110:8:110:13 | buffer | buffer | +| test.cpp:131:14:131:19 | buffer | Variable $@ may not be null terminated. | test.cpp:128:7:128:12 | buffer | buffer | +| test.cpp:140:10:140:15 | buffer | Variable $@ may not be null terminated. | test.cpp:137:8:137:13 | buffer | buffer | +| test.cpp:148:14:148:19 | buffer | Variable $@ may not be null terminated. | test.cpp:144:8:144:13 | buffer | buffer | +| test.cpp:183:10:183:15 | buffer | Variable $@ may not be null terminated. | test.cpp:179:8:179:13 | buffer | buffer | +| test.cpp:236:10:236:15 | buffer | Variable $@ may not be null terminated. | test.cpp:234:8:234:13 | buffer | buffer | +| test.cpp:264:10:264:15 | buffer | Variable $@ may not be null terminated. | test.cpp:261:8:261:13 | buffer | buffer | +| test.cpp:285:10:285:15 | buffer | Variable $@ may not be null terminated. | test.cpp:282:8:282:13 | buffer | buffer | +| test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 | +| test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer | +| test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer | | test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer | -| test.cpp:365:19:365:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:363:8:363:14 | buffer2 | buffer2 | -| test.cpp:392:17:392:22 | buffer | Variable $@ may not be null terminated. | test.cpp:390:8:390:13 | buffer | buffer | -| test.cpp:398:18:398:23 | buffer | Variable $@ may not be null terminated. | test.cpp:396:8:396:13 | buffer | buffer | +| test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer | +| test.cpp:421:19:421:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:419:8:419:14 | buffer2 | buffer2 | +| test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer | +| test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTerminationTainted.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTerminationTainted.expected index 3bf8c4d3652..b0a0d6cbb66 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTerminationTainted.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTerminationTainted.expected @@ -1,2 +1,2 @@ -| test.cpp:410:10:410:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:409:18:409:23 | buffer | User-provided value | -| test.cpp:425:10:425:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:424:9:424:14 | buffer | User-provided value | +| test.cpp:466:10:466:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:465:18:465:23 | buffer | User-provided value | +| test.cpp:481:10:481:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:480:9:480:14 | buffer | User-provided value | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp index 7fa4ef60093..f34be96fc33 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp @@ -6,6 +6,7 @@ size_t strlen(const char *s); char *strcpy(char *s1, const char *s2); char *strcat(char *s1, const char *s2); char *strdup(const char *s1); + void *malloc(size_t size); void *memset(void *s, int c, size_t n); void *memcpy(void *s1, const void *s2, size_t n); @@ -226,6 +227,7 @@ void doNothing(char *data) { }; void doNothing2(const char *data); void clearBuffer(char *data, size_t size); + void test_strcat() { { @@ -318,6 +320,13 @@ void test_strcat() clearBuffer(buffer, 1024); strcat(buffer, "content"); // GOOD } + + + + + + + } void test_strlen(bool cond1, bool cond2) @@ -354,6 +363,53 @@ void test_strlen(bool cond1, bool cond2) if (cond2) strlen(buffer); // BAD } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } void test_strcpy() From ec2e4f432a724c11f5bbec8b55f36b351cbfcc06 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 14:03:41 +0100 Subject: [PATCH 095/361] C++: Add more test cases, inspired by FPs on LGTM with the query. --- .../ImproperNullTermination.expected | 4 + .../ImproperNullTermination/test.cpp | 103 ++++++++++-------- 2 files changed, 62 insertions(+), 45 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected index 4ffa8b7ebe9..fe40f764f5c 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected @@ -17,9 +17,13 @@ | test.cpp:285:10:285:15 | buffer | Variable $@ may not be null terminated. | test.cpp:282:8:282:13 | buffer | buffer | | test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 | | test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer | +| test.cpp:328:10:328:15 | buffer | Variable $@ may not be null terminated. | test.cpp:325:8:325:13 | buffer | buffer | | test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer | | test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer | | test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer | +| test.cpp:392:11:392:16 | buffer | Variable $@ may not be null terminated. | test.cpp:381:8:381:13 | buffer | buffer | +| test.cpp:410:11:410:16 | buffer | Variable $@ may not be null terminated. | test.cpp:397:8:397:13 | buffer | buffer | | test.cpp:421:19:421:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:419:8:419:14 | buffer2 | buffer2 | | test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer | | test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer | +| test.cpp:502:10:502:18 | after_ptr | Variable $@ may not be null terminated. | test.cpp:497:9:497:17 | after_ptr | after_ptr | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp index f34be96fc33..74055352ae7 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp @@ -6,7 +6,7 @@ size_t strlen(const char *s); char *strcpy(char *s1, const char *s2); char *strcat(char *s1, const char *s2); char *strdup(const char *s1); - +long int strtol(const char* nptr, char** endptr, int base); void *malloc(size_t size); void *memset(void *s, int c, size_t n); void *memcpy(void *s1, const void *s2, size_t n); @@ -226,7 +226,7 @@ void test_readlink(int fd, const char *path, size_t sz) void doNothing(char *data) { }; void doNothing2(const char *data); void clearBuffer(char *data, size_t size); - +char *id(char *data) { return data; } void test_strcat() { @@ -321,12 +321,12 @@ void test_strcat() strcat(buffer, "content"); // GOOD } + { + char buffer[1024]; - - - - - + clearBuffer(id(buffer), 1024); + strcat(buffer, "content"); // GOOD [FALSE POSITIVE] + } } void test_strlen(bool cond1, bool cond2) @@ -364,52 +364,52 @@ void test_strlen(bool cond1, bool cond2) strlen(buffer); // BAD } + { + char buffer[1024]; + if (cond1) + { + buffer[0] = 0; + } else { + buffer[0] = 0; + } + strlen(buffer); // GOOD + } + { + char buffer[1024]; + int init = 0; + if (cond1) + { + buffer[0] = 0; + init = 1; + } + if (init != 0) + { + strlen(buffer); // GOOD [FALSE POSITIVE] + } + } + { + char buffer[1024]; + int init = 0; + if (cond1) + { + buffer[0] = 0; + init = 1; + } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + if (init == 0) + { + // ... + } else { + strlen(buffer); // GOOD [FALSE POSITIVE] + } + } } void test_strcpy() @@ -489,3 +489,16 @@ void test_read_fread(int read_src, FILE *s) strlen(buffer); // GOOD } } + +void test_strtol() +{ + { + char buffer[100]; + char *after_ptr; + long int num; + + strcpy(buffer, "123abc"); + num = strtol("123abc", &after_ptr, 10); + strlen(after_ptr); // GOOD [FALSE POSITIVE] + } +} From d41e5177572a3d9e2dea94572e223722e6ad3cc0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 10:44:42 +0100 Subject: [PATCH 096/361] C++: Simplify mayAddNullTerminator. --- cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll index 6cb366d46ee..caf3e42e80a 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll @@ -54,7 +54,7 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) { not functionArgumentMustBeNullTerminated(f, i) and c.getAnArgumentSubExpr(i) = va | - not f.hasEntryPoint() and not functionArgumentMustBeNullTerminated(f, i) + not f.hasEntryPoint() or mayAddNullTerminator(_, f.getParameter(i).getAnAccess()) or From 11d7a0b7124300654d65fcc2418b06f5581e8578 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 14:37:41 +0100 Subject: [PATCH 097/361] C++: Exclude results where the address of the variable is taken. --- .../Likely Bugs/Memory Management/ImproperNullTermination.ql | 1 + .../ImproperNullTermination/ImproperNullTermination.expected | 1 - .../Memory Management/ImproperNullTermination/test.cpp | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql index 2e643070a19..ed378dce60a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql @@ -53,6 +53,7 @@ class ImproperNullTerminationReachability extends StackVariableReachabilityWithR override predicate isBarrier(ControlFlowNode node, StackVariable v) { exprDefinition(v, node, _) or mayAddNullTerminator(node, v.getAnAccess()) or + node.(AddressOfExpr).getOperand() = v.getAnAccess() or // address taken isSinkActual(node, v) // only report first use } } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected index fe40f764f5c..5842ac17238 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected @@ -26,4 +26,3 @@ | test.cpp:421:19:421:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:419:8:419:14 | buffer2 | buffer2 | | test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer | | test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer | -| test.cpp:502:10:502:18 | after_ptr | Variable $@ may not be null terminated. | test.cpp:497:9:497:17 | after_ptr | after_ptr | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp index 74055352ae7..140d578362b 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp @@ -499,6 +499,6 @@ void test_strtol() strcpy(buffer, "123abc"); num = strtol("123abc", &after_ptr, 10); - strlen(after_ptr); // GOOD [FALSE POSITIVE] + strlen(after_ptr); // GOOD } } From ebe0988d9afb06ccd9bd63b6abeedacc8a816fea Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 1 Oct 2021 16:30:56 +0200 Subject: [PATCH 098/361] Let 'ql/lib' folders trigger the CSV workflow --- .github/workflows/csv-coverage-pr-artifacts.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/csv-coverage-pr-artifacts.yml b/.github/workflows/csv-coverage-pr-artifacts.yml index 201eea5c073..8b89b9b22c1 100644 --- a/.github/workflows/csv-coverage-pr-artifacts.yml +++ b/.github/workflows/csv-coverage-pr-artifacts.yml @@ -6,6 +6,8 @@ on: - '.github/workflows/csv-coverage-pr-comment.yml' - '*/ql/src/**/*.ql' - '*/ql/src/**/*.qll' + - '*/ql/lib/**/*.ql' + - '*/ql/lib/**/*.qll' - 'misc/scripts/library-coverage/*.py' # input data files - '*/documentation/library-coverage/cwe-sink.csv' From 99ba80d492894dfa78043674bda64ebf553d4b14 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Fri, 1 Oct 2021 16:57:30 +0200 Subject: [PATCH 099/361] C#: Adjust test output. --- .../dataflow/external-models/ExternalFlow.expected | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected index 62af20beb18..ecc6b95c817 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected @@ -45,6 +45,9 @@ edges | ExternalFlow.cs:91:30:91:30 | SSA def(i) : Int32 | ExternalFlow.cs:92:18:92:18 | (...) ... | | ExternalFlow.cs:121:46:121:46 | s : Object | ExternalFlow.cs:60:35:60:35 | o : Object | | ExternalFlow.cs:123:34:123:41 | elements [element] : Object | ExternalFlow.cs:72:23:72:23 | o : Object | +| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | ExternalFlow.cs:72:23:72:23 | o : Object | +| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | ExternalFlow.cs:123:34:123:41 | elements [element] : Object | +| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | ExternalFlow.cs:123:34:123:41 | elements [element] : Object | nodes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | semmle.label | call to method StepArgRes | @@ -106,6 +109,7 @@ nodes | ExternalFlow.cs:92:18:92:18 | (...) ... | semmle.label | (...) ... | | ExternalFlow.cs:121:46:121:46 | s : Object | semmle.label | s : Object | | ExternalFlow.cs:123:34:123:41 | elements [element] : Object | semmle.label | elements [element] : Object | +| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | semmle.label | elements [element] : Object | subpaths invalidModelRow #select From ada30800c94edd0bb824ab0554426f91fd3d37c1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 16:16:06 +0100 Subject: [PATCH 100/361] C++: Exclude results where identity-like functions obscure operations on a variable. --- .../lib/semmle/code/cpp/commons/NullTermination.qll | 11 ++++++++--- .../ImproperNullTermination.expected | 1 - .../ImproperNullTermination/test.cpp | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll index caf3e42e80a..42c9fa01f89 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll @@ -45,22 +45,27 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) { ae.getRValue().getAChild*() = va ) or - // Function call: library function, varargs function, function - // containing assembler code, or function where the relevant - // parameter is potentially added a null terminator. + // Function calls... exists(Call c, Function f, int i | e = c and f = c.getTarget() and not functionArgumentMustBeNullTerminated(f, i) and c.getAnArgumentSubExpr(i) = va | + // library function not f.hasEntryPoint() or + // function where the relevant parameter is potentially added a null terminator mayAddNullTerminator(_, f.getParameter(i).getAnAccess()) or + // varargs function f.isVarargs() and i >= f.getNumberOfParameters() or + // function containing assembler code exists(AsmStmt s | s.getEnclosingFunction() = f) + or + // function where the relevant parameter is returned (leaking it) + exists(ReturnStmt rs | rs.getEnclosingFunction() = f and rs.getExpr().getAChild*() = f.getParameter(i).getAnAccess()) ) or // Call without target (e.g., function pointer call) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected index 5842ac17238..bb0580051e7 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected @@ -17,7 +17,6 @@ | test.cpp:285:10:285:15 | buffer | Variable $@ may not be null terminated. | test.cpp:282:8:282:13 | buffer | buffer | | test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 | | test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer | -| test.cpp:328:10:328:15 | buffer | Variable $@ may not be null terminated. | test.cpp:325:8:325:13 | buffer | buffer | | test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer | | test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer | | test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp index 140d578362b..fb355498caf 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp @@ -325,7 +325,7 @@ void test_strcat() char buffer[1024]; clearBuffer(id(buffer), 1024); - strcat(buffer, "content"); // GOOD [FALSE POSITIVE] + strcat(buffer, "content"); // GOOD } } From bb6e6f4808b0354e72001136f4d6d2aa226fa0df Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:24:40 +0200 Subject: [PATCH 101/361] Java: Split literals tests This allows changing individual tests in the future without having to adjust the expected output of all other tests. --- .../booleanLiterals/BooleanLiterals.java | 31 ++++ .../booleanLiterals/booleanLiterals.expected | 15 ++ .../booleanLiterals.ql} | 0 .../literals/charLiterals/CharLiterals.java | 44 ++++++ .../charLiterals/charLiterals.expected | 20 +++ .../charLiterals.ql} | 0 .../doubleLiterals/DoubleLiterals.java | 50 +++++++ .../doubleLiterals/doubleLiterals.expected | 25 ++++ .../doubleLiterals.ql} | 0 .../literals/floatLiterals/FloatLiterals.java | 49 +++++++ .../floatLiterals/floatLiterals.expected | 24 +++ .../floatLiterals.ql} | 0 .../integerLiterals/IntegerLiterals.java | 57 ++++++++ .../integerLiterals/integerLiterals.expected | 30 ++++ .../integerLiterals.ql} | 0 .../literals/literalBoolean.expected | 3 - .../literals/literalChar.expected | 10 -- .../literals/literalDouble.expected | 16 -- .../literals/literalFloat.expected | 16 -- .../literals/literalInteger.expected | 20 --- .../literals/literalLong.expected | 20 --- .../literals/literalString.expected | 20 --- .../literals-numeric/NumericLiterals.java | 2 +- .../negativeNumericLiteral.expected | 0 .../negativeNumericLiterals.expected | 12 ++ .../negativeNumericLiterals.ql} | 0 .../literals/literals/Literals.java | 138 ------------------ .../literals/longLiterals/LongLiterals.java | 56 +++++++ .../longLiterals/longLiterals.expected | 30 ++++ .../longLiterals.ql} | 0 .../stringLiterals/StringLiterals.java | 59 ++++++++ .../stringLiterals/stringLiterals.expected | 33 +++++ .../stringLiterals.ql} | 0 33 files changed, 536 insertions(+), 244 deletions(-) create mode 100644 java/ql/test/library-tests/literals/booleanLiterals/BooleanLiterals.java create mode 100644 java/ql/test/library-tests/literals/booleanLiterals/booleanLiterals.expected rename java/ql/test/library-tests/literals/{literalBoolean.ql => booleanLiterals/booleanLiterals.ql} (100%) create mode 100644 java/ql/test/library-tests/literals/charLiterals/CharLiterals.java create mode 100644 java/ql/test/library-tests/literals/charLiterals/charLiterals.expected rename java/ql/test/library-tests/literals/{literalChar.ql => charLiterals/charLiterals.ql} (100%) create mode 100644 java/ql/test/library-tests/literals/doubleLiterals/DoubleLiterals.java create mode 100644 java/ql/test/library-tests/literals/doubleLiterals/doubleLiterals.expected rename java/ql/test/library-tests/literals/{literalDouble.ql => doubleLiterals/doubleLiterals.ql} (100%) create mode 100644 java/ql/test/library-tests/literals/floatLiterals/FloatLiterals.java create mode 100644 java/ql/test/library-tests/literals/floatLiterals/floatLiterals.expected rename java/ql/test/library-tests/literals/{literalFloat.ql => floatLiterals/floatLiterals.ql} (100%) create mode 100644 java/ql/test/library-tests/literals/integerLiterals/IntegerLiterals.java create mode 100644 java/ql/test/library-tests/literals/integerLiterals/integerLiterals.expected rename java/ql/test/library-tests/literals/{literalInteger.ql => integerLiterals/integerLiterals.ql} (100%) delete mode 100644 java/ql/test/library-tests/literals/literalBoolean.expected delete mode 100644 java/ql/test/library-tests/literals/literalChar.expected delete mode 100644 java/ql/test/library-tests/literals/literalDouble.expected delete mode 100644 java/ql/test/library-tests/literals/literalFloat.expected delete mode 100644 java/ql/test/library-tests/literals/literalInteger.expected delete mode 100644 java/ql/test/library-tests/literals/literalLong.expected delete mode 100644 java/ql/test/library-tests/literals/literalString.expected rename java/ql/test/library-tests/{ => literals}/literals-numeric/NumericLiterals.java (95%) rename java/ql/test/library-tests/{ => literals}/literals-numeric/negativeNumericLiteral.expected (100%) create mode 100644 java/ql/test/library-tests/literals/literals-numeric/negativeNumericLiterals.expected rename java/ql/test/library-tests/{literals-numeric/negativeNumericLiteral.ql => literals/literals-numeric/negativeNumericLiterals.ql} (100%) delete mode 100644 java/ql/test/library-tests/literals/literals/Literals.java create mode 100644 java/ql/test/library-tests/literals/longLiterals/LongLiterals.java create mode 100644 java/ql/test/library-tests/literals/longLiterals/longLiterals.expected rename java/ql/test/library-tests/literals/{literalLong.ql => longLiterals/longLiterals.ql} (100%) create mode 100644 java/ql/test/library-tests/literals/stringLiterals/StringLiterals.java create mode 100644 java/ql/test/library-tests/literals/stringLiterals/stringLiterals.expected rename java/ql/test/library-tests/literals/{literalString.ql => stringLiterals/stringLiterals.ql} (100%) diff --git a/java/ql/test/library-tests/literals/booleanLiterals/BooleanLiterals.java b/java/ql/test/library-tests/literals/booleanLiterals/BooleanLiterals.java new file mode 100644 index 00000000000..feff9a908e4 --- /dev/null +++ b/java/ql/test/library-tests/literals/booleanLiterals/BooleanLiterals.java @@ -0,0 +1,31 @@ +package booleanLiterals; + +public class BooleanLiterals { + boolean[] booleans = { + true, + false, + // Using Unicode escapes (which are handled during pre-processing) + \u0074\u0072\u0075\u0065, // true + }; + + // The operation expression (e.g. `&&`) is not a literal + boolean[] logicOperations = { + true && true, + false && false, + true && false, + true || true, + false || false, + true || false, + }; + + Object[] nonBooleanLiterals = { + "true", + "false", + 1, + 0, + Boolean.TRUE, + Boolean.FALSE, + }; + + boolean nonLiteral; +} diff --git a/java/ql/test/library-tests/literals/booleanLiterals/booleanLiterals.expected b/java/ql/test/library-tests/literals/booleanLiterals/booleanLiterals.expected new file mode 100644 index 00000000000..75acbb8d07f --- /dev/null +++ b/java/ql/test/library-tests/literals/booleanLiterals/booleanLiterals.expected @@ -0,0 +1,15 @@ +| BooleanLiterals.java:5:3:5:6 | true | true | true | +| BooleanLiterals.java:6:3:6:7 | false | false | false | +| BooleanLiterals.java:8:8:8:26 | 4\\u0072\\u0075\\u0065 | true | true | +| BooleanLiterals.java:13:3:13:6 | true | true | true | +| BooleanLiterals.java:13:11:13:14 | true | true | true | +| BooleanLiterals.java:14:3:14:7 | false | false | false | +| BooleanLiterals.java:14:12:14:16 | false | false | false | +| BooleanLiterals.java:15:3:15:6 | true | true | true | +| BooleanLiterals.java:15:11:15:15 | false | false | false | +| BooleanLiterals.java:16:3:16:6 | true | true | true | +| BooleanLiterals.java:16:11:16:14 | true | true | true | +| BooleanLiterals.java:17:3:17:7 | false | false | false | +| BooleanLiterals.java:17:12:17:16 | false | false | false | +| BooleanLiterals.java:18:3:18:6 | true | true | true | +| BooleanLiterals.java:18:11:18:15 | false | false | false | diff --git a/java/ql/test/library-tests/literals/literalBoolean.ql b/java/ql/test/library-tests/literals/booleanLiterals/booleanLiterals.ql similarity index 100% rename from java/ql/test/library-tests/literals/literalBoolean.ql rename to java/ql/test/library-tests/literals/booleanLiterals/booleanLiterals.ql diff --git a/java/ql/test/library-tests/literals/charLiterals/CharLiterals.java b/java/ql/test/library-tests/literals/charLiterals/CharLiterals.java new file mode 100644 index 00000000000..51274f9899e --- /dev/null +++ b/java/ql/test/library-tests/literals/charLiterals/CharLiterals.java @@ -0,0 +1,44 @@ +package charLiterals; + +public class CharLiterals { + char[] chars = { + 'a', + '\u0061', // 'a' + '\u0000', + '\uFFFF', + '\ufFfF', + '\0', + '\n', + '"', + '\\', + '\'', + '\123', // octal escape sequence for 'S' + '\uD800', // high surrogate + '\uDC00', // low surrogate + // Using Unicode escapes (which are handled during pre-processing) + '\u005C\u005C', // escaped backslash + '\u005C\u0027', // escaped single quote + \u0027a\u0027, // 'a' + }; + + // + and - are not part of the literal + int[] charsWithSign = { + +'a', + -'a', + }; + + // The operation expression (e.g. `+`) is not a literal + int[] numericOperations = { + 'a' + 'b', + }; + + Object[] nonCharLiterals = { + "a", + "", + "\uD800\uDC00", // surrogate pair + 0, + Character.MIN_VALUE, + }; + + char nonLiteral; +} diff --git a/java/ql/test/library-tests/literals/charLiterals/charLiterals.expected b/java/ql/test/library-tests/literals/charLiterals/charLiterals.expected new file mode 100644 index 00000000000..987f7c17fe4 --- /dev/null +++ b/java/ql/test/library-tests/literals/charLiterals/charLiterals.expected @@ -0,0 +1,20 @@ +| CharLiterals.java:5:3:5:5 | 'a' | a | +| CharLiterals.java:6:3:6:10 | '\\u0061' | a | +| CharLiterals.java:7:3:7:10 | '\\u0000' | \u0000 | +| CharLiterals.java:8:3:8:10 | '\\uFFFF' | \uffff | +| CharLiterals.java:9:3:9:10 | '\\ufFfF' | \uffff | +| CharLiterals.java:10:3:10:6 | '\\0' | \u0000 | +| CharLiterals.java:11:3:11:6 | '\\n' | \n | +| CharLiterals.java:12:3:12:5 | '"' | " | +| CharLiterals.java:13:3:13:6 | '\\\\' | \\ | +| CharLiterals.java:14:3:14:6 | '\\'' | ' | +| CharLiterals.java:15:3:15:8 | '\\123' | S | +| CharLiterals.java:16:3:16:10 | '\\uD800' | \ufffd | +| CharLiterals.java:17:3:17:10 | '\\uDC00' | \ufffd | +| CharLiterals.java:19:3:19:16 | '\\u005C\\u005C' | \\ | +| CharLiterals.java:20:3:20:16 | '\\u005C\\u0027' | ' | +| CharLiterals.java:21:8:21:15 | 7a\\u0027 | a | +| CharLiterals.java:26:4:26:6 | 'a' | a | +| CharLiterals.java:27:4:27:6 | 'a' | a | +| CharLiterals.java:32:3:32:5 | 'a' | a | +| CharLiterals.java:32:9:32:11 | 'b' | b | diff --git a/java/ql/test/library-tests/literals/literalChar.ql b/java/ql/test/library-tests/literals/charLiterals/charLiterals.ql similarity index 100% rename from java/ql/test/library-tests/literals/literalChar.ql rename to java/ql/test/library-tests/literals/charLiterals/charLiterals.ql diff --git a/java/ql/test/library-tests/literals/doubleLiterals/DoubleLiterals.java b/java/ql/test/library-tests/literals/doubleLiterals/DoubleLiterals.java new file mode 100644 index 00000000000..bf437c31a6a --- /dev/null +++ b/java/ql/test/library-tests/literals/doubleLiterals/DoubleLiterals.java @@ -0,0 +1,50 @@ +package doubleLiterals; + +public class DoubleLiterals { + double[] doubles = { + 0.0, + 0d, + 0D, + .0d, + .0, + 0., + 1.234567890123456789, + 1.55555555555555555555, + // From the JLS + 1e1, + 1.7976931348623157E308, + 0x1.f_ffff_ffff_ffffP+1023, + 4.9e-324, + 0x0.0_0000_0000_0001P-1022, + 0x1.0P-1074, + // Using Unicode escapes (which are handled during pre-processing) + \u0030\u002E\u0030, // 0.0 + }; + + // + and - are not part of the literal + double[] doublesWithSign = { + +0.0, + -0.0, + +1.0, + -1.0, + +1.7976931348623157E308, + -1.7976931348623157E308, + }; + + // The operation expression (e.g. `+`) is not a literal + double[] numericOperations = { + 0.0 + 0.0, + 0.0 / 0.0, + }; + + Object[] nonDoubleLiterals = { + "0", + '0', + 0, + 0.0f, + (double) 0.0f, + Double.MIN_VALUE, + }; + + double nonLiteral; +} diff --git a/java/ql/test/library-tests/literals/doubleLiterals/doubleLiterals.expected b/java/ql/test/library-tests/literals/doubleLiterals/doubleLiterals.expected new file mode 100644 index 00000000000..574ba90a98f --- /dev/null +++ b/java/ql/test/library-tests/literals/doubleLiterals/doubleLiterals.expected @@ -0,0 +1,25 @@ +| DoubleLiterals.java:5:3:5:5 | 0.0 | 0.0 | 0.0 | +| DoubleLiterals.java:6:3:6:4 | 0d | 0.0 | 0.0 | +| DoubleLiterals.java:7:3:7:4 | 0D | 0.0 | 0.0 | +| DoubleLiterals.java:8:3:8:5 | .0d | 0.0 | 0.0 | +| DoubleLiterals.java:9:3:9:4 | .0 | 0.0 | 0.0 | +| DoubleLiterals.java:10:3:10:4 | 0. | 0.0 | 0.0 | +| DoubleLiterals.java:11:3:11:22 | 1.234567890123456789 | 1.2345678901234567 | 1.2345678901234567 | +| DoubleLiterals.java:12:3:12:24 | 1.55555555555555555555 | 1.5555555555555556 | 1.5555555555555556 | +| DoubleLiterals.java:14:3:14:5 | 1e1 | 10.0 | 10.0 | +| DoubleLiterals.java:15:3:15:24 | 1.7976931348623157E308 | 1.7976931348623157E308 | 1.7976931348623157E308 | +| DoubleLiterals.java:16:3:16:28 | 0x1.f_ffff_ffff_ffffP+1023 | 1.7976931348623157E308 | 1.7976931348623157E308 | +| DoubleLiterals.java:17:3:17:10 | 4.9e-324 | 4.9E-324 | 4.9E-324 | +| DoubleLiterals.java:18:3:18:28 | 0x0.0_0000_0000_0001P-1022 | 4.9E-324 | 4.9E-324 | +| DoubleLiterals.java:19:3:19:13 | 0x1.0P-1074 | 4.9E-324 | 4.9E-324 | +| DoubleLiterals.java:21:8:21:20 | 0\\u002E\\u0030 | 0.0 | 0.0 | +| DoubleLiterals.java:26:4:26:6 | 0.0 | 0.0 | 0.0 | +| DoubleLiterals.java:27:4:27:6 | 0.0 | 0.0 | 0.0 | +| DoubleLiterals.java:28:4:28:6 | 1.0 | 1.0 | 1.0 | +| DoubleLiterals.java:29:4:29:6 | 1.0 | 1.0 | 1.0 | +| DoubleLiterals.java:30:4:30:25 | 1.7976931348623157E308 | 1.7976931348623157E308 | 1.7976931348623157E308 | +| DoubleLiterals.java:31:4:31:25 | 1.7976931348623157E308 | 1.7976931348623157E308 | 1.7976931348623157E308 | +| DoubleLiterals.java:36:3:36:5 | 0.0 | 0.0 | 0.0 | +| DoubleLiterals.java:36:9:36:11 | 0.0 | 0.0 | 0.0 | +| DoubleLiterals.java:37:3:37:5 | 0.0 | 0.0 | 0.0 | +| DoubleLiterals.java:37:9:37:11 | 0.0 | 0.0 | 0.0 | diff --git a/java/ql/test/library-tests/literals/literalDouble.ql b/java/ql/test/library-tests/literals/doubleLiterals/doubleLiterals.ql similarity index 100% rename from java/ql/test/library-tests/literals/literalDouble.ql rename to java/ql/test/library-tests/literals/doubleLiterals/doubleLiterals.ql diff --git a/java/ql/test/library-tests/literals/floatLiterals/FloatLiterals.java b/java/ql/test/library-tests/literals/floatLiterals/FloatLiterals.java new file mode 100644 index 00000000000..fc9722d1052 --- /dev/null +++ b/java/ql/test/library-tests/literals/floatLiterals/FloatLiterals.java @@ -0,0 +1,49 @@ +package floatLiterals; + +public class FloatLiterals { + float[] floats = { + 0.0f, + 0f, + .0f, + 0.f, + 1_0_0.0f, + 1.234567890123456789f, + 1.55555555555555555555f, + // From the JLS + 1e1f, + 3.4028235e38f, + 0x1.fffffeP+127f, + 1.4e-45f, + 0x0.000002P-126f, + 0x1.0P-149f, + // Using Unicode escapes (which are handled during pre-processing) + \u0030\u002E\u0030\u0066, // 0.0f + }; + + // + and - are not part of the literal + float[] floatsWithSign = { + +0.f, + -0.f, + +1.0f, + -1.0f, + +3.4028235e38f, + -3.4028235e38f, + }; + + // The operation expression (e.g. `+`) is not a literal + float[] numericOperations = { + 0.0f + 0.0f, + 0.0f / 0.0f, + }; + + Object[] nonFloatLiterals = { + "0f", + '0', + 0, + 0.0, + (float) 0.0, + Float.MIN_VALUE, + }; + + float nonLiteral; +} diff --git a/java/ql/test/library-tests/literals/floatLiterals/floatLiterals.expected b/java/ql/test/library-tests/literals/floatLiterals/floatLiterals.expected new file mode 100644 index 00000000000..c1a499f0f52 --- /dev/null +++ b/java/ql/test/library-tests/literals/floatLiterals/floatLiterals.expected @@ -0,0 +1,24 @@ +| FloatLiterals.java:5:3:5:6 | 0.0f | 0.0 | 0.0 | +| FloatLiterals.java:6:3:6:4 | 0f | 0.0 | 0.0 | +| FloatLiterals.java:7:3:7:5 | .0f | 0.0 | 0.0 | +| FloatLiterals.java:8:3:8:5 | 0.f | 0.0 | 0.0 | +| FloatLiterals.java:9:3:9:10 | 1_0_0.0f | 100.0 | 100.0 | +| FloatLiterals.java:10:3:10:23 | 1.234567890123456789f | 1.2345679 | 1.2345679 | +| FloatLiterals.java:11:3:11:25 | 1.55555555555555555555f | 1.5555556 | 1.5555556 | +| FloatLiterals.java:13:3:13:6 | 1e1f | 10.0 | 10.0 | +| FloatLiterals.java:14:3:14:15 | 3.4028235e38f | 3.4028235E38 | 3.4028235E38 | +| FloatLiterals.java:15:3:15:18 | 0x1.fffffeP+127f | 3.4028235E38 | 3.4028235E38 | +| FloatLiterals.java:16:3:16:10 | 1.4e-45f | 1.4E-45 | 1.4E-45 | +| FloatLiterals.java:17:3:17:18 | 0x0.000002P-126f | 1.4E-45 | 1.4E-45 | +| FloatLiterals.java:18:3:18:13 | 0x1.0P-149f | 1.4E-45 | 1.4E-45 | +| FloatLiterals.java:20:8:20:26 | 0\\u002E\\u0030\\u0066 | 0.0 | 0.0 | +| FloatLiterals.java:25:4:25:6 | 0.f | 0.0 | 0.0 | +| FloatLiterals.java:26:4:26:6 | 0.f | 0.0 | 0.0 | +| FloatLiterals.java:27:4:27:7 | 1.0f | 1.0 | 1.0 | +| FloatLiterals.java:28:4:28:7 | 1.0f | 1.0 | 1.0 | +| FloatLiterals.java:29:4:29:16 | 3.4028235e38f | 3.4028235E38 | 3.4028235E38 | +| FloatLiterals.java:30:4:30:16 | 3.4028235e38f | 3.4028235E38 | 3.4028235E38 | +| FloatLiterals.java:35:3:35:6 | 0.0f | 0.0 | 0.0 | +| FloatLiterals.java:35:10:35:13 | 0.0f | 0.0 | 0.0 | +| FloatLiterals.java:36:3:36:6 | 0.0f | 0.0 | 0.0 | +| FloatLiterals.java:36:10:36:13 | 0.0f | 0.0 | 0.0 | diff --git a/java/ql/test/library-tests/literals/literalFloat.ql b/java/ql/test/library-tests/literals/floatLiterals/floatLiterals.ql similarity index 100% rename from java/ql/test/library-tests/literals/literalFloat.ql rename to java/ql/test/library-tests/literals/floatLiterals/floatLiterals.ql diff --git a/java/ql/test/library-tests/literals/integerLiterals/IntegerLiterals.java b/java/ql/test/library-tests/literals/integerLiterals/IntegerLiterals.java new file mode 100644 index 00000000000..965e3238c1f --- /dev/null +++ b/java/ql/test/library-tests/literals/integerLiterals/IntegerLiterals.java @@ -0,0 +1,57 @@ +package integerLiterals; + +public class IntegerLiterals { + int[] ints = { + 0, + 1, + 0_0, + 0___0, + 0_12, // octal + 0X012, // hex + 0xaBcDeF, // hex + 0B11, // binary + 0x80000000, + 2147483647, + -2147483648, // special case: sign is part of the literal + // From the JLS + 0x7fff_ffff, + 0177_7777_7777, // octal + 0b0111_1111_1111_1111_1111_1111_1111_1111, // binary + 0x8000_0000, + 0200_0000_0000, + 0b1000_0000_0000_0000_0000_0000_0000_0000, + 0xffff_ffff, + 0377_7777_7777, + 0b1111_1111_1111_1111_1111_1111_1111_1111, + // Using Unicode escapes (which are handled during pre-processing) + \u0030, // 0 + }; + + // + and - are not part of the literal + int[] intsWithSign = { + +0, + -0, + +1, + -1, + +2147483647, + }; + + // The operation expression (e.g. `+`) is not a literal + int[] numericOperations = { + 1 + 1, + 0 / 0, + }; + + Object[] nonIntLiterals = { + "0", + '0', + 0L, + (int) 0L, + 0.0, + (int) 0.0, + Integer.MIN_VALUE, + 'a' + 'b', // result is int 195, but this is not a literal + }; + + int nonLiteral; +} diff --git a/java/ql/test/library-tests/literals/integerLiterals/integerLiterals.expected b/java/ql/test/library-tests/literals/integerLiterals/integerLiterals.expected new file mode 100644 index 00000000000..3ff7870ca66 --- /dev/null +++ b/java/ql/test/library-tests/literals/integerLiterals/integerLiterals.expected @@ -0,0 +1,30 @@ +| IntegerLiterals.java:5:3:5:3 | 0 | 0 | 0 | +| IntegerLiterals.java:6:3:6:3 | 1 | 1 | 1 | +| IntegerLiterals.java:7:3:7:5 | 0_0 | 0 | 0 | +| IntegerLiterals.java:8:3:8:7 | 0___0 | 0 | 0 | +| IntegerLiterals.java:9:3:9:6 | 0_12 | 10 | 10 | +| IntegerLiterals.java:10:3:10:7 | 0X012 | 18 | 18 | +| IntegerLiterals.java:11:3:11:10 | 0xaBcDeF | 11259375 | 11259375 | +| IntegerLiterals.java:12:3:12:6 | 0B11 | 3 | 3 | +| IntegerLiterals.java:13:3:13:12 | 0x80000000 | -2147483648 | -2147483648 | +| IntegerLiterals.java:14:3:14:12 | 2147483647 | 2147483647 | 2147483647 | +| IntegerLiterals.java:15:3:15:13 | -2147483648 | -2147483648 | -2147483648 | +| IntegerLiterals.java:17:3:17:13 | 0x7fff_ffff | 2147483647 | 2147483647 | +| IntegerLiterals.java:18:3:18:16 | 0177_7777_7777 | 2147483647 | 2147483647 | +| IntegerLiterals.java:19:3:19:43 | 0b0111_1111_1111_1111_1111_1111_1111_1111 | 2147483647 | 2147483647 | +| IntegerLiterals.java:20:3:20:13 | 0x8000_0000 | -2147483648 | -2147483648 | +| IntegerLiterals.java:21:3:21:16 | 0200_0000_0000 | -2147483648 | -2147483648 | +| IntegerLiterals.java:22:3:22:43 | 0b1000_0000_0000_0000_0000_0000_0000_0000 | -2147483648 | -2147483648 | +| IntegerLiterals.java:23:3:23:13 | 0xffff_ffff | -1 | -1 | +| IntegerLiterals.java:24:3:24:16 | 0377_7777_7777 | -1 | -1 | +| IntegerLiterals.java:25:3:25:43 | 0b1111_1111_1111_1111_1111_1111_1111_1111 | -1 | -1 | +| IntegerLiterals.java:27:8:27:8 | 0 | 0 | 0 | +| IntegerLiterals.java:32:4:32:4 | 0 | 0 | 0 | +| IntegerLiterals.java:33:4:33:4 | 0 | 0 | 0 | +| IntegerLiterals.java:34:4:34:4 | 1 | 1 | 1 | +| IntegerLiterals.java:35:4:35:4 | 1 | 1 | 1 | +| IntegerLiterals.java:36:4:36:13 | 2147483647 | 2147483647 | 2147483647 | +| IntegerLiterals.java:41:3:41:3 | 1 | 1 | 1 | +| IntegerLiterals.java:41:7:41:7 | 1 | 1 | 1 | +| IntegerLiterals.java:42:3:42:3 | 0 | 0 | 0 | +| IntegerLiterals.java:42:7:42:7 | 0 | 0 | 0 | diff --git a/java/ql/test/library-tests/literals/literalInteger.ql b/java/ql/test/library-tests/literals/integerLiterals/integerLiterals.ql similarity index 100% rename from java/ql/test/library-tests/literals/literalInteger.ql rename to java/ql/test/library-tests/literals/integerLiterals/integerLiterals.ql diff --git a/java/ql/test/library-tests/literals/literalBoolean.expected b/java/ql/test/library-tests/literals/literalBoolean.expected deleted file mode 100644 index bfc9f1a043f..00000000000 --- a/java/ql/test/library-tests/literals/literalBoolean.expected +++ /dev/null @@ -1,3 +0,0 @@ -| literals/Literals.java:11:22:11:25 | true | true | true | -| literals/Literals.java:16:3:16:6 | true | true | true | -| literals/Literals.java:17:3:17:7 | false | false | false | diff --git a/java/ql/test/library-tests/literals/literalChar.expected b/java/ql/test/library-tests/literals/literalChar.expected deleted file mode 100644 index 00eb45eff57..00000000000 --- a/java/ql/test/library-tests/literals/literalChar.expected +++ /dev/null @@ -1,10 +0,0 @@ -| literals/Literals.java:12:22:12:24 | 'x' | x | -| literals/Literals.java:21:3:21:5 | 'a' | a | -| literals/Literals.java:22:3:22:10 | '\\u0061' | a | -| literals/Literals.java:23:3:23:10 | '\\u0000' | \u0000 | -| literals/Literals.java:24:3:24:6 | '\\0' | \u0000 | -| literals/Literals.java:25:3:25:6 | '\\n' | \n | -| literals/Literals.java:26:3:26:6 | '\\0' | \u0000 | -| literals/Literals.java:27:3:27:6 | '\\\\' | \\ | -| literals/Literals.java:28:3:28:6 | '\\'' | ' | -| literals/Literals.java:29:3:29:8 | '\\123' | S | diff --git a/java/ql/test/library-tests/literals/literalDouble.expected b/java/ql/test/library-tests/literals/literalDouble.expected deleted file mode 100644 index ba64bdd8446..00000000000 --- a/java/ql/test/library-tests/literals/literalDouble.expected +++ /dev/null @@ -1,16 +0,0 @@ -| literals/Literals.java:10:22:10:27 | 456.0D | 456.0 | 456.0 | -| literals/Literals.java:33:3:33:5 | 0.0 | 0.0 | 0.0 | -| literals/Literals.java:34:3:34:4 | 0d | 0.0 | 0.0 | -| literals/Literals.java:35:3:35:5 | .0d | 0.0 | 0.0 | -| literals/Literals.java:36:3:36:4 | .0 | 0.0 | 0.0 | -| literals/Literals.java:37:4:37:6 | 0.d | 0.0 | 0.0 | -| literals/Literals.java:38:4:38:6 | 0.d | 0.0 | 0.0 | -| literals/Literals.java:39:3:39:22 | 1.234567890123456789 | 1.2345678901234567 | 1.2345678901234567 | -| literals/Literals.java:40:3:40:24 | 1.55555555555555555555 | 1.5555555555555556 | 1.5555555555555556 | -| literals/Literals.java:42:3:42:5 | 1e1 | 10.0 | 10.0 | -| literals/Literals.java:43:3:43:24 | 1.7976931348623157E308 | 1.7976931348623157E308 | 1.7976931348623157E308 | -| literals/Literals.java:44:4:44:25 | 1.7976931348623157E308 | 1.7976931348623157E308 | 1.7976931348623157E308 | -| literals/Literals.java:45:3:45:28 | 0x1.f_ffff_ffff_ffffP+1023 | 1.7976931348623157E308 | 1.7976931348623157E308 | -| literals/Literals.java:46:3:46:10 | 4.9e-324 | 4.9E-324 | 4.9E-324 | -| literals/Literals.java:47:3:47:28 | 0x0.0_0000_0000_0001P-1022 | 4.9E-324 | 4.9E-324 | -| literals/Literals.java:48:3:48:13 | 0x1.0P-1074 | 4.9E-324 | 4.9E-324 | diff --git a/java/ql/test/library-tests/literals/literalFloat.expected b/java/ql/test/library-tests/literals/literalFloat.expected deleted file mode 100644 index f6221533fdb..00000000000 --- a/java/ql/test/library-tests/literals/literalFloat.expected +++ /dev/null @@ -1,16 +0,0 @@ -| literals/Literals.java:9:22:9:27 | 123.0F | 123.0 | 123.0 | -| literals/Literals.java:52:3:52:6 | 0.0f | 0.0 | 0.0 | -| literals/Literals.java:53:3:53:4 | 0f | 0.0 | 0.0 | -| literals/Literals.java:54:3:54:5 | .0f | 0.0 | 0.0 | -| literals/Literals.java:55:4:55:6 | 0.f | 0.0 | 0.0 | -| literals/Literals.java:56:4:56:6 | 0.f | 0.0 | 0.0 | -| literals/Literals.java:57:3:57:10 | 1_0_0.0f | 100.0 | 100.0 | -| literals/Literals.java:58:3:58:23 | 1.234567890123456789f | 1.2345679 | 1.2345679 | -| literals/Literals.java:59:3:59:25 | 1.55555555555555555555f | 1.5555556 | 1.5555556 | -| literals/Literals.java:61:3:61:6 | 1e1f | 10.0 | 10.0 | -| literals/Literals.java:62:3:62:15 | 3.4028235e38f | 3.4028235E38 | 3.4028235E38 | -| literals/Literals.java:63:4:63:16 | 3.4028235e38f | 3.4028235E38 | 3.4028235E38 | -| literals/Literals.java:64:3:64:18 | 0x1.fffffeP+127f | 3.4028235E38 | 3.4028235E38 | -| literals/Literals.java:65:3:65:10 | 1.4e-45f | 1.4E-45 | 1.4E-45 | -| literals/Literals.java:66:3:66:18 | 0x0.000002P-126f | 1.4E-45 | 1.4E-45 | -| literals/Literals.java:67:3:67:13 | 0x1.0P-149f | 1.4E-45 | 1.4E-45 | diff --git a/java/ql/test/library-tests/literals/literalInteger.expected b/java/ql/test/library-tests/literals/literalInteger.expected deleted file mode 100644 index 40c6a89cd98..00000000000 --- a/java/ql/test/library-tests/literals/literalInteger.expected +++ /dev/null @@ -1,20 +0,0 @@ -| literals/Literals.java:7:22:7:24 | 123 | 123 | 123 | -| literals/Literals.java:71:3:71:3 | 0 | 0 | 0 | -| literals/Literals.java:72:3:72:5 | 0_0 | 0 | 0 | -| literals/Literals.java:73:3:73:7 | 0___0 | 0 | 0 | -| literals/Literals.java:74:3:74:6 | 0_12 | 10 | 10 | -| literals/Literals.java:75:3:75:7 | 0X012 | 18 | 18 | -| literals/Literals.java:76:3:76:10 | 0xaBcDeF | 11259375 | 11259375 | -| literals/Literals.java:77:3:77:6 | 0B11 | 3 | 3 | -| literals/Literals.java:78:3:78:12 | 0x80000000 | -2147483648 | -2147483648 | -| literals/Literals.java:79:3:79:12 | 2147483647 | 2147483647 | 2147483647 | -| literals/Literals.java:80:3:80:13 | -2147483648 | -2147483648 | -2147483648 | -| literals/Literals.java:82:3:82:13 | 0x7fff_ffff | 2147483647 | 2147483647 | -| literals/Literals.java:83:3:83:16 | 0177_7777_7777 | 2147483647 | 2147483647 | -| literals/Literals.java:84:3:84:43 | 0b0111_1111_1111_1111_1111_1111_1111_1111 | 2147483647 | 2147483647 | -| literals/Literals.java:85:3:85:13 | 0x8000_0000 | -2147483648 | -2147483648 | -| literals/Literals.java:86:3:86:16 | 0200_0000_0000 | -2147483648 | -2147483648 | -| literals/Literals.java:87:3:87:43 | 0b1000_0000_0000_0000_0000_0000_0000_0000 | -2147483648 | -2147483648 | -| literals/Literals.java:88:3:88:13 | 0xffff_ffff | -1 | -1 | -| literals/Literals.java:89:3:89:16 | 0377_7777_7777 | -1 | -1 | -| literals/Literals.java:90:3:90:43 | 0b1111_1111_1111_1111_1111_1111_1111_1111 | -1 | -1 | diff --git a/java/ql/test/library-tests/literals/literalLong.expected b/java/ql/test/library-tests/literals/literalLong.expected deleted file mode 100644 index f46c55f9f37..00000000000 --- a/java/ql/test/library-tests/literals/literalLong.expected +++ /dev/null @@ -1,20 +0,0 @@ -| literals/Literals.java:8:22:8:25 | 456L | 456 | -| literals/Literals.java:94:3:94:4 | 0l | 0 | -| literals/Literals.java:95:3:95:4 | 0L | 0 | -| literals/Literals.java:96:3:96:6 | 0_0L | 0 | -| literals/Literals.java:97:3:97:8 | 0___0L | 0 | -| literals/Literals.java:98:3:98:7 | 0_12L | 10 | -| literals/Literals.java:99:3:99:8 | 0X012L | 18 | -| literals/Literals.java:100:3:100:11 | 0xaBcDeFL | 11259375 | -| literals/Literals.java:101:3:101:7 | 0B11L | 3 | -| literals/Literals.java:102:3:102:22 | 9223372036854775807L | 9223372036854775807 | -| literals/Literals.java:103:3:103:23 | -9223372036854775808L | -9223372036854775808 | -| literals/Literals.java:105:3:105:24 | 0x7fff_ffff_ffff_ffffL | 9223372036854775807 | -| literals/Literals.java:106:3:106:30 | 07_7777_7777_7777_7777_7777L | 9223372036854775807 | -| literals/Literals.java:107:3:107:84 | 0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L | 9223372036854775807 | -| literals/Literals.java:108:3:108:24 | 0x8000_0000_0000_0000L | -9223372036854775808 | -| literals/Literals.java:109:3:109:31 | 010_0000_0000_0000_0000_0000L | -9223372036854775808 | -| literals/Literals.java:110:3:110:84 | 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L | -9223372036854775808 | -| literals/Literals.java:111:3:111:24 | 0xffff_ffff_ffff_ffffL | -1 | -| literals/Literals.java:112:3:112:31 | 017_7777_7777_7777_7777_7777L | -1 | -| literals/Literals.java:113:3:113:84 | 0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L | -1 | diff --git a/java/ql/test/library-tests/literals/literalString.expected b/java/ql/test/library-tests/literals/literalString.expected deleted file mode 100644 index ff39e8085e1..00000000000 --- a/java/ql/test/library-tests/literals/literalString.expected +++ /dev/null @@ -1,20 +0,0 @@ -| literals/Literals.java:6:22:6:37 | "literal string" | literal string | literal string | -| literals/Literals.java:117:3:117:19 | "hello" + "world" | helloworld | helloworld | -| literals/Literals.java:118:3:118:17 | "hello,\\tworld" | hello,\tworld | hello,\tworld | -| literals/Literals.java:119:3:119:21 | "hello,\\u0009world" | hello,\tworld | hello,\tworld | -| literals/Literals.java:120:3:120:10 | "\\u0061" | a | a | -| literals/Literals.java:121:3:121:6 | "\\0" | \u0000 | \u0000 | -| literals/Literals.java:122:3:122:9 | "\\0000" | \u00000 | \u00000 | -| literals/Literals.java:123:3:123:6 | "\\"" | " | " | -| literals/Literals.java:124:3:124:6 | "\\'" | ' | ' | -| literals/Literals.java:125:3:125:6 | "\\n" | \n | \n | -| literals/Literals.java:126:3:126:6 | "\\\\" | \\ | \\ | -| literals/Literals.java:127:3:127:13 | "test \\123" | test S | test S | -| literals/Literals.java:128:3:128:9 | "\\1234" | S4 | S4 | -| literals/Literals.java:129:3:129:13 | "\\u0061567" | a567 | a567 | -| literals/Literals.java:130:3:130:13 | "\\u1234567" | \u1234567 | \u1234567 | -| literals/Literals.java:131:3:131:18 | "\\uaBcDeF\\u0aB1" | \uabcdeF\u0ab1 | \uabcdeF\u0ab1 | -| literals/Literals.java:132:3:132:16 | "\\uD800\\uDC00" | \ud800\udc00 | \ud800\udc00 | -| literals/Literals.java:134:3:134:10 | "\\uD800" | \ufffd | \ufffd | -| literals/Literals.java:135:3:135:10 | "\\uDC00" | \ufffd | \ufffd | -| literals/Literals.java:136:3:136:31 | "hello\\uD800hello\\uDC00world" | hello\ufffdhello\ufffdworld | hello\ufffdhello\ufffdworld | diff --git a/java/ql/test/library-tests/literals-numeric/NumericLiterals.java b/java/ql/test/library-tests/literals/literals-numeric/NumericLiterals.java similarity index 95% rename from java/ql/test/library-tests/literals-numeric/NumericLiterals.java rename to java/ql/test/library-tests/literals/literals-numeric/NumericLiterals.java index 02f2fbfcc6b..776ac6215fc 100644 --- a/java/ql/test/library-tests/literals-numeric/NumericLiterals.java +++ b/java/ql/test/library-tests/literals/literals-numeric/NumericLiterals.java @@ -1,4 +1,4 @@ -class NumericLiterals { +class NumericLiterals { void negativeLiterals() { float f = -1f; double d = -1d; diff --git a/java/ql/test/library-tests/literals-numeric/negativeNumericLiteral.expected b/java/ql/test/library-tests/literals/literals-numeric/negativeNumericLiteral.expected similarity index 100% rename from java/ql/test/library-tests/literals-numeric/negativeNumericLiteral.expected rename to java/ql/test/library-tests/literals/literals-numeric/negativeNumericLiteral.expected diff --git a/java/ql/test/library-tests/literals/literals-numeric/negativeNumericLiterals.expected b/java/ql/test/library-tests/literals/literals-numeric/negativeNumericLiterals.expected new file mode 100644 index 00000000000..95100f259dd --- /dev/null +++ b/java/ql/test/library-tests/literals/literals-numeric/negativeNumericLiterals.expected @@ -0,0 +1,12 @@ +| NumericLiterals.java:3:14:3:15 | 1f | 1.0 | NumericLiterals.java:3:13:3:15 | -... | +| NumericLiterals.java:4:15:4:16 | 1d | 1.0 | NumericLiterals.java:4:14:4:16 | -... | +| NumericLiterals.java:5:13:5:22 | 2147483647 | 2147483647 | NumericLiterals.java:5:12:5:22 | -... | +| NumericLiterals.java:6:12:6:22 | -2147483648 | -2147483648 | NumericLiterals.java:6:7:6:22 | i2 | +| NumericLiterals.java:7:13:7:46 | 0b10000000000000000000000000000000 | -2147483648 | NumericLiterals.java:7:12:7:46 | -... | +| NumericLiterals.java:8:13:8:24 | 020000000000 | -2147483648 | NumericLiterals.java:8:12:8:24 | -... | +| NumericLiterals.java:9:13:9:22 | 0x80000000 | -2147483648 | NumericLiterals.java:9:12:9:22 | -... | +| NumericLiterals.java:10:14:10:33 | 9223372036854775807L | 9223372036854775807 | NumericLiterals.java:10:13:10:33 | -... | +| NumericLiterals.java:11:13:11:33 | -9223372036854775808L | -9223372036854775808 | NumericLiterals.java:11:8:11:33 | l2 | +| NumericLiterals.java:12:14:12:80 | 0b1000000000000000000000000000000000000000000000000000000000000000L | -9223372036854775808 | NumericLiterals.java:12:13:12:80 | -... | +| NumericLiterals.java:13:14:13:37 | 01000000000000000000000L | -9223372036854775808 | NumericLiterals.java:13:13:13:37 | -... | +| NumericLiterals.java:14:14:14:32 | 0x8000000000000000L | -9223372036854775808 | NumericLiterals.java:14:13:14:32 | -... | diff --git a/java/ql/test/library-tests/literals-numeric/negativeNumericLiteral.ql b/java/ql/test/library-tests/literals/literals-numeric/negativeNumericLiterals.ql similarity index 100% rename from java/ql/test/library-tests/literals-numeric/negativeNumericLiteral.ql rename to java/ql/test/library-tests/literals/literals-numeric/negativeNumericLiterals.ql diff --git a/java/ql/test/library-tests/literals/literals/Literals.java b/java/ql/test/library-tests/literals/literals/Literals.java deleted file mode 100644 index 082310acb80..00000000000 --- a/java/ql/test/library-tests/literals/literals/Literals.java +++ /dev/null @@ -1,138 +0,0 @@ -package literals; - -public class Literals { - public int notAliteral; - public void doStuff() { - System.out.println("literal string"); - System.out.println(123); - System.out.println(456L); - System.out.println(123.0F); - System.out.println(456.0D); - System.out.println(true); - System.out.println('x'); - } - - boolean[] booleans = { - true, - false - }; - - char[] chars = { - 'a', - '\u0061', // 'a' - '\u0000', - '\0', - '\n', - '\0', - '\\', - '\'', - '\123' // octal escape sequence for 'S' - }; - - double[] doubles = { - 0.0, - 0d, - .0d, - .0, - -0.d, - +0.d, - 1.234567890123456789, - 1.55555555555555555555, - // From the JLS - 1e1, - 1.7976931348623157E308, - -1.7976931348623157E308, - 0x1.f_ffff_ffff_ffffP+1023, - 4.9e-324, - 0x0.0_0000_0000_0001P-1022, - 0x1.0P-1074 - }; - - float[] floats = { - 0.0f, - 0f, - .0f, - -0.f, - +0.f, - 1_0_0.0f, - 1.234567890123456789f, - 1.55555555555555555555f, - // From the JLS - 1e1f, - 3.4028235e38f, - -3.4028235e38f, - 0x1.fffffeP+127f, - 1.4e-45f, - 0x0.000002P-126f, - 0x1.0P-149f - }; - - int[] ints = { - 0, - 0_0, - 0___0, - 0_12, // octal - 0X012, // hex - 0xaBcDeF, // hex - 0B11, // binary - 0x80000000, - 2147483647, - -2147483648, - // From the JLS - 0x7fff_ffff, - 0177_7777_7777, // octal - 0b0111_1111_1111_1111_1111_1111_1111_1111, // binary - 0x8000_0000, - 0200_0000_0000, - 0b1000_0000_0000_0000_0000_0000_0000_0000, - 0xffff_ffff, - 0377_7777_7777, - 0b1111_1111_1111_1111_1111_1111_1111_1111 - }; - - long[] longs = { - 0l, - 0L, - 0_0L, - 0___0L, - 0_12L, // octal - 0X012L, // hex - 0xaBcDeFL, // hex - 0B11L, // binary - 9223372036854775807L, - -9223372036854775808L, - // From the JLS - 0x7fff_ffff_ffff_ffffL, - 07_7777_7777_7777_7777_7777L, // octal - 0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L, // binary - 0x8000_0000_0000_0000L, - 010_0000_0000_0000_0000_0000L, - 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L, - 0xffff_ffff_ffff_ffffL, - 017_7777_7777_7777_7777_7777L, - 0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L - }; - - String[] strings = { - "hello" + "world", // two separate literals - "hello,\tworld", - "hello,\u0009world", - "\u0061", // 'a' - "\0", - "\0000", - "\"", - "\'", - "\n", - "\\", - "test \123", // octal escape sequence for 'S' - "\1234", // octal escape followed by '4' - "\u0061567", // escape sequence for 'a' followed by "567" - "\u1234567", // '\u1234' followed by "567" - "\uaBcDeF\u0aB1", // '\uABCD' followed by "eF" followed by '\u0AB1' - "\uD800\uDC00", // surrogate pair - // Unpaired surrogates - "\uD800", - "\uDC00", - "hello\uD800hello\uDC00world" - }; -} diff --git a/java/ql/test/library-tests/literals/longLiterals/LongLiterals.java b/java/ql/test/library-tests/literals/longLiterals/LongLiterals.java new file mode 100644 index 00000000000..7501300684b --- /dev/null +++ b/java/ql/test/library-tests/literals/longLiterals/LongLiterals.java @@ -0,0 +1,56 @@ +package longLiterals; + +public class LongLiterals { + long[] longs = { + 0l, + 0L, + 1L, + 0_0L, + 0___0L, + 0_12L, // octal + 0X012L, // hex + 0xaBcDeFL, // hex + 0B11L, // binary + 9223372036854775807L, + -9223372036854775808L, // special case: sign is part of the literal + // From the JLS + 0x7fff_ffff_ffff_ffffL, + 07_7777_7777_7777_7777_7777L, // octal + 0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L, // binary + 0x8000_0000_0000_0000L, + 010_0000_0000_0000_0000_0000L, + 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L, + 0xffff_ffff_ffff_ffffL, + 017_7777_7777_7777_7777_7777L, + 0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L, + // Using Unicode escapes (which are handled during pre-processing) + \u0030\u004C, // 0L + }; + + // + and - are not part of the literal + long[] longsWithSign = { + +0L, + -0L, + +1L, + -1L, + +9223372036854775807L, + }; + + // The operation expression (e.g. `+`) is not a literal + long[] numericOperations = { + 1L + 1L, + 0L / 0L, + }; + + Object[] longLongLiterals = { + "0L", + '0', + 0, + (long) 0, + 0.0, + (long) 0.0, + Long.MIN_VALUE, + }; + + long nonLiteral; +} diff --git a/java/ql/test/library-tests/literals/longLiterals/longLiterals.expected b/java/ql/test/library-tests/literals/longLiterals/longLiterals.expected new file mode 100644 index 00000000000..d020a8f1c87 --- /dev/null +++ b/java/ql/test/library-tests/literals/longLiterals/longLiterals.expected @@ -0,0 +1,30 @@ +| LongLiterals.java:5:3:5:4 | 0l | 0 | +| LongLiterals.java:6:3:6:4 | 0L | 0 | +| LongLiterals.java:7:3:7:4 | 1L | 1 | +| LongLiterals.java:8:3:8:6 | 0_0L | 0 | +| LongLiterals.java:9:3:9:8 | 0___0L | 0 | +| LongLiterals.java:10:3:10:7 | 0_12L | 10 | +| LongLiterals.java:11:3:11:8 | 0X012L | 18 | +| LongLiterals.java:12:3:12:11 | 0xaBcDeFL | 11259375 | +| LongLiterals.java:13:3:13:7 | 0B11L | 3 | +| LongLiterals.java:14:3:14:22 | 9223372036854775807L | 9223372036854775807 | +| LongLiterals.java:15:3:15:23 | -9223372036854775808L | -9223372036854775808 | +| LongLiterals.java:17:3:17:24 | 0x7fff_ffff_ffff_ffffL | 9223372036854775807 | +| LongLiterals.java:18:3:18:30 | 07_7777_7777_7777_7777_7777L | 9223372036854775807 | +| LongLiterals.java:19:3:19:84 | 0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L | 9223372036854775807 | +| LongLiterals.java:20:3:20:24 | 0x8000_0000_0000_0000L | -9223372036854775808 | +| LongLiterals.java:21:3:21:31 | 010_0000_0000_0000_0000_0000L | -9223372036854775808 | +| LongLiterals.java:22:3:22:84 | 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L | -9223372036854775808 | +| LongLiterals.java:23:3:23:24 | 0xffff_ffff_ffff_ffffL | -1 | +| LongLiterals.java:24:3:24:31 | 017_7777_7777_7777_7777_7777L | -1 | +| LongLiterals.java:25:3:25:84 | 0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L | -1 | +| LongLiterals.java:27:8:27:14 | 0\\u004C | 0 | +| LongLiterals.java:32:4:32:5 | 0L | 0 | +| LongLiterals.java:33:4:33:5 | 0L | 0 | +| LongLiterals.java:34:4:34:5 | 1L | 1 | +| LongLiterals.java:35:4:35:5 | 1L | 1 | +| LongLiterals.java:36:4:36:23 | 9223372036854775807L | 9223372036854775807 | +| LongLiterals.java:41:3:41:4 | 1L | 1 | +| LongLiterals.java:41:8:41:9 | 1L | 1 | +| LongLiterals.java:42:3:42:4 | 0L | 0 | +| LongLiterals.java:42:8:42:9 | 0L | 0 | diff --git a/java/ql/test/library-tests/literals/literalLong.ql b/java/ql/test/library-tests/literals/longLiterals/longLiterals.ql similarity index 100% rename from java/ql/test/library-tests/literals/literalLong.ql rename to java/ql/test/library-tests/literals/longLiterals/longLiterals.ql diff --git a/java/ql/test/library-tests/literals/stringLiterals/StringLiterals.java b/java/ql/test/library-tests/literals/stringLiterals/StringLiterals.java new file mode 100644 index 00000000000..7325cf3e340 --- /dev/null +++ b/java/ql/test/library-tests/literals/stringLiterals/StringLiterals.java @@ -0,0 +1,59 @@ +package stringLiterals; + +import java.io.File; + +public class StringLiterals { + String[] strings = { + "", + "hello,\tworld", + "hello,\u0009world", + "\u0061", // 'a' + "\0", + "\uFFFF", + "\ufFfF", + "\"", + "\'", + "\n", + "\\", + "test \123", // octal escape sequence for 'S' + "\1234", // octal escape followed by '4' + "\0000", // octal escape \000 followed by '0' + "\u0061567", // escape sequence for 'a' followed by "567" + "\u1234567", // '\u1234' followed by "567" + "\uaBcDeF\u0aB1", // '\uABCD' followed by "eF" followed by '\u0AB1' + "\uD800\uDC00", // surrogate pair + "\uDBFF\uDFFF", // U+10FFFF + // Unpaired surrogates + "\uD800", + "\uDC00", + "hello\uD800hello\uDC00world", // malformed surrogates + // Using Unicode escapes (which are handled during pre-processing) + "\u005C\u0022", // escaped double quote ("\"") + \u0022\u0061\u0022, // "a" + }; + + // The concatenation (`+`) is not a string literal + String[] stringConcatenation = { + // CodeQL erroneously reports this as one literal, see https://github.com/github/codeql/issues/5469 + "hello" + "world", + null + "a", + "a" + null, + "a" + 1, + 1 + "a", + "a" + true, + true + "a", + "a" + 'b', + 'b' + "a", + }; + + Object[] nonStringLiterals = { + 'a', + '"', + true, + null, + 0, + File.pathSeparator + }; + + String nonLiteral; +} diff --git a/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.expected b/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.expected new file mode 100644 index 00000000000..7f8c0e2b5d1 --- /dev/null +++ b/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.expected @@ -0,0 +1,33 @@ +| StringLiterals.java:7:3:7:4 | "" | | | +| StringLiterals.java:8:3:8:17 | "hello,\\tworld" | hello,\tworld | hello,\tworld | +| StringLiterals.java:9:3:9:21 | "hello,\\u0009world" | hello,\tworld | hello,\tworld | +| StringLiterals.java:10:3:10:10 | "\\u0061" | a | a | +| StringLiterals.java:11:3:11:6 | "\\0" | \u0000 | \u0000 | +| StringLiterals.java:12:3:12:10 | "\\uFFFF" | \uffff | \uffff | +| StringLiterals.java:13:3:13:10 | "\\ufFfF" | \uffff | \uffff | +| StringLiterals.java:14:3:14:6 | "\\"" | " | " | +| StringLiterals.java:15:3:15:6 | "\\'" | ' | ' | +| StringLiterals.java:16:3:16:6 | "\\n" | \n | \n | +| StringLiterals.java:17:3:17:6 | "\\\\" | \\ | \\ | +| StringLiterals.java:18:3:18:13 | "test \\123" | test S | test S | +| StringLiterals.java:19:3:19:9 | "\\1234" | S4 | S4 | +| StringLiterals.java:20:3:20:9 | "\\0000" | \u00000 | \u00000 | +| StringLiterals.java:21:3:21:13 | "\\u0061567" | a567 | a567 | +| StringLiterals.java:22:3:22:13 | "\\u1234567" | \u1234567 | \u1234567 | +| StringLiterals.java:23:3:23:18 | "\\uaBcDeF\\u0aB1" | \uabcdeF\u0ab1 | \uabcdeF\u0ab1 | +| StringLiterals.java:24:3:24:16 | "\\uD800\\uDC00" | \ud800\udc00 | \ud800\udc00 | +| StringLiterals.java:25:3:25:16 | "\\uDBFF\\uDFFF" | \udbff\udfff | \udbff\udfff | +| StringLiterals.java:27:3:27:10 | "\\uD800" | \ufffd | \ufffd | +| StringLiterals.java:28:3:28:10 | "\\uDC00" | \ufffd | \ufffd | +| StringLiterals.java:29:3:29:31 | "hello\\uD800hello\\uDC00world" | hello\ufffdhello\ufffdworld | hello\ufffdhello\ufffdworld | +| StringLiterals.java:31:3:31:16 | "\\u005C\\u0022" | " | " | +| StringLiterals.java:32:8:32:20 | 2\\u0061\\u0022 | a | a | +| StringLiterals.java:38:3:38:19 | "hello" + "world" | helloworld | helloworld | +| StringLiterals.java:39:10:39:12 | "a" | a | a | +| StringLiterals.java:40:3:40:5 | "a" | a | a | +| StringLiterals.java:41:3:41:5 | "a" | a | a | +| StringLiterals.java:42:7:42:9 | "a" | a | a | +| StringLiterals.java:43:3:43:5 | "a" | a | a | +| StringLiterals.java:44:10:44:12 | "a" | a | a | +| StringLiterals.java:45:3:45:5 | "a" | a | a | +| StringLiterals.java:46:9:46:11 | "a" | a | a | diff --git a/java/ql/test/library-tests/literals/literalString.ql b/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.ql similarity index 100% rename from java/ql/test/library-tests/literals/literalString.ql rename to java/ql/test/library-tests/literals/stringLiterals/stringLiterals.ql From 924b7320bc2a640922c697cba03fbcdefb48f700 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Sat, 4 Sep 2021 21:24:16 +0200 Subject: [PATCH 102/361] Java: Add test for NullLiteral --- java/ql/lib/semmle/code/java/Expr.qll | 1 + .../literals/nullLiterals/NullLiterals.java | 22 +++++++++++++++++++ .../nullLiterals/nullLiterals.expected | 3 +++ .../literals/nullLiterals/nullLiterals.ql | 4 ++++ 4 files changed, 30 insertions(+) create mode 100644 java/ql/test/library-tests/literals/nullLiterals/NullLiterals.java create mode 100644 java/ql/test/library-tests/literals/nullLiterals/nullLiterals.expected create mode 100644 java/ql/test/library-tests/literals/nullLiterals/nullLiterals.ql diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index 3e5d54e6ac6..abc91472494 100755 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -734,6 +734,7 @@ class StringLiteral extends Literal, @stringliteral { /** The null literal, written `null`. */ class NullLiteral extends Literal, @nullliteral { + // Override these predicates because the inherited ones have no result override string getLiteral() { result = "null" } override string getValue() { result = "null" } diff --git a/java/ql/test/library-tests/literals/nullLiterals/NullLiterals.java b/java/ql/test/library-tests/literals/nullLiterals/NullLiterals.java new file mode 100644 index 00000000000..f0042b2f11a --- /dev/null +++ b/java/ql/test/library-tests/literals/nullLiterals/NullLiterals.java @@ -0,0 +1,22 @@ +package nullLiterals; + +public class NullLiterals { + Object[] nulls = { + null, + // Using Unicode escapes (which are handled during pre-processing) + \u006E\u0075\u006C\u006C, // null + }; + + // The operation expressions (e.g. cast) are not a literal + Object[] operations = { + (Object) null, + }; + + Object[] nonNullLiterals = { + "null", + 0, + Boolean.FALSE, + }; + + Object nonLiteral; +} diff --git a/java/ql/test/library-tests/literals/nullLiterals/nullLiterals.expected b/java/ql/test/library-tests/literals/nullLiterals/nullLiterals.expected new file mode 100644 index 00000000000..0401876d07c --- /dev/null +++ b/java/ql/test/library-tests/literals/nullLiterals/nullLiterals.expected @@ -0,0 +1,3 @@ +| NullLiterals.java:5:3:5:6 | null | null | +| NullLiterals.java:7:8:7:26 | null | null | +| NullLiterals.java:12:12:12:15 | null | null | diff --git a/java/ql/test/library-tests/literals/nullLiterals/nullLiterals.ql b/java/ql/test/library-tests/literals/nullLiterals/nullLiterals.ql new file mode 100644 index 00000000000..4bfcf3c206b --- /dev/null +++ b/java/ql/test/library-tests/literals/nullLiterals/nullLiterals.ql @@ -0,0 +1,4 @@ +import semmle.code.java.Expr + +from NullLiteral lit +select lit, lit.getValue() From a62772c27496e35e764be895015ede2ef4fd7eb3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 16:35:12 +0100 Subject: [PATCH 103/361] C++: Add change note. --- cpp/change-notes/2021-10-01-improper-null-termination.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 cpp/change-notes/2021-10-01-improper-null-termination.md diff --git a/cpp/change-notes/2021-10-01-improper-null-termination.md b/cpp/change-notes/2021-10-01-improper-null-termination.md new file mode 100644 index 00000000000..fc569913ccf --- /dev/null +++ b/cpp/change-notes/2021-10-01-improper-null-termination.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Several improvements made to the `NullTermination.qll` library and the 'Potential improper null termination' (cpp/improper-null-termination). These changes reduce the number of false positive results for this query and related query 'User-controlled data may not be null terminated' (cpp/user-controlled-null-termination-tainted). From 5e4498a53a76fd2bfc2fdb207c6bae6417444e96 Mon Sep 17 00:00:00 2001 From: Joe Farebrother <joefarebrother@github.com> Date: Fri, 1 Oct 2021 16:53:53 +0100 Subject: [PATCH 104/361] Add more models; fix tests --- .../code/java/frameworks/android/Intent.qll | 29 ++- .../dataflow/taintsources/remote.expected | 2 + .../frameworks/android/intent/Test.java | 183 ++++++++++++++++++ .../frameworks/android/intent/models.csv | 27 ++- 4 files changed, 239 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 77c45b1e6f2..50b29e77298 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -79,6 +79,15 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.os;BaseBundle;true;putString;;;Argument[1];MapValue of Argument[-1];value", "android.os;BaseBundle;true;putStringArray;;;Argument[0];MapKey of Argument[-1];value", "android.os;BaseBundle;true;putStringArray;;;Argument[1];MapValue of Argument[-1];value", + "android.os;Bundle;false;Bundle;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;false;Bundle;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value", + "android.os;Bundle;false;Bundle;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value", + "android.os;Bundle;false;Bundle;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value", + "android.os;Bundle;true;clone;();;MapKey of Argument[-1];MapKey of ReturnValue;value", + "android.os;Bundle;true;clone;();;MapValue of Argument[-1];MapValue of ReturnValue;value", + // model for Bundle.deepCopy is not fully precise, as some map values aren't copied by value + "android.os;Bundle;true;deepCopy;();;MapKey of Argument[-1];MapKey of ReturnValue;value", + "android.os;Bundle;true;deepCopy;();;MapValue of Argument[-1];MapValue of ReturnValue;value", "android.os;Bundle;true;getBinder;(String);;MapValue of Argument[-1];ReturnValue;value", "android.os;Bundle;true;getBundle;(String);;MapValue of Argument[-1];ReturnValue;value", "android.os;Bundle;true;getByteArray;(String);;MapValue of Argument[-1];ReturnValue;value", @@ -133,6 +142,11 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value", "android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint", "android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint", + // currently only the Extras part of the intent is fully modelled + "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;value", + "android.content;Intent;false;Intent;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;false;Intent;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", @@ -172,7 +186,20 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.content;Intent;true;replaceExtras;(Bundle);;Argument[-1];ReturnValue;value", "android.content;Intent;true;replaceExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;replaceExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", - "android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value" + "android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setAction;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setClass;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setClassName;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setComponent;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setData;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setDataAndNormalize;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setDataAndType;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setDataAndTypeAndNormalize;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setFlags;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setIdentifier;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setPackage;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setType;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setTypeAndNormalize;;;Argument[-1];ReturnValue;value" ] } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.expected b/java/ql/test/library-tests/dataflow/taintsources/remote.expected index f3b5685d4b9..f1e5b4e3ff1 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.expected @@ -14,6 +14,8 @@ | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:52 | getStringExtra(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:17:29:17:35 | trouble | | IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1358:19:1358:27 | parameter this | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] read: <map.value> of argument -1 in getString | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] to write: return (return) in getString | | IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | parameter this | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:30 | getIntent(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:42 | getExtras(...) | diff --git a/java/ql/test/library-tests/frameworks/android/intent/Test.java b/java/ql/test/library-tests/frameworks/android/intent/Test.java index 525986aeb45..725f4880da0 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/Test.java +++ b/java/ql/test/library-tests/frameworks/android/intent/Test.java @@ -1,5 +1,6 @@ package generatedtest; +import android.content.Context; import android.content.Intent; import android.os.BaseBundle; import android.os.Bundle; @@ -27,6 +28,34 @@ public class Test { public void test() throws Exception { + { + // "android.content;Intent;false;Intent;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapKeyDefault(source())); + out = new Intent(in); + sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;false;Intent;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" + Intent out = null; + Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + out = new Intent(in); + sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + } + { + // "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.addCategory(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.addFlags(0); + sink(out); // $ hasValueFlow + } { // "android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Bundle out = null; @@ -790,6 +819,104 @@ public class Test { out.replaceExtras(in); sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow } + { + // "android.content;Intent;true;setAction;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setAction(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setClass;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setClass(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setClassName;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setClassName((String)null, (String)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setClassName;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setClassName((Context)null, (String)null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setComponent;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setComponent(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setData;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setData(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setDataAndNormalize;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setDataAndNormalize(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setDataAndType;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setDataAndType(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setDataAndTypeAndNormalize;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setDataAndTypeAndNormalize(null, null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setFlags;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setFlags(0); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setIdentifier;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setIdentifier(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setPackage;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setPackage(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setType;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setType(null); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;setTypeAndNormalize;;;Argument[-1];ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = in.setTypeAndNormalize(null); + sink(out); // $ hasValueFlow + } { // "android.os;BaseBundle;true;get;(String);;MapValue of Argument[-1];ReturnValue;value" Object out = null; @@ -931,6 +1058,62 @@ public class Test { out.putStringArray(null, in); sink(getMapValueDefault(out)); // $ hasValueFlow } + { + // "android.os;Bundle;false;Bundle;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + Bundle in = (Bundle)newWithMapKeyDefault(source()); + out = new Bundle(in); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;false;Bundle;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value" + Bundle out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = new Bundle(in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;false;Bundle;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value" + Bundle out = null; + PersistableBundle in = (PersistableBundle)newWithMapKeyDefault(source()); + out = new Bundle(in); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;false;Bundle;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value" + Bundle out = null; + PersistableBundle in = (PersistableBundle)newWithMapValueDefault(source()); + out = new Bundle(in); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;clone;();;MapKey of Argument[-1];MapKey of ReturnValue;value" + Object out = null; + Bundle in = (Bundle)newWithMapKeyDefault(source()); + out = in.clone(); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;clone;();;MapValue of Argument[-1];MapValue of ReturnValue;value" + Object out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.clone(); + sink(getMapValueDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;deepCopy;();;MapKey of Argument[-1];MapKey of ReturnValue;value" + Bundle out = null; + Bundle in = (Bundle)newWithMapKeyDefault(source()); + out = in.deepCopy(); + sink(getMapKeyDefault(out)); // $ hasValueFlow + } + { + // "android.os;Bundle;true;deepCopy;();;MapValue of Argument[-1];MapValue of ReturnValue;value" + Bundle out = null; + Bundle in = (Bundle)newWithMapValueDefault(source()); + out = in.deepCopy(); + sink(getMapValueDefault(out)); // $ hasValueFlow + } { // "android.os;Bundle;true;getBinder;(String);;MapValue of Argument[-1];ReturnValue;value" IBinder out = null; diff --git a/java/ql/test/library-tests/frameworks/android/intent/models.csv b/java/ql/test/library-tests/frameworks/android/intent/models.csv index 83be9bbcb0c..5a58fd36765 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/models.csv +++ b/java/ql/test/library-tests/frameworks/android/intent/models.csv @@ -18,6 +18,14 @@ android.os;BaseBundle;true;putString;;;Argument[0];MapKey of Argument[-1];value android.os;BaseBundle;true;putString;;;Argument[1];MapValue of Argument[-1];value android.os;BaseBundle;true;putStringArray;;;Argument[0];MapKey of Argument[-1];value android.os;BaseBundle;true;putStringArray;;;Argument[1];MapValue of Argument[-1];value +android.os;Bundle;false;Bundle;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value +android.os;Bundle;false;Bundle;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value +android.os;Bundle;false;Bundle;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value +android.os;Bundle;false;Bundle;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value +android.os;Bundle;true;clone;();;MapKey of Argument[-1];MapKey of ReturnValue;value +android.os;Bundle;true;clone;();;MapValue of Argument[-1];MapValue of ReturnValue;value +android.os;Bundle;true;deepCopy;();;MapKey of Argument[-1];MapKey of ReturnValue;value +android.os;Bundle;true;deepCopy;();;MapValue of Argument[-1];MapValue of ReturnValue;value android.os;Bundle;true;getBinder;(String);;MapValue of Argument[-1];ReturnValue;value android.os;Bundle;true;getBundle;(String);;MapValue of Argument[-1];ReturnValue;value android.os;Bundle;true;getByteArray;(String);;MapValue of Argument[-1];ReturnValue;value @@ -72,6 +80,10 @@ android.os;Bundle;true;putStringArrayList;;;Argument[0];MapKey of Argument[-1];v android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint +android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value +android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;value +android.content;Intent;false;Intent;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value +android.content;Intent;false;Intent;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value @@ -111,4 +123,17 @@ android.content;Intent;true;replaceExtras;(Bundle);;MapValue of Argument[0];MapV android.content;Intent;true;replaceExtras;(Bundle);;Argument[-1];ReturnValue;value android.content;Intent;true;replaceExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value android.content;Intent;true;replaceExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value \ No newline at end of file +android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value +android.content;Intent;true;setAction;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setClass;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setClassName;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setComponent;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setData;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setDataAndNormalize;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setDataAndType;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setDataAndTypeAndNormalize;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setFlags;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setIdentifier;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setPackage;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setType;;;Argument[-1];ReturnValue;value +android.content;Intent;true;setTypeAndNormalize;;;Argument[-1];ReturnValue;value \ No newline at end of file From 51188aa93f8ace3095db28918786ec7408cf319e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 17:04:22 +0100 Subject: [PATCH 105/361] C++: Give the two queries medium precision (for now). --- .../src/Likely Bugs/Memory Management/ImproperNullTermination.ql | 1 + .../src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql | 1 + 2 files changed, 2 insertions(+) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql index ed378dce60a..5c92b0a3db7 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql @@ -5,6 +5,7 @@ * @kind problem * @id cpp/improper-null-termination * @problem.severity warning + * @precision medium * @security-severity 7.8 * @tags security * external/cwe/cwe-170 diff --git a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql index b2844c319ba..31ce1037b27 100644 --- a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql @@ -5,6 +5,7 @@ * @kind problem * @id cpp/user-controlled-null-termination-tainted * @problem.severity warning + * @precision medium * @security-severity 10.0 * @tags security * external/cwe/cwe-170 From 085701c7dbef2358629b709369e9714af61e4bdc Mon Sep 17 00:00:00 2001 From: Joe Farebrother <joefarebrother@github.com> Date: Fri, 1 Oct 2021 17:11:12 +0100 Subject: [PATCH 106/361] Remove models.csv --- .../frameworks/android/intent/models.csv | 139 ------------------ 1 file changed, 139 deletions(-) delete mode 100644 java/ql/test/library-tests/frameworks/android/intent/models.csv diff --git a/java/ql/test/library-tests/frameworks/android/intent/models.csv b/java/ql/test/library-tests/frameworks/android/intent/models.csv deleted file mode 100644 index 5a58fd36765..00000000000 --- a/java/ql/test/library-tests/frameworks/android/intent/models.csv +++ /dev/null @@ -1,139 +0,0 @@ -android.os;BaseBundle;true;get;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;BaseBundle;true;getString;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;BaseBundle;true;getString;(String,String);;MapValue of Argument[-1];ReturnValue;value -android.os;BaseBundle;true;getString;(String,String);;Argument[1];ReturnValue;value -android.os;BaseBundle;true;getStringArray;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;BaseBundle;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value -android.os;BaseBundle;true;putAll;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putAll;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value -android.os;BaseBundle;true;putBoolean;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putBooleanArray;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putDouble;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putDoubleArray;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putInt;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putIntArray;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putLong;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putLongArray;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putString;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putString;;;Argument[1];MapValue of Argument[-1];value -android.os;BaseBundle;true;putStringArray;;;Argument[0];MapKey of Argument[-1];value -android.os;BaseBundle;true;putStringArray;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;false;Bundle;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value -android.os;Bundle;false;Bundle;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value -android.os;Bundle;false;Bundle;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value -android.os;Bundle;false;Bundle;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value -android.os;Bundle;true;clone;();;MapKey of Argument[-1];MapKey of ReturnValue;value -android.os;Bundle;true;clone;();;MapValue of Argument[-1];MapValue of ReturnValue;value -android.os;Bundle;true;deepCopy;();;MapKey of Argument[-1];MapKey of ReturnValue;value -android.os;Bundle;true;deepCopy;();;MapValue of Argument[-1];MapValue of ReturnValue;value -android.os;Bundle;true;getBinder;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getBundle;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getByteArray;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getCharArray;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getCharSequence;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getCharSequence;(String,CharSequence);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getCharSequence;(String,CharSequence);;Argument[1];ReturnValue;value -android.os;Bundle;true;getCharSequenceArray;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getCharSequenceArrayList;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getParcelable;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getParcelableArrayList;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getSerializable;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getSparseParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;getStringArrayList;(String);;MapValue of Argument[-1];ReturnValue;value -android.os;Bundle;true;putAll;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putAll;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value -android.os;Bundle;true;putBinder;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putBinder;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putBundle;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putBundle;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putByte;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putByteArray;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putByteArray;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putChar;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putCharArray;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putCharArray;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putCharSequence;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putCharSequence;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putCharSequenceArray;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putCharSequenceArray;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putCharSequenceArrayList;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putCharSequenceArrayList;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putFloat;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putFloatArray;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putIntegerArrayList;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putParcelable;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putParcelable;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putParcelableArray;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putParcelableArray;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putParcelableArrayList;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putParcelableArrayList;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putSerializable;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putSerializable;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putShort;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putShortArray;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putSize;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putSizeF;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putSparseParcelableArray;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putSparseParcelableArray;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;putStringArrayList;;;Argument[0];MapKey of Argument[-1];value -android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value -android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint -android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint -android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value -android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;value -android.content;Intent;false;Intent;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;false;Intent;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getCharArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getCharSequenceArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getCharSequenceArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getCharSequenceExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getParcelableArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getParcelableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getSerializableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getStringArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getStringArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;getStringExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value -android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;value -android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value -android.content;Intent;true;putIntegerArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putIntegerArrayListExtra;;;Argument[-1];ReturnValue;value -android.content;Intent;true;putParcelableArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putParcelableArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putParcelableArrayListExtra;;;Argument[-1];ReturnValue;value -android.content;Intent;true;putStringArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putStringArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putStringArrayListExtra;;;Argument[-1];ReturnValue;value -android.content;Intent;true;putExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putExtras;(Bundle);;Argument[-1];ReturnValue;value -android.content;Intent;true;putExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;putExtras;(Intent);;Argument[-1];ReturnValue;value -android.content;Intent;true;replaceExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;replaceExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;replaceExtras;(Bundle);;Argument[-1];ReturnValue;value -android.content;Intent;true;replaceExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;replaceExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value -android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value -android.content;Intent;true;setAction;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setClass;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setClassName;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setComponent;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setData;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setDataAndNormalize;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setDataAndType;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setDataAndTypeAndNormalize;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setFlags;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setIdentifier;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setPackage;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setType;;;Argument[-1];ReturnValue;value -android.content;Intent;true;setTypeAndNormalize;;;Argument[-1];ReturnValue;value \ No newline at end of file From e3fed559453ab1b855838c8afb8ebe31d19d6c19 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Tue, 7 Sep 2021 00:02:12 +0200 Subject: [PATCH 107/361] Java: Add tests for text blocks --- java/ql/lib/semmle/code/java/Expr.qll | 10 ++- .../stringLiterals/StringLiterals.java | 54 +++++++++++++ .../literals/stringLiterals/options | 1 + .../stringLiterals/stringLiterals.expected | 81 +++++++++++-------- .../literals/stringLiterals/stringLiterals.ql | 8 +- 5 files changed, 117 insertions(+), 37 deletions(-) create mode 100644 java/ql/test/library-tests/literals/stringLiterals/options diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index abc91472494..b83f5332756 100755 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -719,7 +719,15 @@ class CharacterLiteral extends Literal, @characterliteral { override string getAPrimaryQlClass() { result = "CharacterLiteral" } } -/** A string literal. For example, `"hello world"`. */ +/** + * A string literal or text block (Java 15 feature). For example, `"hello world"` + * or + * ```java + * """ + * Text with "quotes" + * """ + * ``` + */ class StringLiteral extends Literal, @stringliteral { /** * Gets the literal string without the quotes. diff --git a/java/ql/test/library-tests/literals/stringLiterals/StringLiterals.java b/java/ql/test/library-tests/literals/stringLiterals/StringLiterals.java index 7325cf3e340..9c0c55b12e5 100644 --- a/java/ql/test/library-tests/literals/stringLiterals/StringLiterals.java +++ b/java/ql/test/library-tests/literals/stringLiterals/StringLiterals.java @@ -32,10 +32,64 @@ public class StringLiterals { \u0022\u0061\u0022, // "a" }; + String[] textBlocks = { + // trailing whitespaces after """ (will be ignored) + """ + test "text" and escaped \u0022 + """, + // Indentation tests + """ + indented + """, + """ + no indentation last line + """, // Line is blank, therefore not indented + """ + indentation last line + \s""", // Line is not blank therefore indented + """ + not-indented + """, + """ + indented + """, + """ + not-indented + """, + """ + spaces (only single space is trimmed) + tab + """, + """ + end on same line""", + """ + trailing spaces ignored: + not ignored: \s + """, + """ + 3 quotes:""\"""", + """ + line \ + continuation \ + """, + """ + Explicit line breaks:\n + \r\n + \r + """, + // Using Unicode escapes (which are handled during pre-processing) + // Currently not detected by StringLiteral.isTextBlock() + \uuu0022"\u0022 + test + \u0022\uu0022", + }; + // The concatenation (`+`) is not a string literal String[] stringConcatenation = { // CodeQL erroneously reports this as one literal, see https://github.com/github/codeql/issues/5469 "hello" + "world", + """ + hello""" + "world", null + "a", "a" + null, "a" + 1, diff --git a/java/ql/test/library-tests/literals/stringLiterals/options b/java/ql/test/library-tests/literals/stringLiterals/options new file mode 100644 index 00000000000..bb7dba26161 --- /dev/null +++ b/java/ql/test/library-tests/literals/stringLiterals/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -source 15 -target 15 diff --git a/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.expected b/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.expected index 7f8c0e2b5d1..bf91a56e723 100644 --- a/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.expected +++ b/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.expected @@ -1,33 +1,48 @@ -| StringLiterals.java:7:3:7:4 | "" | | | -| StringLiterals.java:8:3:8:17 | "hello,\\tworld" | hello,\tworld | hello,\tworld | -| StringLiterals.java:9:3:9:21 | "hello,\\u0009world" | hello,\tworld | hello,\tworld | -| StringLiterals.java:10:3:10:10 | "\\u0061" | a | a | -| StringLiterals.java:11:3:11:6 | "\\0" | \u0000 | \u0000 | -| StringLiterals.java:12:3:12:10 | "\\uFFFF" | \uffff | \uffff | -| StringLiterals.java:13:3:13:10 | "\\ufFfF" | \uffff | \uffff | -| StringLiterals.java:14:3:14:6 | "\\"" | " | " | -| StringLiterals.java:15:3:15:6 | "\\'" | ' | ' | -| StringLiterals.java:16:3:16:6 | "\\n" | \n | \n | -| StringLiterals.java:17:3:17:6 | "\\\\" | \\ | \\ | -| StringLiterals.java:18:3:18:13 | "test \\123" | test S | test S | -| StringLiterals.java:19:3:19:9 | "\\1234" | S4 | S4 | -| StringLiterals.java:20:3:20:9 | "\\0000" | \u00000 | \u00000 | -| StringLiterals.java:21:3:21:13 | "\\u0061567" | a567 | a567 | -| StringLiterals.java:22:3:22:13 | "\\u1234567" | \u1234567 | \u1234567 | -| StringLiterals.java:23:3:23:18 | "\\uaBcDeF\\u0aB1" | \uabcdeF\u0ab1 | \uabcdeF\u0ab1 | -| StringLiterals.java:24:3:24:16 | "\\uD800\\uDC00" | \ud800\udc00 | \ud800\udc00 | -| StringLiterals.java:25:3:25:16 | "\\uDBFF\\uDFFF" | \udbff\udfff | \udbff\udfff | -| StringLiterals.java:27:3:27:10 | "\\uD800" | \ufffd | \ufffd | -| StringLiterals.java:28:3:28:10 | "\\uDC00" | \ufffd | \ufffd | -| StringLiterals.java:29:3:29:31 | "hello\\uD800hello\\uDC00world" | hello\ufffdhello\ufffdworld | hello\ufffdhello\ufffdworld | -| StringLiterals.java:31:3:31:16 | "\\u005C\\u0022" | " | " | -| StringLiterals.java:32:8:32:20 | 2\\u0061\\u0022 | a | a | -| StringLiterals.java:38:3:38:19 | "hello" + "world" | helloworld | helloworld | -| StringLiterals.java:39:10:39:12 | "a" | a | a | -| StringLiterals.java:40:3:40:5 | "a" | a | a | -| StringLiterals.java:41:3:41:5 | "a" | a | a | -| StringLiterals.java:42:7:42:9 | "a" | a | a | -| StringLiterals.java:43:3:43:5 | "a" | a | a | -| StringLiterals.java:44:10:44:12 | "a" | a | a | -| StringLiterals.java:45:3:45:5 | "a" | a | a | -| StringLiterals.java:46:9:46:11 | "a" | a | a | +| StringLiterals.java:7:3:7:4 | "" | | | | +| StringLiterals.java:8:3:8:17 | "hello,\\tworld" | hello,\tworld | hello,\tworld | | +| StringLiterals.java:9:3:9:21 | "hello,\\u0009world" | hello,\tworld | hello,\tworld | | +| StringLiterals.java:10:3:10:10 | "\\u0061" | a | a | | +| StringLiterals.java:11:3:11:6 | "\\0" | \u0000 | \u0000 | | +| StringLiterals.java:12:3:12:10 | "\\uFFFF" | \uffff | \uffff | | +| StringLiterals.java:13:3:13:10 | "\\ufFfF" | \uffff | \uffff | | +| StringLiterals.java:14:3:14:6 | "\\"" | " | " | | +| StringLiterals.java:15:3:15:6 | "\\'" | ' | ' | | +| StringLiterals.java:16:3:16:6 | "\\n" | \n | \n | | +| StringLiterals.java:17:3:17:6 | "\\\\" | \\ | \\ | | +| StringLiterals.java:18:3:18:13 | "test \\123" | test S | test S | | +| StringLiterals.java:19:3:19:9 | "\\1234" | S4 | S4 | | +| StringLiterals.java:20:3:20:9 | "\\0000" | \u00000 | \u00000 | | +| StringLiterals.java:21:3:21:13 | "\\u0061567" | a567 | a567 | | +| StringLiterals.java:22:3:22:13 | "\\u1234567" | \u1234567 | \u1234567 | | +| StringLiterals.java:23:3:23:18 | "\\uaBcDeF\\u0aB1" | \uabcdeF\u0ab1 | \uabcdeF\u0ab1 | | +| StringLiterals.java:24:3:24:16 | "\\uD800\\uDC00" | \ud800\udc00 | \ud800\udc00 | | +| StringLiterals.java:25:3:25:16 | "\\uDBFF\\uDFFF" | \udbff\udfff | \udbff\udfff | | +| StringLiterals.java:27:3:27:10 | "\\uD800" | \ufffd | \ufffd | | +| StringLiterals.java:28:3:28:10 | "\\uDC00" | \ufffd | \ufffd | | +| StringLiterals.java:29:3:29:31 | "hello\\uD800hello\\uDC00world" | hello\ufffdhello\ufffdworld | hello\ufffdhello\ufffdworld | | +| StringLiterals.java:31:3:31:16 | "\\u005C\\u0022" | " | " | | +| StringLiterals.java:32:8:32:20 | 2\\u0061\\u0022 | a | a | | +| StringLiterals.java:37:3:39:5 | """ \t \n\t\ttest "text" and escaped \\u0022\n\t\t""" | test "text" and escaped "\n | test "text" and escaped "\n | text-block | +| StringLiterals.java:41:3:43:5 | """\n\t\t\tindented\n\t\t""" | \tindented\n | \tindented\n | text-block | +| StringLiterals.java:44:3:46:5 | """\n\tno indentation last line\n\t\t""" | no indentation last line\n | no indentation last line\n | text-block | +| StringLiterals.java:47:3:49:7 | """\n\tindentation last line\n\t\t\\s""" | indentation last line\n\t | indentation last line\n\t | text-block | +| StringLiterals.java:50:3:52:6 | """\n\t\t\tnot-indented\n\t\t\t""" | not-indented\n | not-indented\n | text-block | +| StringLiterals.java:53:3:55:4 | """\n\t\tindented\n\t""" | \tindented\n | \tindented\n | text-block | +| StringLiterals.java:56:4:58:5 | """\n\t\tnot-indented\n\t\t""" | not-indented\n | not-indented\n | text-block | +| StringLiterals.java:59:3:62:6 | """\n\t\t spaces (only single space is trimmed)\n\t\t\ttab\n\t\t\t""" | spaces (only single space is trimmed)\ntab\n | spaces (only single space is trimmed)\ntab\n | text-block | +| StringLiterals.java:63:3:64:22 | """\n\t\t\tend on same line""" | end on same line | end on same line | text-block | +| StringLiterals.java:65:3:68:5 | """\n\t\ttrailing spaces ignored: \t \n\t\tnot ignored: \t \\s\n\t\t""" | trailing spaces ignored:\nnot ignored: \t \n | trailing spaces ignored:\nnot ignored: \t \n | text-block | +| StringLiterals.java:69:3:70:18 | """\n\t\t3 quotes:""\\"""" | 3 quotes:""" | 3 quotes:""" | text-block | +| StringLiterals.java:71:3:74:5 | """\n\t\tline \\\n\t\tcontinuation \\\n\t\t""" | line continuation | line continuation | text-block | +| StringLiterals.java:75:3:79:5 | """\n\t\tExplicit line breaks:\\n\n\t\t\\r\\n\n\t\t\\r\n\t\t""" | Explicit line breaks:\n\n\r\n\n\r\n | Explicit line breaks:\n\n\r\n\n\r\n | text-block | +| StringLiterals.java:82:10:84:16 | 2"\\u0022\n\t\ttest\n\t\t\\u0022\\uu0022" | test\n | test\n | | +| StringLiterals.java:90:3:90:19 | "hello" + "world" | helloworld | helloworld | | +| StringLiterals.java:91:3:92:20 | """\n\t\thello""" + "world" | helloworld | helloworld | text-block | +| StringLiterals.java:93:10:93:12 | "a" | a | a | | +| StringLiterals.java:94:3:94:5 | "a" | a | a | | +| StringLiterals.java:95:3:95:5 | "a" | a | a | | +| StringLiterals.java:96:7:96:9 | "a" | a | a | | +| StringLiterals.java:97:3:97:5 | "a" | a | a | | +| StringLiterals.java:98:10:98:12 | "a" | a | a | | +| StringLiterals.java:99:3:99:5 | "a" | a | a | | +| StringLiterals.java:100:9:100:11 | "a" | a | a | | diff --git a/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.ql b/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.ql index e2128e54e0e..4b754090ff5 100644 --- a/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.ql +++ b/java/ql/test/library-tests/literals/stringLiterals/stringLiterals.ql @@ -1,5 +1,7 @@ import semmle.code.java.Expr -from StringLiteral lit -where lit.getFile().(CompilationUnit).fromSource() -select lit, lit.getValue(), lit.getRepresentedString() +from StringLiteral lit, string isTextBlock +where + lit.getFile().(CompilationUnit).fromSource() and + if lit.isTextBlock() then isTextBlock = "text-block" else isTextBlock = "" +select lit, lit.getValue(), lit.getRepresentedString(), isTextBlock From 3463c28e2416f236ddd0acaac6f13492a77bee42 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Fri, 1 Oct 2021 18:27:46 +0200 Subject: [PATCH 108/361] C++: Add return value dereference to 'callOutput'. This will need to be modified once we get return value side effects in the IR. --- .../lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll index 2f4037d4ec8..c7e61ea2e33 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll @@ -38,5 +38,8 @@ Instruction callOutput(CallInstruction call, FunctionOutput output) { effect.getPrimaryInstruction() = call and output.isParameterDerefOrQualifierObject(effect.getIndex()) ) - // TODO: return value dereference + or + // TODO: modify this when we get return value dereferences + result = call and + output.isReturnValueDeref() } From 06791426074dfe3322bd36b223bed81ac886efbf Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Fri, 1 Oct 2021 18:27:55 +0200 Subject: [PATCH 109/361] C++: Accept test changes. --- .../taint-tests/copyableclass_declonly.cpp | 2 +- .../dataflow/taint-tests/map.cpp | 4 +- .../dataflow/taint-tests/string.cpp | 68 +++++++++---------- .../dataflow/taint-tests/stringstream.cpp | 16 ++--- .../dataflow/taint-tests/taint.cpp | 2 +- .../dataflow/taint-tests/vector.cpp | 16 ++--- 6 files changed, 54 insertions(+), 54 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/copyableclass_declonly.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/copyableclass_declonly.cpp index f8169db1128..307e1ecaa76 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/copyableclass_declonly.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/copyableclass_declonly.cpp @@ -64,6 +64,6 @@ void test_copyableclass_declonly() sink(s1); // $ ast,ir sink(s2); // $ ast,ir - sink(s3 = source()); // $ ast MISSING: ir + sink(s3 = source()); // $ ast,ir } } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index aabd898830e..4e85a6b9aa3 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -415,10 +415,10 @@ void test_unordered_map() sink(m30["abc"]); sink(m31.try_emplace("abc", source(), 2)); // $ ast,ir sink(m31); // $ ast,ir - sink(m31["abc"]); // $ ast MISSING: ir + sink(m31["abc"]); // $ ast,ir sink(m32.try_emplace("abc", 1, source())); // $ ast,ir sink(m32); // $ ast,ir - sink(m32["abc"]); // $ ast MISSING: ir + sink(m32["abc"]); // $ ast,ir // additional emplace test cases std::unordered_map<char *, char *> m33; diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 0e29d314887..9ce653c654a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -30,20 +30,20 @@ void test_string() sink(b); sink(c); // $ ast,ir sink(b.c_str()); - sink(c.c_str()); // $ ast MISSING: ir + sink(c.c_str()); // $ ast,ir } void test_strings2() { string path1 = user_input(); - sink(path1.c_str(), "r"); // $ ast MISSING: ir + sink(path1.c_str(), "r"); // $ ast,ir string path2; path2 = user_input(); - sink(path2.c_str(), "r"); // $ ast MISSING: ir + sink(path2.c_str(), "r"); // $ ast,ir string path3(user_input()); - sink(path3.c_str(), "r"); // $ ast MISSING: ir + sink(path3.c_str(), "r"); // $ ast,ir } void test_string3() @@ -67,7 +67,7 @@ void test_string4() // convert back std::string -> char * cs = ss.c_str(); - sink(cs); // $ ast MISSING: ir + sink(cs); // $ ast,ir sink(ss); // $ ast,ir } @@ -159,12 +159,12 @@ void test_string_append() { sink(s5); // $ ast,ir s6 = s3; - sink(s6 += s4); // $ ast MISSING: ir + sink(s6 += s4); // $ ast,ir sink(s6); // $ ast,ir s7 = s3; - sink(s7 += source()); // $ ast MISSING: ir - sink(s7 += " "); // $ ast MISSING: ir + sink(s7 += source()); // $ ast,ir + sink(s7 += " "); // $ ast,ir sink(s7); // $ ast,ir s8 = s3; @@ -196,10 +196,10 @@ void test_string_assign() { sink(s3.assign(s1)); sink(s3); - sink(s4.assign(s2)); // $ ast MISSING: ir + sink(s4.assign(s2)); // $ ast,ir sink(s4); // $ ast,ir - sink(s5.assign(10, c)); // $ ast MISSING: ir + sink(s5.assign(10, c)); // $ ast,ir sink(s5); // $ ast,ir sink(s6.assign(s1)); @@ -217,15 +217,15 @@ void test_string_insert() { sink(s3); s4 = s2; - sink(s4.insert(0, s1)); // $ ast MISSING: ir + sink(s4.insert(0, s1)); // $ ast,ir sink(s4); // $ ast,ir s5 = s1; - sink(s5.insert(0, s2)); // $ ast MISSING: ir + sink(s5.insert(0, s2)); // $ ast,ir sink(s5); // $ ast,ir s6 = s1; - sink(s6.insert(0, 10, c)); // $ ast MISSING: ir + sink(s6.insert(0, 10, c)); // $ ast,ir sink(s6); // $ ast,ir } @@ -240,15 +240,15 @@ void test_string_replace() { sink(s3); s4 = s2; - sink(s4.replace(1, 2, s1)); // $ ast MISSING: ir + sink(s4.replace(1, 2, s1)); // $ ast,ir sink(s4); // $ ast,ir s5 = s1; - sink(s5.replace(1, 2, s2)); // $ ast MISSING: ir + sink(s5.replace(1, 2, s2)); // $ ast,ir sink(s5); // $ ast,ir s6 = s1; - sink(s6.replace(1, 2, 10, c)); // $ ast MISSING: ir + sink(s6.replace(1, 2, 10, c)); // $ ast,ir sink(s6); // $ ast,ir } @@ -309,7 +309,7 @@ void test_string_data() std::string b(source()); sink(a.data()); - sink(b.data()); // $ ast MISSING: ir + sink(b.data()); // $ ast,ir sink(a.length()); sink(b.length()); } @@ -360,7 +360,7 @@ void test_string_iterators() { std::string s4("world"); sink(s1); - sink(s1.append(s2.begin(), s2.end())); // $ ast MISSING: ir + sink(s1.append(s2.begin(), s2.end())); // $ ast,ir sink(s1); // $ ast,ir sink(s3); @@ -433,7 +433,7 @@ void test_string_insert_more() sink(s1.insert(0, cs1)); sink(s1); - sink(s2.insert(0, cs2)); // $ ast MISSING: ir + sink(s2.insert(0, cs2)); // $ ast,ir sink(s2); // $ ast,ir } @@ -446,7 +446,7 @@ void test_string_iterator_methods() sink(a.insert(a.begin(), 10, 'x')); sink(a); - sink(b.insert(b.begin(), 10, ns_char::source())); // $ ast MISSING: ir + sink(b.insert(b.begin(), 10, ns_char::source())); // $ ast,ir sink(b); // $ ast,ir } @@ -459,10 +459,10 @@ void test_string_iterator_methods() sink(c.insert(c.end(), s1.begin(), s1.end())); sink(c); - sink(d.insert(d.end(), s2.begin(), s2.end())); // $ ast MISSING: ir + sink(d.insert(d.end(), s2.begin(), s2.end())); // $ ast,ir sink(d); // $ ast,ir - sink(s2.insert(s2.end(), s1.begin(), s1.end())); // $ ast MISSING: ir + sink(s2.insert(s2.end(), s1.begin(), s1.end())); // $ ast,ir sink(s2); // $ ast,ir } @@ -475,10 +475,10 @@ void test_string_iterator_methods() sink(e.append(s3.begin(), s3.end())); sink(e); - sink(f.append(s4.begin(), s4.end())); // $ ast MISSING: ir + sink(f.append(s4.begin(), s4.end())); // $ ast,ir sink(f); // $ ast,ir - sink(s4.append(s3.begin(), s3.end())); // $ ast MISSING: ir + sink(s4.append(s3.begin(), s3.end())); // $ ast,ir sink(s4); // $ ast,ir } @@ -491,7 +491,7 @@ void test_string_iterator_methods() sink(g.assign(s5.cbegin(), s5.cend())); sink(g); - sink(h.assign(s6.cbegin(), s6.cend())); // $ ast MISSING: ir + sink(h.assign(s6.cbegin(), s6.cend())); // $ ast,ir sink(h); // $ ast,ir sink(s6.assign(s5.cbegin(), s5.cend())); @@ -519,8 +519,8 @@ void test_string_front_back() { sink(a.front()); sink(a.back()); a.push_back(ns_char::source()); - sink(a.front()); // $ SPURIOUS: ast - sink(a.back()); // $ ast MISSING: ir + sink(a.front()); // $ SPURIOUS: ast,ir + sink(a.back()); // $ ast,ir } void test_string_return_assign() { @@ -533,12 +533,12 @@ void test_string_return_assign() { std::string f("ff"); sink( a += (b += "bb") ); - sink( c += (d += source()) ); // $ ast MISSING: ir - sink( (e += "ee") += source() ); // $ ast MISSING: ir - sink( (f += source()) += "ff" ); // $ ast MISSING: ir + sink( c += (d += source()) ); // $ ast,ir + sink( (e += "ee") += source() ); // $ ast,ir + sink( (f += source()) += "ff" ); // $ ast,ir sink(a); sink(b); - sink(c); // $ ast MISSING: ir + sink(c); // $ ast,ir sink(d); // $ ast,ir sink(e); // $ ast MISSING: ir sink(f); // $ ast,ir @@ -553,12 +553,12 @@ void test_string_return_assign() { std::string f("ff"); sink( a.assign(b.assign("bb")) ); - sink( c.assign(d.assign(source())) ); // $ ast MISSING: ir - sink( e.assign("ee").assign(source()) ); // $ ast MISSING: ir + sink( c.assign(d.assign(source())) ); // $ ast,ir + sink( e.assign("ee").assign(source()) ); // $ ast,ir sink( f.assign(source()).assign("ff") ); sink(a); sink(b); - sink(c); // $ ast MISSING: ir + sink(c); // $ ast,ir sink(d); // $ ast,ir sink(e); // $ ast MISSING: ir sink(f); // $ SPURIOUS: ast,ir diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp index fab96fc878d..249c8ac21bf 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -53,15 +53,15 @@ void test_stringstream_string(int amount) sink(ss7); // $ SPURIOUS: ast,ir sink(ss8.put('a')); - sink(ss9.put(ns_char::source())); // $ ast MISSING: ir - sink(ss10.put('a').put(ns_char::source()).put('z')); // $ ast MISSING: ir + sink(ss9.put(ns_char::source())); // $ ast,ir + sink(ss10.put('a').put(ns_char::source()).put('z')); // $ ast,ir sink(ss8); sink(ss9); // $ ast,ir sink(ss10); // $ ast MISSING: ir sink(ss11.write("begin", 5)); - sink(ss12.write(source(), 5)); // $ ast MISSING: ir - sink(ss13.write("begin", 5).write(source(), amount).write("end", 3)); // $ ast MISSING: ir + sink(ss12.write(source(), 5)); // $ ast,ir + sink(ss13.write("begin", 5).write(source(), amount).write("end", 3)); // $ ast,ir sink(ss11); sink(ss12); // $ ast,ir sink(ss13); // $ ast MISSING: ir @@ -73,7 +73,7 @@ void test_stringstream_int(int source) int v1 = 0, v2 = 0; sink(ss1 << 1234); - sink(ss2 << source); // $ ast MISSING: ir + sink(ss2 << source); // $ ast,ir sink(ss1 >> v1); sink(ss2 >> v2); // $ ast,ir @@ -97,7 +97,7 @@ void test_stringstream_constructors() std::stringstream ss6; sink(ss5 = std::stringstream("abc")); - sink(ss6 = std::stringstream(source())); // $ ast MISSING: ir + sink(ss6 = std::stringstream(source())); // $ ast,ir sink(ss1); sink(ss2); // $ ast,ir @@ -193,7 +193,7 @@ void test_stringstream_putback() sink(ss.get()); sink(ss.putback('b')); sink(ss.get()); - sink(ss.putback(ns_char::source())); // $ ast MISSING: ir + sink(ss.putback(ns_char::source())); // $ ast,ir sink(ss.get()); // $ ast,ir } @@ -263,6 +263,6 @@ void test_chaining() sink(b1); // $ ast,ir sink(b2); // $ ast,ir - sink(ss2.write("abc", 3).flush().write(source(), 3).flush().write("xyz", 3)); // $ ast MISSING: ir + sink(ss2.write("abc", 3).flush().write(source(), 3).flush().write("xyz", 3)); // $ ast,ir sink(ss2); // $ ast MISSING: ir } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index 9434dbe52ae..92a44f2950c 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -466,7 +466,7 @@ void test_qualifiers() sink(d.getString()); d.setString(strings::source()); sink(d); // $ ast,ir - sink(d.getString()); // $ ast MISSING: ir + sink(d.getString()); // $ ast,ir } // --- non-standard swap --- diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index 4f0c8fab414..aacef1f4a5b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -68,8 +68,8 @@ void test_element_taint(int x) { v5.push_back(source()); sink(v5); // $ ast,ir - sink(v5.front()); // $ SPURIOUS: ast - sink(v5.back()); // $ ast MISSING: ir + sink(v5.front()); // $ SPURIOUS: ast,ir + sink(v5.back()); // $ ast,ir v6.data()[2] = source(); sink(v6); // $ ast MISSING: ir @@ -81,8 +81,8 @@ void test_element_taint(int x) { v7.insert(it, source()); } sink(v7); // $ ast,ir - sink(v7.front()); // $ ast MISSING: ir - sink(v7.back()); // $ SPURIOUS: ast + sink(v7.front()); // $ ast,ir + sink(v7.back()); // $ SPURIOUS: ast,ir { const std::vector<int> &v8c = v8; @@ -283,8 +283,8 @@ void test_data_more() { v1.push_back(source()); sink(v1); // $ ast,ir - sink(v1.data()); // $ ast MISSING: ir - sink(v1.data()[2]); // $ ast MISSING: ir + sink(v1.data()); // $ ast,ir + sink(v1.data()[2]); // $ ast,ir *(v2.data()) = ns_int::source(); sink(v2); // $ ast MISSING: ir @@ -305,10 +305,10 @@ void test_vector_insert() { sink(a.insert(a.end(), b.begin(), b.end())); sink(a); - sink(c.insert(c.end(), d.begin(), d.end())); // $ ast MISSING: ir + sink(c.insert(c.end(), d.begin(), d.end())); // $ ast,ir sink(c); // $ ast,ir - sink(d.insert(d.end(), a.begin(), a.end())); // $ ast MISSING: ir + sink(d.insert(d.end(), a.begin(), a.end())); // $ ast,ir sink(d); // $ ast,ir } From b9a1a451a9471a3988b3cfff1b002822b72745e1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Oct 2021 19:21:30 +0100 Subject: [PATCH 110/361] C++: Autoformat. --- cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll index 42c9fa01f89..71569cc89e5 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll @@ -65,7 +65,9 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) { exists(AsmStmt s | s.getEnclosingFunction() = f) or // function where the relevant parameter is returned (leaking it) - exists(ReturnStmt rs | rs.getEnclosingFunction() = f and rs.getExpr().getAChild*() = f.getParameter(i).getAnAccess()) + exists(ReturnStmt rs | + rs.getEnclosingFunction() = f and rs.getExpr().getAChild*() = f.getParameter(i).getAnAccess() + ) ) or // Call without target (e.g., function pointer call) From cc8b581c0615c757e1af1de0eb0c8aa13f688488 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Fri, 1 Oct 2021 22:23:17 +0200 Subject: [PATCH 111/361] C++: Accept test changes. --- .../semmle/ExecTainted/ExecTainted.expected | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected index 72dfd5e7967..4b1b5a61ace 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected @@ -20,8 +20,17 @@ edges | test.cpp:93:17:93:24 | filename indirection | test.cpp:93:11:93:14 | strncat output argument | | test.cpp:93:17:93:24 | filename indirection | test.cpp:93:11:93:14 | strncat output argument | | test.cpp:106:20:106:25 | call to getenv | test.cpp:107:33:107:36 | path indirection | +| test.cpp:107:31:107:31 | call to operator+ | test.cpp:108:18:108:22 | call to c_str indirection | +| test.cpp:107:33:107:36 | path indirection | test.cpp:107:31:107:31 | call to operator+ | +| test.cpp:107:33:107:36 | path indirection | test.cpp:107:31:107:31 | call to operator+ | | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | path indirection | +| test.cpp:114:17:114:17 | Call | test.cpp:114:25:114:29 | call to c_str indirection | +| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | Call | +| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | Call | | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | path indirection | +| test.cpp:120:17:120:17 | Call | test.cpp:120:10:120:30 | call to data indirection | +| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | Call | +| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | Call | | test.cpp:140:9:140:11 | fread output argument | test.cpp:142:31:142:33 | str indirection | | test.cpp:142:11:142:17 | sprintf output argument | test.cpp:143:10:143:16 | command indirection | | test.cpp:142:31:142:33 | str indirection | test.cpp:142:11:142:17 | sprintf output argument | @@ -48,10 +57,16 @@ nodes | test.cpp:93:17:93:24 | filename indirection | semmle.label | filename indirection | | test.cpp:94:45:94:48 | path indirection | semmle.label | path indirection | | test.cpp:106:20:106:25 | call to getenv | semmle.label | call to getenv | +| test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ | | test.cpp:107:33:107:36 | path indirection | semmle.label | path indirection | +| test.cpp:108:18:108:22 | call to c_str indirection | semmle.label | call to c_str indirection | | test.cpp:113:20:113:25 | call to getenv | semmle.label | call to getenv | +| test.cpp:114:17:114:17 | Call | semmle.label | Call | | test.cpp:114:19:114:22 | path indirection | semmle.label | path indirection | +| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection | | test.cpp:119:20:119:25 | call to getenv | semmle.label | call to getenv | +| test.cpp:120:10:120:30 | call to data indirection | semmle.label | call to data indirection | +| test.cpp:120:17:120:17 | Call | semmle.label | Call | | test.cpp:120:19:120:22 | path indirection | semmle.label | path indirection | | test.cpp:140:9:140:11 | fread output argument | semmle.label | fread output argument | | test.cpp:142:11:142:17 | sprintf output argument | semmle.label | sprintf output argument | @@ -64,4 +79,7 @@ subpaths | test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:62:9:62:16 | fread output argument | user input (String read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument | | test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:82:9:82:16 | fread output argument | user input (String read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument | | test.cpp:94:45:94:48 | path | test.cpp:91:9:91:16 | fread output argument | test.cpp:94:45:94:48 | path indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:91:9:91:16 | fread output argument | user input (String read by fread) | test.cpp:93:11:93:14 | strncat output argument | strncat output argument | +| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:25 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:106:20:106:25 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ | +| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | Call | Call | +| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:119:20:119:25 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | Call | Call | | test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:140:9:140:11 | fread output argument | user input (String read by fread) | test.cpp:142:11:142:17 | sprintf output argument | sprintf output argument | From 25792b2a4537a5ecce7431b871fa68ce095b3c9d Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan <owen-mc@github.com> Date: Sat, 2 Oct 2021 08:04:17 +0100 Subject: [PATCH 112/361] Change class name to avoid clash with Go and Javascript libraries --- cpp/ql/test/TestUtilities/InlineExpectationsTest.qll | 10 +++++----- .../TestUtilities/InlineExpectationsTestPrivate.qll | 6 +++--- java/ql/test/TestUtilities/InlineExpectationsTest.qll | 10 +++++----- .../TestUtilities/InlineExpectationsTestPrivate.qll | 4 ++-- .../ql/test/TestUtilities/InlineExpectationsTest.qll | 10 +++++----- .../TestUtilities/InlineExpectationsTestPrivate.qll | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/cpp/ql/test/TestUtilities/InlineExpectationsTest.qll b/cpp/ql/test/TestUtilities/InlineExpectationsTest.qll index d351bac89a8..37224a9af8b 100644 --- a/cpp/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/cpp/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -4,7 +4,7 @@ * (in that the `.expected` file should always be empty). * * To add this framework to a new language: - * - Add a file `InlineExpectationsTestPrivate.qll` that defines a `LineComment` class. This class + * - Add a file `InlineExpectationsTestPrivate.qll` that defines a `ExpectationComment` class. This class * must support a `getContents` method that returns the contents of the given comment, _excluding_ * the comment indicator itself. It should also define `toString` and `getLocation` as usual. * @@ -194,7 +194,7 @@ private int getEndOfColumnPosition(int start, string content) { } private predicate getAnExpectation( - LineComment comment, TColumn column, string expectation, string tags, string value + ExpectationComment comment, TColumn column, string expectation, string tags, string value ) { exists(string content | content = comment.getContents().regexpCapture(expectationCommentPattern(), 1) and @@ -247,14 +247,14 @@ private newtype TFailureLocatable = ) { test.hasActualResult(location, element, tag, value) } or - TValidExpectation(LineComment comment, string tag, string value, string knownFailure) { + TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) { exists(TColumn column, string tags | getAnExpectation(comment, column, _, tags, value) and tag = tags.splitAt(",") and knownFailure = getColumnString(column) ) } or - TInvalidExpectation(LineComment comment, string expectation) { + TInvalidExpectation(ExpectationComment comment, string expectation) { getAnExpectation(comment, _, expectation, _, _) and not expectation.regexpMatch(expectationPattern()) } @@ -292,7 +292,7 @@ class ActualResult extends FailureLocatable, TActualResult { } abstract private class Expectation extends FailureLocatable { - LineComment comment; + ExpectationComment comment; override string toString() { result = comment.toString() } diff --git a/cpp/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll b/cpp/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll index f3aae029eb4..adad4238095 100644 --- a/cpp/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll +++ b/cpp/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll @@ -1,16 +1,16 @@ import cpp -private newtype TLineComment = MkLineComment(CppStyleComment c) +private newtype TExpectationComment = MkExpectationComment(CppStyleComment c) /** * Represents a line comment in the CPP style. * Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_ * include the preceding comment marker (`//`). */ -class LineComment extends TLineComment { +class ExpectationComment extends TExpectationComment { CppStyleComment comment; - LineComment() { this = MkLineComment(comment) } + ExpectationComment() { this = MkExpectationComment(comment) } /** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */ string getContents() { result = comment.getContents().suffix(2) } diff --git a/java/ql/test/TestUtilities/InlineExpectationsTest.qll b/java/ql/test/TestUtilities/InlineExpectationsTest.qll index d351bac89a8..37224a9af8b 100644 --- a/java/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/java/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -4,7 +4,7 @@ * (in that the `.expected` file should always be empty). * * To add this framework to a new language: - * - Add a file `InlineExpectationsTestPrivate.qll` that defines a `LineComment` class. This class + * - Add a file `InlineExpectationsTestPrivate.qll` that defines a `ExpectationComment` class. This class * must support a `getContents` method that returns the contents of the given comment, _excluding_ * the comment indicator itself. It should also define `toString` and `getLocation` as usual. * @@ -194,7 +194,7 @@ private int getEndOfColumnPosition(int start, string content) { } private predicate getAnExpectation( - LineComment comment, TColumn column, string expectation, string tags, string value + ExpectationComment comment, TColumn column, string expectation, string tags, string value ) { exists(string content | content = comment.getContents().regexpCapture(expectationCommentPattern(), 1) and @@ -247,14 +247,14 @@ private newtype TFailureLocatable = ) { test.hasActualResult(location, element, tag, value) } or - TValidExpectation(LineComment comment, string tag, string value, string knownFailure) { + TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) { exists(TColumn column, string tags | getAnExpectation(comment, column, _, tags, value) and tag = tags.splitAt(",") and knownFailure = getColumnString(column) ) } or - TInvalidExpectation(LineComment comment, string expectation) { + TInvalidExpectation(ExpectationComment comment, string expectation) { getAnExpectation(comment, _, expectation, _, _) and not expectation.regexpMatch(expectationPattern()) } @@ -292,7 +292,7 @@ class ActualResult extends FailureLocatable, TActualResult { } abstract private class Expectation extends FailureLocatable { - LineComment comment; + ExpectationComment comment; override string toString() { result = comment.toString() } diff --git a/java/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll b/java/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll index e2c0e0091ba..1ee16e93d10 100644 --- a/java/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll +++ b/java/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll @@ -4,8 +4,8 @@ import java * A class representing line comments in Java, which is simply Javadoc restricted * to EOL comments, with an extra accessor used by the InlineExpectations core code */ -class LineComment extends Javadoc { - LineComment() { isEolComment(this) } +class ExpectationComment extends Javadoc { + ExpectationComment() { isEolComment(this) } /** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */ string getContents() { result = this.getChild(0).toString() } diff --git a/python/ql/test/TestUtilities/InlineExpectationsTest.qll b/python/ql/test/TestUtilities/InlineExpectationsTest.qll index d351bac89a8..37224a9af8b 100644 --- a/python/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/python/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -4,7 +4,7 @@ * (in that the `.expected` file should always be empty). * * To add this framework to a new language: - * - Add a file `InlineExpectationsTestPrivate.qll` that defines a `LineComment` class. This class + * - Add a file `InlineExpectationsTestPrivate.qll` that defines a `ExpectationComment` class. This class * must support a `getContents` method that returns the contents of the given comment, _excluding_ * the comment indicator itself. It should also define `toString` and `getLocation` as usual. * @@ -194,7 +194,7 @@ private int getEndOfColumnPosition(int start, string content) { } private predicate getAnExpectation( - LineComment comment, TColumn column, string expectation, string tags, string value + ExpectationComment comment, TColumn column, string expectation, string tags, string value ) { exists(string content | content = comment.getContents().regexpCapture(expectationCommentPattern(), 1) and @@ -247,14 +247,14 @@ private newtype TFailureLocatable = ) { test.hasActualResult(location, element, tag, value) } or - TValidExpectation(LineComment comment, string tag, string value, string knownFailure) { + TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) { exists(TColumn column, string tags | getAnExpectation(comment, column, _, tags, value) and tag = tags.splitAt(",") and knownFailure = getColumnString(column) ) } or - TInvalidExpectation(LineComment comment, string expectation) { + TInvalidExpectation(ExpectationComment comment, string expectation) { getAnExpectation(comment, _, expectation, _, _) and not expectation.regexpMatch(expectationPattern()) } @@ -292,7 +292,7 @@ class ActualResult extends FailureLocatable, TActualResult { } abstract private class Expectation extends FailureLocatable { - LineComment comment; + ExpectationComment comment; override string toString() { result = comment.toString() } diff --git a/python/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll b/python/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll index aaea45a3cce..9c2ca9335e3 100644 --- a/python/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll +++ b/python/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll @@ -4,4 +4,4 @@ import python * A class representing line comments in Python. As this is the only form of comment Python * permits, we simply reuse the `Comment` class. */ -class LineComment = Comment; +class ExpectationComment = Comment; From 938d003e5e8d9d9324dd3e5347e7fba211190ad3 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan <owen-mc@github.com> Date: Sat, 2 Oct 2021 08:11:49 +0100 Subject: [PATCH 113/361] Fix example to use space after $ for consistency --- cpp/ql/test/TestUtilities/InlineExpectationsTest.qll | 4 ++-- java/ql/test/TestUtilities/InlineExpectationsTest.qll | 4 ++-- python/ql/test/TestUtilities/InlineExpectationsTest.qll | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/TestUtilities/InlineExpectationsTest.qll b/cpp/ql/test/TestUtilities/InlineExpectationsTest.qll index 37224a9af8b..52a790cca28 100644 --- a/cpp/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/cpp/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -60,8 +60,8 @@ * * Example: * ```cpp - * int i = x + 5; // $const=5 - * int j = y + (7 - 3) // $const=7 const=3 const=4 // The result of the subtraction is a constant. + * int i = x + 5; // $ const=5 + * int j = y + (7 - 3) // $ const=7 const=3 const=4 // The result of the subtraction is a constant. * ``` * * For tests that contain known missing and spurious results, it is possible to further diff --git a/java/ql/test/TestUtilities/InlineExpectationsTest.qll b/java/ql/test/TestUtilities/InlineExpectationsTest.qll index 37224a9af8b..52a790cca28 100644 --- a/java/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/java/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -60,8 +60,8 @@ * * Example: * ```cpp - * int i = x + 5; // $const=5 - * int j = y + (7 - 3) // $const=7 const=3 const=4 // The result of the subtraction is a constant. + * int i = x + 5; // $ const=5 + * int j = y + (7 - 3) // $ const=7 const=3 const=4 // The result of the subtraction is a constant. * ``` * * For tests that contain known missing and spurious results, it is possible to further diff --git a/python/ql/test/TestUtilities/InlineExpectationsTest.qll b/python/ql/test/TestUtilities/InlineExpectationsTest.qll index 37224a9af8b..52a790cca28 100644 --- a/python/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/python/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -60,8 +60,8 @@ * * Example: * ```cpp - * int i = x + 5; // $const=5 - * int j = y + (7 - 3) // $const=7 const=3 const=4 // The result of the subtraction is a constant. + * int i = x + 5; // $ const=5 + * int j = y + (7 - 3) // $ const=7 const=3 const=4 // The result of the subtraction is a constant. * ``` * * For tests that contain known missing and spurious results, it is possible to further From fb1385b3e8e2403a52d5ac15e4266263493cf565 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Sun, 3 Oct 2021 00:13:36 +0200 Subject: [PATCH 114/361] Java: Fix formatting of SpuriousJavadocParam.java --- java/ql/src/Advisory/Documentation/SpuriousJavadocParam.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Advisory/Documentation/SpuriousJavadocParam.java b/java/ql/src/Advisory/Documentation/SpuriousJavadocParam.java index 20513b19a9c..bef5de55717 100644 --- a/java/ql/src/Advisory/Documentation/SpuriousJavadocParam.java +++ b/java/ql/src/Advisory/Documentation/SpuriousJavadocParam.java @@ -44,7 +44,7 @@ public <T> void parameterized(T parameter){ ... } * * @param <X> The type of the elements. */ -class Generic<T> { ...} +class Generic<T> { ... } /** * GOOD: A proper Javadoc comment. From 682a2aae3a1dcedd18bde3cc56f8a7e668cff491 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 4 Oct 2021 10:45:44 +0200 Subject: [PATCH 115/361] C#: Filter `using var _ = ...` results from `DeadStoreOfLocal.ql` --- csharp/ql/src/Dead Code/DeadStoreOfLocal.ql | 7 ++++++- .../Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs | 6 ++++++ .../Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql index 1064a76c2e0..42aa3cac428 100644 --- a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql +++ b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql @@ -72,7 +72,12 @@ predicate mayEscape(LocalVariable v) { class RelevantDefinition extends AssignableDefinition { RelevantDefinition() { - this instanceof AssignableDefinitions::AssignmentDefinition + this.(AssignableDefinitions::AssignmentDefinition).getAssignment() = + any(Assignment a | + if a = any(UsingStmt us).getAVariableDeclExpr() + then not a.getTargetVariable().hasName("_") + else any() + ) or this instanceof AssignableDefinitions::MutationDefinition or diff --git a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs index 289ffed7953..074c07b1878 100644 --- a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs +++ b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs @@ -460,4 +460,10 @@ public static class AnonymousVariable count++; return count; } + + public static void Using() + { + using var x = new System.IO.FileStream("", System.IO.FileMode.Open); // BAD + using var _ = new System.IO.FileStream("", System.IO.FileMode.Open); // GOOD + } } diff --git a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected index ab6a47ca9ed..0b0c265f0ff 100644 --- a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected +++ b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected @@ -14,6 +14,7 @@ | DeadStoreOfLocal.cs:331:9:331:32 | ... = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:327:23:327:23 | b | b | | DeadStoreOfLocal.cs:372:13:372:20 | String s = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:372:13:372:13 | s | s | | DeadStoreOfLocal.cs:398:13:398:21 | ... = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:396:13:396:13 | s | s | +| DeadStoreOfLocal.cs:466:19:466:75 | FileStream x = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:466:19:466:19 | x | x | | DeadStoreOfLocalBad.cs:7:13:7:48 | Boolean success = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocalBad.cs:7:13:7:19 | success | success | | DeadStoreOfLocalBad.cs:23:32:23:32 | FormatException e | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocalBad.cs:23:32:23:32 | e | e | | DeadStoreOfLocalBad.cs:32:22:32:22 | String s | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocalBad.cs:32:22:32:22 | s | s | From 70b9b002cb6a31096d2cfc96baa77d807e1906b4 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 4 Oct 2021 10:47:44 +0200 Subject: [PATCH 116/361] C#: Add change note --- csharp/change-notes/2021-10-04-dead-store-of-local.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 csharp/change-notes/2021-10-04-dead-store-of-local.md diff --git a/csharp/change-notes/2021-10-04-dead-store-of-local.md b/csharp/change-notes/2021-10-04-dead-store-of-local.md new file mode 100644 index 00000000000..bb186924ce8 --- /dev/null +++ b/csharp/change-notes/2021-10-04-dead-store-of-local.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Discarded `using` declarationg, `using var _ = ...`, are no longer flagged by the query "Useless assignment to local variable". From 4521a9fdf0af2aa74b9fe85834cd82b437288d13 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Mon, 4 Oct 2021 11:36:53 +0200 Subject: [PATCH 117/361] Update python/ql/lib/semmle/python/frameworks/Stdlib.qll Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> --- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 0239b726cef..61b307bf51b 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -222,9 +222,7 @@ private module StdlibPrivate { // these check if the file exists "exists", "lexists", "isfile", "isdir", "islink", "ismount", // these raise errors if the file does not exist - "getatime", "getmtime", "getctime", "getsize", - // this will resolve symlinks - "realpath" + "getatime", "getmtime", "getctime", "getsize" ]) .getACall() } From aa91c267925868f852fc1b39772bffbf9d884b89 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Mon, 4 Oct 2021 12:12:07 +0200 Subject: [PATCH 118/361] Python: Add missing taint steps --- .../lib/semmle/python/frameworks/Stdlib.qll | 76 +++++++++++-------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 61b307bf51b..04f3bdf8d7b 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -243,6 +243,52 @@ private module StdlibPrivate { } } + // Functions with non-standard arguments: + // - os.path.join(path, *paths) + // - os.path.relpath(path, start=os.curdir) + // Functions that need summaries: + // - os.path.commonpath(paths): takes a sequence + // - os.path.commonprefix(list): takes a list argument + // - os.path.splitdrive: retunrs a tuple + // - os.path.splittext: returns a tuple + private string pathComputation() { + result in [ + "abspath", "basename", "commonpath", "dirname", "expanduser", "expandvars", "join", + "normcase", "normpath", "realpath", "relpath", "split" + ] + } + + /** + * The `os.path` module offers a number of methods for computing new paths from existing paths. + * These should all propagate taint. + */ + private class OsPathComputation extends DataFlow::CallCfgNode { + string methodName; + + OsPathComputation() { + methodName = pathComputation() and + this = os::path().getMember(methodName).getACall() + } + + DataFlow::Node getPathArg() { + result in [this.getArg(0), this.getArgByName("path")] + or + methodName = "join" and result = this.getArg(_) + or + methodName = "relpath" and result in [this.getArg(1), this.getArgByName("start")] + } + } + + /** An additional taint step for path computations. */ + private class OsPathComputationAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + exists(OsPathComputation call | + nodeTo = call and + nodeFrom = call.getPathArg() + ) + } + } + /** * A call to `os.path.normpath`. * See https://docs.python.org/3/library/os.path.html#os.path.normpath @@ -253,16 +299,6 @@ private module StdlibPrivate { DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] } } - /** An additional taint step for calls to `os.path.normpath` */ - private class OsPathNormpathCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { - override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - exists(OsPathNormpathCall call | - nodeTo = call and - nodeFrom = call.getPathArg() - ) - } - } - /** * A call to `os.path.abspath`. * See https://docs.python.org/3/library/os.path.html#os.path.abspath @@ -273,16 +309,6 @@ private module StdlibPrivate { DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] } } - /** An additional taint step for calls to `os.path.abspath` */ - private class OsPathAbspathCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { - override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - exists(OsPathAbspathCall call | - nodeTo = call and - nodeFrom = call.getPathArg() - ) - } - } - /** * A call to `os.path.realpath`. * See https://docs.python.org/3/library/os.path.html#os.path.realpath @@ -293,16 +319,6 @@ private module StdlibPrivate { DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] } } - /** An additional taint step for calls to `os.path.realpath` */ - private class OsPathRealpathCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { - override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - exists(OsPathRealpathCall call | - nodeTo = call and - nodeFrom = call.getPathArg() - ) - } - } - /** * A call to `os.system`. * See https://docs.python.org/3/library/os.html#os.system From f06632a8e7a25059546594720572ed3fc69e9dfd Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 4 Oct 2021 12:00:35 +0200 Subject: [PATCH 119/361] C#: Filter discards in tuples in `ConstantCondition.ql` --- .../2021-10-04-constand-condition.md | 2 + .../Control-Flow/ConstantCondition.ql | 2 + .../ConstantCondition/ConstantCondition.cs | 41 ++++++++++++------- .../ConstantCondition.expected | 4 +- 4 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 csharp/change-notes/2021-10-04-constand-condition.md diff --git a/csharp/change-notes/2021-10-04-constand-condition.md b/csharp/change-notes/2021-10-04-constand-condition.md new file mode 100644 index 00000000000..70ad5b5ea75 --- /dev/null +++ b/csharp/change-notes/2021-10-04-constand-condition.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Discards in tuple patterns, for example `(_, string s)`, are no longer flagged by the query "Constant condition". \ No newline at end of file diff --git a/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql b/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql index 0b4f4fd99b8..a0542a94735 100644 --- a/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql +++ b/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql @@ -123,6 +123,8 @@ class ConstantMatchingCondition extends ConstantCondition { se.getCase(i).getPattern() = this.(DiscardExpr) and i > 0 ) + or + this = any(PositionalPatternExpr ppe).getPattern(_) } override string getMessage() { diff --git a/csharp/ql/test/query-tests/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.cs b/csharp/ql/test/query-tests/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.cs index dd72191a29a..9e7386149a4 100644 --- a/csharp/ql/test/query-tests/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.cs +++ b/csharp/ql/test/query-tests/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.cs @@ -48,8 +48,8 @@ class ConstantNullness j = (int?)i ?? 1; // BAD s = ""?.CommaJoinWith(s); // BAD s = s ?? ""; // GOOD - s = (i==0 ? s : null) ?? s; // GOOD - var k = (i==0 ? s : null)?.Length; // GOOD + s = (i == 0 ? s : null) ?? s; // GOOD + var k = (i == 0 ? s : null)?.Length; // GOOD } } @@ -59,12 +59,12 @@ class ConstantMatching { switch (1 + 2) { - case 2 : // BAD - break; - case 3 : // BAD - break; - case int _ : // GOOD - break; + case 2: // BAD + break; + case 3: // BAD + break; + case int _: // GOOD + break; } } @@ -72,10 +72,10 @@ class ConstantMatching { switch ((object)s) { - case int _ : // BAD - break; - case "" : // GOOD - break; + case int _: // BAD + break; + case "": // GOOD + break; } } @@ -83,8 +83,8 @@ class ConstantMatching { switch (o) { - case IList _ : // GOOD - break; + case IList _: // GOOD + break; } } @@ -105,7 +105,8 @@ class ConstantMatching }; } - void M6(bool b1, bool b2) { + void M6(bool b1, bool b2) + { if (!b1) return; if (!b2) @@ -113,6 +114,16 @@ class ConstantMatching if (b1 && b2) // BAD return; } + + string M7(object o) + { + return o switch + { + (string s, _) => s, // GOOD + (_, string s) => s, // GOOD + _ => "" // GOOD + }; + } } class Assertions diff --git a/csharp/ql/test/query-tests/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.expected b/csharp/ql/test/query-tests/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.expected index f7ce6c1824a..17a51125c4c 100644 --- a/csharp/ql/test/query-tests/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.expected +++ b/csharp/ql/test/query-tests/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.expected @@ -8,8 +8,8 @@ | ConstantCondition.cs:64:18:64:18 | 3 | Pattern always matches. | | ConstantCondition.cs:75:18:75:20 | access to type Int32 | Pattern never matches. | | ConstantCondition.cs:95:13:95:13 | _ | Pattern always matches. | -| ConstantCondition.cs:113:13:113:14 | access to parameter b1 | Condition always evaluates to 'true'. | -| ConstantCondition.cs:113:19:113:20 | access to parameter b2 | Condition always evaluates to 'true'. | +| ConstantCondition.cs:114:13:114:14 | access to parameter b1 | Condition always evaluates to 'true'. | +| ConstantCondition.cs:114:19:114:20 | access to parameter b2 | Condition always evaluates to 'true'. | | ConstantConditionBad.cs:5:16:5:20 | ... > ... | Condition always evaluates to 'false'. | | ConstantConditionalExpressionCondition.cs:11:22:11:34 | ... == ... | Condition always evaluates to 'true'. | | ConstantConditionalExpressionCondition.cs:12:21:12:25 | false | Condition always evaluates to 'false'. | From a3156400829bc37b815df1a658722b2feffd32e3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 4 Oct 2021 13:15:26 +0200 Subject: [PATCH 120/361] C#: Address review comments --- .../2021-10-04-dead-store-of-local.md | 2 +- csharp/ql/src/Dead Code/DeadStoreOfLocal.ql | 6 +----- .../DeadStoreOfLocal/DeadStoreOfLocal.cs | 19 +++++++++++++------ .../DeadStoreOfLocal.expected | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/csharp/change-notes/2021-10-04-dead-store-of-local.md b/csharp/change-notes/2021-10-04-dead-store-of-local.md index bb186924ce8..307f10af654 100644 --- a/csharp/change-notes/2021-10-04-dead-store-of-local.md +++ b/csharp/change-notes/2021-10-04-dead-store-of-local.md @@ -1,2 +1,2 @@ lgtm,codescanning -* Discarded `using` declarationg, `using var _ = ...`, are no longer flagged by the query "Useless assignment to local variable". +* `using` declarations are no longer flagged by the query "Useless assignment to local variable". diff --git a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql index 42aa3cac428..19766a550ec 100644 --- a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql +++ b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql @@ -73,11 +73,7 @@ predicate mayEscape(LocalVariable v) { class RelevantDefinition extends AssignableDefinition { RelevantDefinition() { this.(AssignableDefinitions::AssignmentDefinition).getAssignment() = - any(Assignment a | - if a = any(UsingStmt us).getAVariableDeclExpr() - then not a.getTargetVariable().hasName("_") - else any() - ) + any(Assignment a | not a = any(UsingDeclStmt uds).getAVariableDeclExpr()) or this instanceof AssignableDefinitions::MutationDefinition or diff --git a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs index 074c07b1878..941981f6d6c 100644 --- a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs +++ b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs @@ -460,10 +460,17 @@ public static class AnonymousVariable count++; return count; } - - public static void Using() - { - using var x = new System.IO.FileStream("", System.IO.FileMode.Open); // BAD - using var _ = new System.IO.FileStream("", System.IO.FileMode.Open); // GOOD - } } + +public static class Using +{ + public static void M() + { + using var x = new System.IO.FileStream("", System.IO.FileMode.Open); // GOOD + using var _ = new System.IO.FileStream("", System.IO.FileMode.Open); // GOOD + + using (var y = new System.IO.FileStream("", System.IO.FileMode.Open)) // BAD + { + } + } +} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected index 0b0c265f0ff..6f718c49407 100644 --- a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected +++ b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected @@ -14,7 +14,7 @@ | DeadStoreOfLocal.cs:331:9:331:32 | ... = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:327:23:327:23 | b | b | | DeadStoreOfLocal.cs:372:13:372:20 | String s = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:372:13:372:13 | s | s | | DeadStoreOfLocal.cs:398:13:398:21 | ... = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:396:13:396:13 | s | s | -| DeadStoreOfLocal.cs:466:19:466:75 | FileStream x = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:466:19:466:19 | x | x | +| DeadStoreOfLocal.cs:472:20:472:76 | FileStream y = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:472:20:472:20 | y | y | | DeadStoreOfLocalBad.cs:7:13:7:48 | Boolean success = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocalBad.cs:7:13:7:19 | success | success | | DeadStoreOfLocalBad.cs:23:32:23:32 | FormatException e | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocalBad.cs:23:32:23:32 | e | e | | DeadStoreOfLocalBad.cs:32:22:32:22 | String s | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocalBad.cs:32:22:32:22 | s | s | From cbd577694c42d19bb760b855ba6d0c1ab87e1216 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 4 Oct 2021 13:30:15 +0200 Subject: [PATCH 121/361] JS: Autoformat --- javascript/ql/lib/semmle/javascript/PackageExports.qll | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/PackageExports.qll b/javascript/ql/lib/semmle/javascript/PackageExports.qll index b8375489e15..5d67b958d28 100644 --- a/javascript/ql/lib/semmle/javascript/PackageExports.qll +++ b/javascript/ql/lib/semmle/javascript/PackageExports.qll @@ -52,7 +52,8 @@ private DataFlow::Node getAValueExportedByPackage() { result = getAValueExportedByPackage().getALocalSource() or // Nested property reads. - result = getAValueExportedByPackage().(DataFlow::SourceNode).getAPropertyReference(publicPropertyName()) + result = + getAValueExportedByPackage().(DataFlow::SourceNode).getAPropertyReference(publicPropertyName()) or // module.exports.foo = require("./other-module.js"); exists(Module mod | @@ -186,9 +187,7 @@ private DataFlow::Node getAnExportFromModule(Module mod) { * This only allows properties whose first character is a letter or number. */ bindingset[result] -private string publicPropertyName() { - result.regexpMatch("[a-zA-Z0-9].*") -} +private string publicPropertyName() { result.regexpMatch("[a-zA-Z0-9].*") } /** * Holds if the given function is part of a private (or protected) method declaration. From 5aec84b672d6dd7b1ae213123114f3ae46e43185 Mon Sep 17 00:00:00 2001 From: Nick Rolfe <nickrolfe@github.com> Date: Mon, 4 Oct 2021 12:30:42 +0100 Subject: [PATCH 122/361] C++: add upgrade script for dbscheme comment changes --- .../old.dbscheme | 2136 +++++++++++++++++ .../semmlecode.cpp.dbscheme | 2136 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 4274 insertions(+) create mode 100644 cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/old.dbscheme create mode 100644 cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/semmlecode.cpp.dbscheme create mode 100644 cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/upgrade.properties diff --git a/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/old.dbscheme b/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/old.dbscheme new file mode 100644 index 00000000000..7806a11dd7a --- /dev/null +++ b/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/old.dbscheme @@ -0,0 +1,2136 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +/** If `function` is a coroutine, then this gives the + std::experimental::resumable_traits instance associated with it, + and the variables representing the `handle` and `promise` for it. */ +coroutine( + unique int function: @function ref, + int traits: @type ref, + int handle: @variable ref, + int promise: @variable ref +); + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +member_function_this_type(unique int id: @function ref, int this_type: @type ref); + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref, + int enclosing : @element ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + | 51 = char8_t + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + ; + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr + +@assign_expr = @assignexpr | @assign_op_expr + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + ; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +@access = @varaccess | @routineexpr ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +| 37 = @stmt_co_return +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/semmlecode.cpp.dbscheme b/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/semmlecode.cpp.dbscheme new file mode 100644 index 00000000000..018f430097e --- /dev/null +++ b/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/semmlecode.cpp.dbscheme @@ -0,0 +1,2136 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +/** If `function` is a coroutine, then this gives the + std::experimental::resumable_traits instance associated with it, + and the variables representing the `handle` and `promise` for it. */ +coroutine( + unique int function: @function ref, + int traits: @type ref, + int handle: @variable ref, + int promise: @variable ref +); + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +member_function_this_type(unique int id: @function ref, int this_type: @type ref); + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref, + int enclosing : @element ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + | 51 = char8_t + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + ; + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr + +@assign_expr = @assignexpr | @assign_op_expr + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + ; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +@access = @varaccess | @routineexpr ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +| 37 = @stmt_co_return +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/upgrade.properties b/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/upgrade.properties new file mode 100644 index 00000000000..63872bd6f10 --- /dev/null +++ b/cpp/upgrades/7806a11dd7ab6611c4245b2e96b8ed13cb5c6056/upgrade.properties @@ -0,0 +1,2 @@ +description: Non-functional change to dbscheme comments +compatibility: full From 064aba810ba73d295f6081a378a348aab5533b08 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Mon, 4 Oct 2021 13:31:07 +0200 Subject: [PATCH 123/361] Remove hyphens from the flow testcase generator folder name So that it can be imported from the autogenerated query `gen.ql` --- .../FlowTestCase.qll | 0 .../FlowTestCaseSupportMethods.qll | 0 .../FlowTestCaseUtils.qll | 0 .../GenerateFlowTestCase.py | 2 +- .../GenerateFlowTestCase.qll | 0 .../testHeader.qlfrag | 0 .../testModelsFooter.qlfrag | 0 .../testModelsHeader.qlfrag | 0 8 files changed, 1 insertion(+), 1 deletion(-) rename java/ql/src/utils/{flow-testcase-generator => flowtestcasegenerator}/FlowTestCase.qll (100%) rename java/ql/src/utils/{flow-testcase-generator => flowtestcasegenerator}/FlowTestCaseSupportMethods.qll (100%) rename java/ql/src/utils/{flow-testcase-generator => flowtestcasegenerator}/FlowTestCaseUtils.qll (100%) rename java/ql/src/utils/{flow-testcase-generator => flowtestcasegenerator}/GenerateFlowTestCase.py (97%) rename java/ql/src/utils/{flow-testcase-generator => flowtestcasegenerator}/GenerateFlowTestCase.qll (100%) rename java/ql/src/utils/{flow-testcase-generator => flowtestcasegenerator}/testHeader.qlfrag (100%) rename java/ql/src/utils/{flow-testcase-generator => flowtestcasegenerator}/testModelsFooter.qlfrag (100%) rename java/ql/src/utils/{flow-testcase-generator => flowtestcasegenerator}/testModelsHeader.qlfrag (100%) diff --git a/java/ql/src/utils/flow-testcase-generator/FlowTestCase.qll b/java/ql/src/utils/flowtestcasegenerator/FlowTestCase.qll similarity index 100% rename from java/ql/src/utils/flow-testcase-generator/FlowTestCase.qll rename to java/ql/src/utils/flowtestcasegenerator/FlowTestCase.qll diff --git a/java/ql/src/utils/flow-testcase-generator/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseSupportMethods.qll similarity index 100% rename from java/ql/src/utils/flow-testcase-generator/FlowTestCaseSupportMethods.qll rename to java/ql/src/utils/flowtestcasegenerator/FlowTestCaseSupportMethods.qll diff --git a/java/ql/src/utils/flow-testcase-generator/FlowTestCaseUtils.qll b/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseUtils.qll similarity index 100% rename from java/ql/src/utils/flow-testcase-generator/FlowTestCaseUtils.qll rename to java/ql/src/utils/flowtestcasegenerator/FlowTestCaseUtils.qll diff --git a/java/ql/src/utils/flow-testcase-generator/GenerateFlowTestCase.py b/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py similarity index 97% rename from java/ql/src/utils/flow-testcase-generator/GenerateFlowTestCase.py rename to java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py index cc4c90809ab..38d90830bf5 100755 --- a/java/ql/src/utils/flow-testcase-generator/GenerateFlowTestCase.py +++ b/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py @@ -130,7 +130,7 @@ with open(os.path.join(queryDir, "qlpack.yml"), "w") as f: f.write("name: test-generation-query\nversion: 0.0.0\nlibraryPathDependencies: codeql/java-queries") with open(qlFile, "w") as f: f.write( - "import java\nimport utils.GenerateFlowTestCase\n\nclass GenRow extends TargetSummaryModelCsv {\n\n\toverride predicate row(string r) {\n\t\tr = [\n") + "import java\nimport utils.flowtestcasegenerator.GenerateFlowTestCase\n\nclass GenRow extends TargetSummaryModelCsv {\n\n\toverride predicate row(string r) {\n\t\tr = [\n") f.write(",\n".join('\t\t\t"%s"' % spec.strip() for spec in specs)) f.write("\n\t\t]\n\t}\n}\n") diff --git a/java/ql/src/utils/flow-testcase-generator/GenerateFlowTestCase.qll b/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.qll similarity index 100% rename from java/ql/src/utils/flow-testcase-generator/GenerateFlowTestCase.qll rename to java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.qll diff --git a/java/ql/src/utils/flow-testcase-generator/testHeader.qlfrag b/java/ql/src/utils/flowtestcasegenerator/testHeader.qlfrag similarity index 100% rename from java/ql/src/utils/flow-testcase-generator/testHeader.qlfrag rename to java/ql/src/utils/flowtestcasegenerator/testHeader.qlfrag diff --git a/java/ql/src/utils/flow-testcase-generator/testModelsFooter.qlfrag b/java/ql/src/utils/flowtestcasegenerator/testModelsFooter.qlfrag similarity index 100% rename from java/ql/src/utils/flow-testcase-generator/testModelsFooter.qlfrag rename to java/ql/src/utils/flowtestcasegenerator/testModelsFooter.qlfrag diff --git a/java/ql/src/utils/flow-testcase-generator/testModelsHeader.qlfrag b/java/ql/src/utils/flowtestcasegenerator/testModelsHeader.qlfrag similarity index 100% rename from java/ql/src/utils/flow-testcase-generator/testModelsHeader.qlfrag rename to java/ql/src/utils/flowtestcasegenerator/testModelsHeader.qlfrag From 54aec7bb96990144de48d0327969f2002965460f Mon Sep 17 00:00:00 2001 From: Taus <tausbn@gmail.com> Date: Mon, 4 Oct 2021 12:16:53 +0000 Subject: [PATCH 124/361] Python: Fix bad magic in `controls/2` The changes to `ModificationOfParameterWithDefault.ql` and the use of `ConditionBlock::controls` therein caused the `BasicBlock` argument to get magicked in, resulting in the following antijoin for the `forall`: ``` [2021-10-04 12:07:46] (108s) Tuple counts for GuardedControlFlow::ConditionBlock::controls_dispred#fbf#antijoin_rhs/5@d84e94 after 1m44s: 201222345 ~7% {5} r1 = JOIN GuardedControlFlow::ConditionBlock::controls_dispred#fbf#shared#2 WITH Flow::BasicBlock::getASuccessor_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.0 'arg1', Rhs.1 'arg4', Lhs.1 'arg0', Lhs.2 'arg2', Lhs.3 'arg3' 200599933 ~4% {5} r2 = JOIN r1 WITH Flow::BasicBlock::dominates#ff ON FIRST 2 OUTPUT Lhs.2 'arg0', Lhs.0 'arg1', Lhs.3 'arg2', Lhs.4 'arg3', Lhs.1 'arg4' 0 ~0% {4} r3 = JOIN GuardedControlFlow::ConditionBlock::controls_dispred#fbf#shared#1 WITH GuardedControlFlow::ConditionBlock#class#f ON FIRST 1 OUTPUT Lhs.0 'arg3', Lhs.2 'arg1', Lhs.1 'arg0', false 0 ~0% {4} r4 = JOIN GuardedControlFlow::ConditionBlock::controls_dispred#fbf#shared WITH GuardedControlFlow::ConditionBlock#class#f ON FIRST 1 OUTPUT Lhs.0 'arg3', Lhs.2 'arg1', Lhs.1 'arg0', true 0 ~0% {4} r5 = r3 UNION r4 0 ~0% {5} r6 = JOIN r5 WITH Flow::BasicBlock::getASuccessor_dispred#ff ON FIRST 2 OUTPUT Lhs.2 'arg0', Lhs.1 'arg1', Lhs.3 'arg2', Lhs.0 'arg3', Rhs.0 200599933 ~4% {5} r7 = r2 UNION r6 return r7 ``` (cancelled) I observed that quick-eval'ing the `controls` predicate exhibit no such bad join order (and terminated quickly) which lead me to conclude that this was a case of bad magic. Adding the `pragma[nomagic]` resulted in a return to the previous performance. --- python/ql/lib/semmle/python/GuardedControlFlow.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ql/lib/semmle/python/GuardedControlFlow.qll b/python/ql/lib/semmle/python/GuardedControlFlow.qll index 37ecfee37d5..73ea183850a 100644 --- a/python/ql/lib/semmle/python/GuardedControlFlow.qll +++ b/python/ql/lib/semmle/python/GuardedControlFlow.qll @@ -9,6 +9,7 @@ class ConditionBlock extends BasicBlock { } /** Basic blocks controlled by this condition, i.e. those BBs for which the condition is testIsTrue */ + pragma[nomagic] predicate controls(BasicBlock controlled, boolean testIsTrue) { /* * For this block to control the block 'controlled' with 'testIsTrue' the following must be true: From eac0222f2ca08af2c5b100b29a2b10941e2a2379 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Mon, 4 Oct 2021 15:15:40 +0100 Subject: [PATCH 125/361] C++: Add more CWEs to 'cpp/incorrect-allocation-error-handling'. --- .../Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql b/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql index 28e7295dcdc..357e6375570 100644 --- a/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql +++ b/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql @@ -4,10 +4,13 @@ * @kind problem * @id cpp/incorrect-allocation-error-handling * @problem.severity warning + * @security-severity 7.5 * @precision medium * @tags correctness * security * external/cwe/cwe-570 + * external/cwe/cwe-252 + * external/cwe/cwe-755 */ import cpp From 0bce8234d8fb1389ecc9768c3e63842c1486f653 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Sun, 3 Oct 2021 00:21:30 +0200 Subject: [PATCH 126/361] Java: Remove overwritten `NestedType.isStatic()` QLDoc Did not mention nested non-member interfaces and record classes. The documentation of the overridden `isStatic()` predicate already mentions that this predicate holds for explicitly and implicitly static elements, so overwriting it is not necessary and only adds more maintenance work. --- java/ql/lib/semmle/code/java/Type.qll | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index 5395e855701..492d1b546cb 100755 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -779,23 +779,15 @@ class NestedType extends RefType { getEnclosingType().isStrictfp() } - /** - * Holds if this nested type is static. - * - * A nested type is static either if it is explicitly declared as such - * using the modifier `static`, or if it is implicitly static - * because one of the following holds: - * - * - it is a member type of an interface, - * - it is a member interface, or - * - it is a nested enum type. - * - * See JLS v8, section 8.5.1 (Static Member Type Declarations), - * section 8.9 (Enums) and section 9.5 (Member Type Declarations). - */ override predicate isStatic() { super.isStatic() or + /* + * Note: The following is most likely redundant because `isStatic()` of the superclass + * holds for implicitly static types, but keep the special casing below for now to be + * on the safe side + */ + // JLS 8.5.1: A member interface is implicitly static. this instanceof Interface or From 11b8d4191f08c85c042e71a971cbce96d8e78f88 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Oct 2021 16:53:33 +0100 Subject: [PATCH 127/361] C++: Repair .expected following merge. --- .../ImproperNullTermination/ImproperNullTermination.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected index 0c61e75efdd..19edbd28c6a 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected @@ -17,7 +17,6 @@ | test.cpp:285:10:285:15 | buffer | Variable $@ may not be null terminated. | test.cpp:282:8:282:13 | buffer | buffer | | test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 | | test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer | -| test.cpp:328:10:328:15 | buffer | Variable $@ may not be null terminated. | test.cpp:325:8:325:13 | buffer | buffer | | test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer | | test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer | | test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer | @@ -27,3 +26,4 @@ | test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer | | test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer | | test.cpp:513:10:513:15 | buffer | Variable $@ may not be null terminated. | test.cpp:511:8:511:13 | buffer | buffer | +| test.cpp:519:16:519:21 | buffer | Variable $@ may not be null terminated. | test.cpp:517:8:517:13 | buffer | buffer | From 99132210109a19582903b517053af4e981e3f026 Mon Sep 17 00:00:00 2001 From: Aditya Sharad <adityasharad@github.com> Date: Mon, 4 Oct 2021 11:08:43 -0700 Subject: [PATCH 128/361] CLI docs: Add example for creating a database using a Bazel build command We have internal material on this subject, so it makes sense to have a reference example. Bazel builds could be in any compiled language, so follow the pattern of the generic build script example. Include the build flags that we recommend to customers, which turn off Bazel's caching and distributed behaviour so that CodeQL can observe the entire build. --- .../codeql-cli/creating-codeql-databases.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index 16dadf16411..fd9bf9a0847 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -221,6 +221,23 @@ commands that you can specify for compiled languages. codeql database create java-database --language=java --command='ant -f build.xml' +- Project built using Bazel:: + + # Navigate to the Bazel workspace. + + # Stop all running Bazel server processes. + bazel shutdown + + # Remove cached objects before building. + bazel clean --expunge + + # Build using the following Bazel flags, to help CodeQL detect the build: + # `--spawn_strategy=local`: build locally, instead of using a distributed build + # `--nouse_action_cache`: turn off build caching, which might prevent recompilation of source code + # `--noremote_accept_cached`, `--noremote_upload_local_results`: avoid using a remote cache + codeql database create new-database --language=<language> \ + --command='bazel build --spawn_strategy=local --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results //path/to/package:target' + - Project built using a custom build script:: codeql database create new-database --language=<language> --command='./scripts/build.sh' From 0e149f0523f8639b6b6c1c527e98ab9e111ac5ad Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Fri, 18 Jun 2021 10:27:03 +0200 Subject: [PATCH 129/361] Move from experimental --- .../CWE/CWE-297/InsecureJavaMail.qhelp | 27 ++++++++++++++ .../Security/CWE/CWE-297/InsecureJavaMail.ql | 0 .../Security/CWE/CWE-297/JavaMail.java | 0 .../Security/CWE/CWE-297/SimpleMail.java | 0 .../CWE/CWE-297/InsecureJavaMail.qhelp | 36 ------------------- .../security/CWE-297/InsecureJavaMail.qlref | 1 - .../query-tests/security/CWE-297/options | 1 - .../CWE-297/InsecureJavaMail.expected | 0 .../security/CWE-297/InsecureJavaMail.java | 0 .../security/CWE-297/InsecureJavaMail.qlref | 1 + .../test/query-tests/security/CWE-297/options | 1 + 11 files changed, 29 insertions(+), 38 deletions(-) create mode 100644 java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp rename java/ql/src/{experimental => }/Security/CWE/CWE-297/InsecureJavaMail.ql (100%) rename java/ql/src/{experimental => }/Security/CWE/CWE-297/JavaMail.java (100%) rename java/ql/src/{experimental => }/Security/CWE/CWE-297/SimpleMail.java (100%) delete mode 100644 java/ql/src/experimental/Security/CWE/CWE-297/InsecureJavaMail.qhelp delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.qlref delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-297/options rename java/ql/test/{experimental => }/query-tests/security/CWE-297/InsecureJavaMail.expected (100%) rename java/ql/test/{experimental => }/query-tests/security/CWE-297/InsecureJavaMail.java (100%) create mode 100644 java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.qlref create mode 100644 java/ql/test/query-tests/security/CWE-297/options diff --git a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp new file mode 100644 index 00000000000..9945227ff0f --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp @@ -0,0 +1,27 @@ +<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> +<qhelp> + + <overview> + <p>JavaMail is commonly used in Java applications to send emails. There are popular third-party libraries like Apache Commons Email which are built on JavaMail and facilitate integration. Authenticated mail sessions require user credentials and mail sessions can require SSL/TLS authentication. It is a common security vulnerability that host-specific certificate data is not validated or is incorrectly validated. Failing to validate the certificate makes the SSL session susceptible to a man-in-the-middle attack.</p> + <p>This query checks whether SSL certificate is validated when username/password is sent in authenticator and when SSL is enabled.</p> + <p>The query has code for both plain JavaMail invocation and mailing through Apache SimpleMail to make it more comprehensive.</p> + </overview> + + <recommendation> + <p>Validate SSL certificate when sensitive information is sent in email communications.</p> + </recommendation> + + <example> + <p>The following two examples show two ways of configuring secure emails through JavaMail or Apache SimpleMail. In the 'BAD' case, +credentials are sent in an SSL session without certificate validation. In the 'GOOD' case, the certificate is validated.</p> + <sample src="JavaMail.java" /> + <sample src="SimpleMail.java" /> + </example> + + <references> + <li> + Log4j2: + <a href="https://issues.apache.org/jira/browse/LOG4J2-2819">Add support for specifying an SSL configuration for SmtpAppender (CVE-2020-9488)</a> + </li> + </references> +</qhelp> diff --git a/java/ql/src/experimental/Security/CWE/CWE-297/InsecureJavaMail.ql b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-297/InsecureJavaMail.ql rename to java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql diff --git a/java/ql/src/experimental/Security/CWE/CWE-297/JavaMail.java b/java/ql/src/Security/CWE/CWE-297/JavaMail.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-297/JavaMail.java rename to java/ql/src/Security/CWE/CWE-297/JavaMail.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-297/SimpleMail.java b/java/ql/src/Security/CWE/CWE-297/SimpleMail.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-297/SimpleMail.java rename to java/ql/src/Security/CWE/CWE-297/SimpleMail.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-297/InsecureJavaMail.qhelp b/java/ql/src/experimental/Security/CWE/CWE-297/InsecureJavaMail.qhelp deleted file mode 100644 index ea1405aa4ee..00000000000 --- a/java/ql/src/experimental/Security/CWE/CWE-297/InsecureJavaMail.qhelp +++ /dev/null @@ -1,36 +0,0 @@ -<!DOCTYPE qhelp PUBLIC - "-//Semmle//qhelp//EN" - "qhelp.dtd"> -<qhelp> - -<overview> -<p>JavaMail is commonly used in Java applications to send emails. There are popular third-party libraries like Apache Commons Email which are built on JavaMail and facilitate integration. Authenticated mail sessions require user credentials and mail sessions can require SSL/TLS authentication. It is a common security vulnerability that host-specific certificate data is not validated or is incorrectly validated. Failing to validate the certificate makes the SSL session susceptible to a man-in-the-middle attack.</p> -<p>This query checks whether SSL certificate is validated when username/password is sent in authenticator and when SSL is enabled.</p> -<p>The query has code for both plain JavaMail invocation and mailing through Apache SimpleMail to make it more comprehensive.</p> -</overview> - -<recommendation> -<p>Validate SSL certificate when sensitive information is sent in email communications.</p> -</recommendation> - -<example> -<p>The following two examples show two ways of configuring secure emails through JavaMail or Apache SimpleMail. In the 'BAD' case, -credentials are sent in an SSL session without certificate validation. In the 'GOOD' case, the certificate is validated.</p> -<sample src="JavaMail.java" /> -<sample src="SimpleMail.java" /> -</example> - -<references> -<li> - <a href="https://cwe.mitre.org/data/definitions/297.html">CWE-297</a> -</li> -<li> - Log4j2: - <a href="https://issues.apache.org/jira/browse/LOG4J2-2819">Add support for specifying an SSL configuration for SmtpAppender (CVE-2020-9488)</a> -</li> -<li> - SonarSource rule: - <a href="https://rules.sonarsource.com/java/tag/owasp/RSPEC-4499">SMTP SSL connection should check server identity</a> -</li> -</references> -</qhelp> diff --git a/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.qlref b/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.qlref deleted file mode 100644 index 565779521f3..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-297/InsecureJavaMail.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-297/options b/java/ql/test/experimental/query-tests/security/CWE-297/options deleted file mode 100644 index 51c4feeca1b..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-297/options +++ /dev/null @@ -1 +0,0 @@ -// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/apache-commons-email-1.6.0:${testdir}/../../../../stubs/javamail-api-1.6.2 diff --git a/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.expected b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.expected similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.expected rename to java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.expected diff --git a/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.java b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.java similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.java rename to java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.java diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.qlref b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.qlref new file mode 100644 index 00000000000..78dddc0f868 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-297/InsecureJavaMail.ql diff --git a/java/ql/test/query-tests/security/CWE-297/options b/java/ql/test/query-tests/security/CWE-297/options new file mode 100644 index 00000000000..563a4fdcfc8 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-297/options @@ -0,0 +1 @@ +// semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-commons-email-1.6.0:${testdir}/../../../stubs/javamail-api-1.6.2 From 8c6d58e6d827046f668d26b18bbb2323fa616745 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Fri, 18 Jun 2021 11:11:52 +0200 Subject: [PATCH 130/361] Refactored into libraries --- .../Security/CWE/CWE-297/InsecureJavaMail.ql | 90 +------------------ .../src/semmle/code/java/frameworks/Mail.qll | 27 ++++++ .../ql/src/semmle/code/java/security/Mail.qll | 74 +++++++++++++++ 3 files changed, 104 insertions(+), 87 deletions(-) create mode 100644 java/ql/src/semmle/code/java/frameworks/Mail.qll create mode 100644 java/ql/src/semmle/code/java/security/Mail.qll diff --git a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql index d0e0dc8b81a..9697b2ae588 100644 --- a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql +++ b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql @@ -12,96 +12,12 @@ */ import java - -/** - * The method to set Java properties - */ -class SetPropertyMethod extends Method { - SetPropertyMethod() { - this.hasName("setProperty") and - this.getDeclaringType().hasQualifiedName("java.util", "Properties") - or - this.hasName("put") and - this.getDeclaringType().getASourceSupertype*().hasQualifiedName("java.util", "Dictionary") - } -} - -/** - * The insecure way to set Java properties in mail sessions. - * 1. Set the mail.smtp.auth property to provide the SMTP Transport with a username and password when connecting to the SMTP server or - * set the mail.smtp.ssl.socketFactory/mail.smtp.ssl.socketFactory.class property to create an SMTP SSL socket. - * 2. No mail.smtp.ssl.checkserveridentity property is enabled. - */ -predicate isInsecureMailPropertyConfig(VarAccess propertiesVarAccess) { - exists(MethodAccess ma | - ma.getMethod() instanceof SetPropertyMethod and - ma.getQualifier() = propertiesVarAccess.getVariable().getAnAccess() and - ( - getStringValue(ma.getArgument(0)).matches("%.auth%") and //mail.smtp.auth - getStringValue(ma.getArgument(1)) = "true" - or - getStringValue(ma.getArgument(0)).matches("%.socketFactory%") //mail.smtp.socketFactory or mail.smtp.socketFactory.class - ) - ) and - not exists(MethodAccess ma | - ma.getMethod() instanceof SetPropertyMethod and - ma.getQualifier() = propertiesVarAccess.getVariable().getAnAccess() and - ( - getStringValue(ma.getArgument(0)).matches("%.ssl.checkserveridentity%") and //mail.smtp.ssl.checkserveridentity - getStringValue(ma.getArgument(1)) = "true" - ) - ) -} - -/** - * Helper method to get string value of an argument - */ -string getStringValue(Expr expr) { - result = expr.(CompileTimeConstantExpr).getStringValue() - or - result = getStringValue(expr.(AddExpr).getLeftOperand()) - or - result = getStringValue(expr.(AddExpr).getRightOperand()) -} - -/** - * The JavaMail session class `javax.mail.Session` - */ -class MailSession extends RefType { - MailSession() { this.hasQualifiedName("javax.mail", "Session") } -} - -/** - * The class of Apache SimpleMail - */ -class SimpleMail extends RefType { - SimpleMail() { this.hasQualifiedName("org.apache.commons.mail", "SimpleEmail") } -} - -/** - * Has TLS/SSL enabled with SimpleMail - */ -predicate enableTLSWithSimpleMail(MethodAccess ma) { - ma.getMethod().hasName("setSSLOnConnect") and - ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true -} - -/** - * Has no certificate check - */ -predicate hasNoCertCheckWithSimpleMail(VarAccess va) { - not exists(MethodAccess ma | - ma.getQualifier() = va.getVariable().getAnAccess() and - ma.getMethod().hasName("setSSLCheckServerIdentity") and - ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true - ) -} +import semmle.code.java.security.Mail from MethodAccess ma where - ma.getMethod().getDeclaringType() instanceof MailSession and - ma.getMethod().getName() = "getInstance" and + ma.getMethod() instanceof MailSessionGetInstanceMethod and isInsecureMailPropertyConfig(ma.getArgument(0)) or - enableTLSWithSimpleMail(ma) and hasNoCertCheckWithSimpleMail(ma.getQualifier()) + enablesEmailSsl(ma) and not hasSslCertificateCheck(ma.getQualifier()) select ma, "Java mailing has insecure SSL configuration" diff --git a/java/ql/src/semmle/code/java/frameworks/Mail.qll b/java/ql/src/semmle/code/java/frameworks/Mail.qll new file mode 100644 index 00000000000..f26cf0c5982 --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/Mail.qll @@ -0,0 +1,27 @@ +/** Provides classes and predicates to work with email */ + +import java + +/** + * The class `javax.mail.Session` + */ +class MailSession extends Class { + MailSession() { this.hasQualifiedName("javax.mail", "Session") } +} + +/** + * The method `getInstance` of the class `javax.mail.Session` + */ +class MailSessionGetInstanceMethod extends Method { + MailSessionGetInstanceMethod() { + this.getDeclaringType() instanceof MailSession and + this.getName() = "getInstance" + } +} + +/** + * A subtype of the class `org.apache.commons.mail.Mail` + */ +class ApacheEmail extends Class { + ApacheEmail() { this.getASupertype*().hasQualifiedName("org.apache.commons.mail", "Email") } +} diff --git a/java/ql/src/semmle/code/java/security/Mail.qll b/java/ql/src/semmle/code/java/security/Mail.qll new file mode 100644 index 00000000000..e5fbb5c65a0 --- /dev/null +++ b/java/ql/src/semmle/code/java/security/Mail.qll @@ -0,0 +1,74 @@ +/** Provides classes and predicates to reason about email vulnerabilities. */ + +import java +import semmle.code.java.frameworks.Mail +private import semmle.code.java.frameworks.Properties + +/** + * The insecure way to set Java properties in mail sessions. + * 1. Set the `mail.smtp.auth` property to provide the SMTP Transport with a username and password when connecting to the SMTP server or + * set the `mail.smtp.ssl.socketFactory`/`mail.smtp.ssl.socketFactory.class` property to create an SMTP SSL socket. + * 2. No `mail.smtp.ssl.checkserveridentity` property is enabled. + */ +predicate isInsecureMailPropertyConfig(VarAccess propertiesVarAccess) { + exists(MethodAccess ma | + ma.getMethod() instanceof SetPropertyMethod and + ma.getQualifier() = propertiesVarAccess.getVariable().getAnAccess() + | + getStringValue(ma.getArgument(0)).matches("%.auth%") and //mail.smtp.auth + getStringValue(ma.getArgument(1)) = "true" + or + getStringValue(ma.getArgument(0)).matches("%.socketFactory%") //mail.smtp.socketFactory or mail.smtp.socketFactory.class + ) and + not exists(MethodAccess ma | + ma.getMethod() instanceof SetPropertyMethod and + ma.getQualifier() = propertiesVarAccess.getVariable().getAnAccess() + | + getStringValue(ma.getArgument(0)).matches("%.ssl.checkserveridentity%") and //mail.smtp.ssl.checkserveridentity + getStringValue(ma.getArgument(1)) = "true" + ) +} + +/** + * Holds if `ma` enables TLS/SSL with Apache Email. + */ +predicate enablesEmailSsl(MethodAccess ma) { + ma.getMethod().hasName("setSSLOnConnect") and + ma.getMethod().getDeclaringType() instanceof ApacheEmail and + ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true +} + +/** + * Holds if a SSL certificate check is enabled on `va` with Apache Email + */ +predicate hasSslCertificateCheck(VarAccess va) { + exists(MethodAccess ma | + ma.getQualifier() = va.getVariable().getAnAccess() and + ma.getMethod().hasName("setSSLCheckServerIdentity") and + ma.getMethod().getDeclaringType() instanceof ApacheEmail and + ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true + ) +} + +/** + * Helper method to get string value of an argument + */ +private string getStringValue(Expr expr) { + result = expr.(CompileTimeConstantExpr).getStringValue() + or + result = getStringValue(expr.(AddExpr).getLeftOperand()) + or + result = getStringValue(expr.(AddExpr).getRightOperand()) +} + +/** + * A method to set Java properties + */ +private class SetPropertyMethod extends Method { + SetPropertyMethod() { + this instanceof PropertiesSetPropertyMethod + or + this.hasName("put") and + this.getDeclaringType().getASourceSupertype*().hasQualifiedName("java.util", "Dictionary") + } +} From 73653f77aa8d5aad7a96420dce3b6fa1285924a4 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Fri, 18 Jun 2021 11:34:56 +0200 Subject: [PATCH 131/361] Use InlineExpectationsTest --- .../CWE-297/InsecureJavaMail.expected | 2 - .../security/CWE-297/InsecureJavaMail.qlref | 1 - .../CWE-297/InsecureJavaMailTest.expected | 0 ...avaMail.java => InsecureJavaMailTest.java} | 40 ++++++++++++++++--- .../security/CWE-297/InsecureJavaMailTest.ql | 23 +++++++++++ 5 files changed, 58 insertions(+), 8 deletions(-) delete mode 100644 java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.expected delete mode 100644 java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.qlref create mode 100644 java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.expected rename java/ql/test/query-tests/security/CWE-297/{InsecureJavaMail.java => InsecureJavaMailTest.java} (50%) create mode 100644 java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.ql diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.expected b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.expected deleted file mode 100644 index 0e3c219ace3..00000000000 --- a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.expected +++ /dev/null @@ -1,2 +0,0 @@ -| InsecureJavaMail.java:29:27:29:72 | getInstance(...) | Java mailing has insecure SSL configuration | -| InsecureJavaMail.java:37:3:37:29 | setSSLOnConnect(...) | Java mailing has insecure SSL configuration | diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.qlref b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.qlref deleted file mode 100644 index 78dddc0f868..00000000000 --- a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.qlref +++ /dev/null @@ -1 +0,0 @@ -Security/CWE/CWE-297/InsecureJavaMail.ql diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.expected b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.java b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.java similarity index 50% rename from java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.java rename to java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.java index 62c64027695..fdfbd1f9f03 100644 --- a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMail.java +++ b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.java @@ -10,7 +10,7 @@ import org.apache.commons.mail.SimpleEmail; import java.util.Properties; -class InsecureJavaMail { +class InsecureJavaMailTest { public void testJavaMail() { final Properties properties = new Properties(); properties.put("mail.transport.protocol", "protocol"); @@ -24,9 +24,26 @@ class InsecureJavaMail { }; if (null != authenticator) { properties.put("mail.smtp.auth", "true"); - // properties.put("mail.smtp.ssl.checkserveridentity", "true"); } - final Session session = Session.getInstance(properties, authenticator); + final Session session = Session.getInstance(properties, authenticator); // $hasInsecureJavaMail + } + + public void testSecureJavaMail() { + final Properties properties = new Properties(); + properties.put("mail.transport.protocol", "protocol"); + properties.put("mail.smtp.host", "hostname"); + properties.put("mail.smtp.socketFactory.class", "classname"); + + final javax.mail.Authenticator authenticator = new javax.mail.Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("username", "password"); + } + }; + if (null != authenticator) { + properties.put("mail.smtp.auth", "true"); + properties.put("mail.smtp.ssl.checkserveridentity", "true"); + } + final Session session = Session.getInstance(properties, authenticator); // Safe } public void testSimpleMail() throws Exception { @@ -34,8 +51,21 @@ class InsecureJavaMail { email.setHostName("config.hostName"); email.setSmtpPort(25); email.setAuthenticator(new DefaultAuthenticator("config.username", "config.password")); - email.setSSLOnConnect(true); - // email.setSSLCheckServerIdentity(true); + email.setSSLOnConnect(true); // $hasInsecureJavaMail + email.setFrom("fromAddress"); + email.setSubject("subject"); + email.setMsg("body"); + email.addTo("toAddress"); + email.send(); + } + + public void testSecureSimpleMail() throws Exception { + Email email = new SimpleEmail(); + email.setHostName("config.hostName"); + email.setSmtpPort(25); + email.setAuthenticator(new DefaultAuthenticator("config.username", "config.password")); + email.setSSLOnConnect(true); // Safe + email.setSSLCheckServerIdentity(true); email.setFrom("fromAddress"); email.setSubject("subject"); email.setMsg("body"); diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.ql b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.ql new file mode 100644 index 00000000000..061aa6711f6 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.ql @@ -0,0 +1,23 @@ +import java +import semmle.code.java.security.Mail +import TestUtilities.InlineExpectationsTest + +class InsecureJavaMailTest extends InlineExpectationsTest { + InsecureJavaMailTest() { this = "HasInsecureJavaMailTest" } + + override string getARelevantTag() { result = "hasInsecureJavaMail" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasInsecureJavaMail" and + exists(MethodAccess ma | + ma.getLocation() = location and + element = ma.toString() and + value = "" + | + ma.getMethod() instanceof MailSessionGetInstanceMethod and + isInsecureMailPropertyConfig(ma.getArgument(0)) + or + enablesEmailSsl(ma) and not hasSslCertificateCheck(ma.getQualifier()) + ) + } +} From c13bf2a2a135ea9976d682dfe8b7849a98853429 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Fri, 18 Jun 2021 11:35:05 +0200 Subject: [PATCH 132/361] Add change note --- java/change-notes/2021-06-18-insecure-java-mail-query.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java/change-notes/2021-06-18-insecure-java-mail-query.md diff --git a/java/change-notes/2021-06-18-insecure-java-mail-query.md b/java/change-notes/2021-06-18-insecure-java-mail-query.md new file mode 100644 index 00000000000..495a7019f9a --- /dev/null +++ b/java/change-notes/2021-06-18-insecure-java-mail-query.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The query "Insecure JavaMail SSL Configuration" (`java/insecure-smtp-ssl`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3491) \ No newline at end of file From a2e9c2f4abc3ed53a34f0c18a404543e817f050e Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Wed, 30 Jun 2021 11:49:31 +0200 Subject: [PATCH 133/361] Apply suggestions from code review Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> --- java/ql/src/semmle/code/java/frameworks/Mail.qll | 2 +- java/ql/src/semmle/code/java/security/Mail.qll | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/Mail.qll b/java/ql/src/semmle/code/java/frameworks/Mail.qll index f26cf0c5982..0f8ff1e0c55 100644 --- a/java/ql/src/semmle/code/java/frameworks/Mail.qll +++ b/java/ql/src/semmle/code/java/frameworks/Mail.qll @@ -20,7 +20,7 @@ class MailSessionGetInstanceMethod extends Method { } /** - * A subtype of the class `org.apache.commons.mail.Mail` + * A subtype of the class `org.apache.commons.mail.Email` */ class ApacheEmail extends Class { ApacheEmail() { this.getASupertype*().hasQualifiedName("org.apache.commons.mail", "Email") } diff --git a/java/ql/src/semmle/code/java/security/Mail.qll b/java/ql/src/semmle/code/java/security/Mail.qll index e5fbb5c65a0..4f4c9c87426 100644 --- a/java/ql/src/semmle/code/java/security/Mail.qll +++ b/java/ql/src/semmle/code/java/security/Mail.qll @@ -56,9 +56,7 @@ predicate hasSslCertificateCheck(VarAccess va) { private string getStringValue(Expr expr) { result = expr.(CompileTimeConstantExpr).getStringValue() or - result = getStringValue(expr.(AddExpr).getLeftOperand()) - or - result = getStringValue(expr.(AddExpr).getRightOperand()) + result = getStringValue(expr.(AddExpr).getAnOperand()) } /** From baffb0ed891f1e10cb19fd9900ab966bdd14fc1f Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Wed, 30 Jun 2021 12:14:55 +0200 Subject: [PATCH 134/361] Consider Jakarta Mail --- .../src/semmle/code/java/frameworks/Mail.qll | 8 +- .../CWE-297/InsecureJakartaMailTest.java | 42 ++++++++++ .../test/query-tests/security/CWE-297/options | 2 +- .../jakarta/mail/Authenticator.java | 20 +++++ .../jakarta/mail/PasswordAuthentication.java | 28 +++++++ .../jakarta/mail/Session.java | 80 +++++++++++++++++++ 6 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 java/ql/test/query-tests/security/CWE-297/InsecureJakartaMailTest.java create mode 100644 java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/Authenticator.java create mode 100644 java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/PasswordAuthentication.java create mode 100644 java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/Session.java diff --git a/java/ql/src/semmle/code/java/frameworks/Mail.qll b/java/ql/src/semmle/code/java/frameworks/Mail.qll index 0f8ff1e0c55..93116009862 100644 --- a/java/ql/src/semmle/code/java/frameworks/Mail.qll +++ b/java/ql/src/semmle/code/java/frameworks/Mail.qll @@ -3,14 +3,14 @@ import java /** - * The class `javax.mail.Session` + * The class `javax.mail.Session` or `jakarta.mail.Session`. */ class MailSession extends Class { - MailSession() { this.hasQualifiedName("javax.mail", "Session") } + MailSession() { this.hasQualifiedName(["javax.mail", "jakarta.mail"], "Session") } } /** - * The method `getInstance` of the class `javax.mail.Session` + * The method `getInstance` of the classes `javax.mail.Session` or `jakarta.mail.Session`. */ class MailSessionGetInstanceMethod extends Method { MailSessionGetInstanceMethod() { @@ -20,7 +20,7 @@ class MailSessionGetInstanceMethod extends Method { } /** - * A subtype of the class `org.apache.commons.mail.Email` + * A subtype of the class `org.apache.commons.mail.Email`. */ class ApacheEmail extends Class { ApacheEmail() { this.getASupertype*().hasQualifiedName("org.apache.commons.mail", "Email") } diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJakartaMailTest.java b/java/ql/test/query-tests/security/CWE-297/InsecureJakartaMailTest.java new file mode 100644 index 00000000000..2dd5cab08ec --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-297/InsecureJakartaMailTest.java @@ -0,0 +1,42 @@ +import java.util.Properties; + +import jakarta.mail.Authenticator; +import jakarta.mail.PasswordAuthentication; +import jakarta.mail.Session; + +class InsecureJakartaMailTest { + public void testJavaMail() { + final Properties properties = new Properties(); + properties.put("mail.transport.protocol", "protocol"); + properties.put("mail.smtp.host", "hostname"); + properties.put("mail.smtp.socketFactory.class", "classname"); + + final jakarta.mail.Authenticator authenticator = new jakarta.mail.Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("username", "password"); + } + }; + if (null != authenticator) { + properties.put("mail.smtp.auth", "true"); + } + final Session session = Session.getInstance(properties, authenticator); // $hasInsecureJavaMail + } + + public void testSecureJavaMail() { + final Properties properties = new Properties(); + properties.put("mail.transport.protocol", "protocol"); + properties.put("mail.smtp.host", "hostname"); + properties.put("mail.smtp.socketFactory.class", "classname"); + + final jakarta.mail.Authenticator authenticator = new jakarta.mail.Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("username", "password"); + } + }; + if (null != authenticator) { + properties.put("mail.smtp.auth", "true"); + properties.put("mail.smtp.ssl.checkserveridentity", "true"); + } + final Session session = Session.getInstance(properties, authenticator); // Safe + } +} diff --git a/java/ql/test/query-tests/security/CWE-297/options b/java/ql/test/query-tests/security/CWE-297/options index 563a4fdcfc8..6fcd80260e3 100644 --- a/java/ql/test/query-tests/security/CWE-297/options +++ b/java/ql/test/query-tests/security/CWE-297/options @@ -1 +1 @@ -// semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-commons-email-1.6.0:${testdir}/../../../stubs/javamail-api-1.6.2 +// semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-commons-email-1.6.0:${testdir}/../../../stubs/javamail-api-1.6.2:${testdir}/../../../stubs/jakarta-mail-2.0.1 diff --git a/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/Authenticator.java b/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/Authenticator.java new file mode 100644 index 00000000000..594f3876f19 --- /dev/null +++ b/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/Authenticator.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.mail; + +public abstract class Authenticator { +} diff --git a/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/PasswordAuthentication.java b/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/PasswordAuthentication.java new file mode 100644 index 00000000000..20751b7f7d9 --- /dev/null +++ b/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/PasswordAuthentication.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the terms of the Eclipse + * Public License v. 2.0, which is available at http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary Licenses when the + * conditions for such availability set forth in the Eclipse Public License v. 2.0 are satisfied: + * GNU General Public License, version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.mail; + +public final class PasswordAuthentication { + public PasswordAuthentication(String userName, String password) {} + + public String getUserName() { + return null; + } + + public String getPassword() { + return null; + } + +} diff --git a/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/Session.java b/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/Session.java new file mode 100644 index 00000000000..6f525babdae --- /dev/null +++ b/java/ql/test/stubs/jakarta-mail-2.0.1/jakarta/mail/Session.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the terms of the Eclipse + * Public License v. 2.0, which is available at http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary Licenses when the + * conditions for such availability set forth in the Eclipse Public License v. 2.0 are satisfied: + * GNU General Public License, version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.mail; + +import java.lang.reflect.*; +import java.io.*; +import java.net.*; +import java.security.*; +import java.util.Properties; + +public final class Session { + public static Session getInstance(Properties props, Authenticator authenticator) { + return null; + } + + public static Session getInstance(Properties props) { + return null; + } + + public static synchronized Session getDefaultInstance(Properties props, + Authenticator authenticator) { + return null; + } + + public static Session getDefaultInstance(Properties props) { + return null; + } + + public synchronized void setDebug(boolean debug) {} + + public synchronized boolean getDebug() { + return false; + } + + public synchronized void setDebugOut(PrintStream out) {} + + public synchronized PrintStream getDebugOut() { + return null; + } + + public synchronized Provider[] getProviders() { + return null; + } + + public synchronized Provider getProvider(String protocol) throws NoSuchProviderException { + return null; + } + + public synchronized void setProvider(Provider provider) throws NoSuchProviderException {} + + public PasswordAuthentication requestPasswordAuthentication(InetAddress addr, int port, + String protocol, String prompt, String defaultUserName) { + return null; + } + + public Properties getProperties() { + return null; + } + + public String getProperty(String name) { + return null; + } + + public synchronized void addProvider(Provider provider) {} + + public synchronized void setProtocolForAddress(String addresstype, String protocol) {} + +} From 2d1278ece50a45c8d21ebb452ca1e52f72976e12 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Wed, 30 Jun 2021 12:22:48 +0200 Subject: [PATCH 135/361] Consider setStartTLSRequired for Apache SimpleEmail --- .../ql/src/semmle/code/java/security/Mail.qll | 2 +- .../CWE-297/InsecureJavaMailTest.java | 31 ---------- .../CWE-297/InsecureSimpleEmailTest.java | 62 +++++++++++++++++++ 3 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 java/ql/test/query-tests/security/CWE-297/InsecureSimpleEmailTest.java diff --git a/java/ql/src/semmle/code/java/security/Mail.qll b/java/ql/src/semmle/code/java/security/Mail.qll index 4f4c9c87426..c100e5c49dc 100644 --- a/java/ql/src/semmle/code/java/security/Mail.qll +++ b/java/ql/src/semmle/code/java/security/Mail.qll @@ -33,7 +33,7 @@ predicate isInsecureMailPropertyConfig(VarAccess propertiesVarAccess) { * Holds if `ma` enables TLS/SSL with Apache Email. */ predicate enablesEmailSsl(MethodAccess ma) { - ma.getMethod().hasName("setSSLOnConnect") and + ma.getMethod().hasName(["setSSLOnConnect", "setStartTLSRequired"]) and ma.getMethod().getDeclaringType() instanceof ApacheEmail and ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true } diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.java b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.java index fdfbd1f9f03..a9880c20339 100644 --- a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.java +++ b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.java @@ -4,12 +4,6 @@ import javax.mail.Authenticator; import javax.mail.PasswordAuthentication; import javax.mail.Session; -import org.apache.commons.mail.DefaultAuthenticator; -import org.apache.commons.mail.Email; -import org.apache.commons.mail.SimpleEmail; - -import java.util.Properties; - class InsecureJavaMailTest { public void testJavaMail() { final Properties properties = new Properties(); @@ -46,30 +40,5 @@ class InsecureJavaMailTest { final Session session = Session.getInstance(properties, authenticator); // Safe } - public void testSimpleMail() throws Exception { - Email email = new SimpleEmail(); - email.setHostName("config.hostName"); - email.setSmtpPort(25); - email.setAuthenticator(new DefaultAuthenticator("config.username", "config.password")); - email.setSSLOnConnect(true); // $hasInsecureJavaMail - email.setFrom("fromAddress"); - email.setSubject("subject"); - email.setMsg("body"); - email.addTo("toAddress"); - email.send(); - } - public void testSecureSimpleMail() throws Exception { - Email email = new SimpleEmail(); - email.setHostName("config.hostName"); - email.setSmtpPort(25); - email.setAuthenticator(new DefaultAuthenticator("config.username", "config.password")); - email.setSSLOnConnect(true); // Safe - email.setSSLCheckServerIdentity(true); - email.setFrom("fromAddress"); - email.setSubject("subject"); - email.setMsg("body"); - email.addTo("toAddress"); - email.send(); - } } diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureSimpleEmailTest.java b/java/ql/test/query-tests/security/CWE-297/InsecureSimpleEmailTest.java new file mode 100644 index 00000000000..5940dbbd457 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-297/InsecureSimpleEmailTest.java @@ -0,0 +1,62 @@ +import org.apache.commons.mail.DefaultAuthenticator; +import org.apache.commons.mail.Email; +import org.apache.commons.mail.SimpleEmail; + +public class InsecureSimpleEmailTest { + public void test() throws Exception { + // with setSSLOnConnect + { + Email email = new SimpleEmail(); + email.setHostName("config.hostName"); + email.setSmtpPort(25); + email.setAuthenticator(new DefaultAuthenticator("config.username", "config.password")); + email.setSSLOnConnect(true); // $hasInsecureJavaMail + email.setFrom("fromAddress"); + email.setSubject("subject"); + email.setMsg("body"); + email.addTo("toAddress"); + email.send(); + } + // with setStartTLSRequired + { + Email email = new SimpleEmail(); + email.setHostName("config.hostName"); + email.setSmtpPort(25); + email.setAuthenticator(new DefaultAuthenticator("config.username", "config.password")); + email.setStartTLSRequired(true); // $hasInsecureJavaMail + email.setFrom("fromAddress"); + email.setSubject("subject"); + email.setMsg("body"); + email.addTo("toAddress"); + email.send(); + } + // safe with setSSLOnConnect + { + Email email = new SimpleEmail(); + email.setHostName("config.hostName"); + email.setSmtpPort(25); + email.setAuthenticator(new DefaultAuthenticator("config.username", "config.password")); + email.setSSLOnConnect(true); // Safe + email.setSSLCheckServerIdentity(true); + email.setFrom("fromAddress"); + email.setSubject("subject"); + email.setMsg("body"); + email.addTo("toAddress"); + email.send(); + } + // safe with setStartTLSRequired + { + Email email = new SimpleEmail(); + email.setHostName("config.hostName"); + email.setSmtpPort(25); + email.setAuthenticator(new DefaultAuthenticator("config.username", "config.password")); + email.setStartTLSRequired(true); // Safe + email.setSSLCheckServerIdentity(true); + email.setFrom("fromAddress"); + email.setSubject("subject"); + email.setMsg("body"); + email.addTo("toAddress"); + email.send(); + } + } +} From 9c1021134a86257f55aaccb419b0649665625359 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Wed, 30 Jun 2021 13:37:20 +0200 Subject: [PATCH 136/361] Add some links to qhelp --- .../src/Security/CWE/CWE-297/InsecureJavaMail.qhelp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp index 9945227ff0f..06a3df57b18 100644 --- a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp +++ b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp @@ -19,9 +19,17 @@ credentials are sent in an SSL session without certificate validation. In the 'G </example> <references> + <li> + Jakarta Mail: + <a href="https://eclipse-ee4j.github.io/mail/docs/SSLNOTES.txt">SSL Notes</a>. + </li> + <li> + Apache Commons: + <a href="https://commons.apache.org/proper/commons-email/userguide.html#Security">Email security</a>. + </li> <li> Log4j2: - <a href="https://issues.apache.org/jira/browse/LOG4J2-2819">Add support for specifying an SSL configuration for SmtpAppender (CVE-2020-9488)</a> + <a href="https://issues.apache.org/jira/browse/LOG4J2-2819">Add support for specifying an SSL configuration for SmtpAppender (CVE-2020-9488)</a>. </li> </references> -</qhelp> +</qhelp> \ No newline at end of file From 9f54b1065a407b4d6baa10d76979d5251e540f67 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Thu, 29 Jul 2021 17:30:01 +0200 Subject: [PATCH 137/361] Apply suggestions from code review Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com> --- java/change-notes/2021-06-18-insecure-java-mail-query.md | 2 +- java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/change-notes/2021-06-18-insecure-java-mail-query.md b/java/change-notes/2021-06-18-insecure-java-mail-query.md index 495a7019f9a..e2778ec1b02 100644 --- a/java/change-notes/2021-06-18-insecure-java-mail-query.md +++ b/java/change-notes/2021-06-18-insecure-java-mail-query.md @@ -1,2 +1,2 @@ lgtm,codescanning -* The query "Insecure JavaMail SSL Configuration" (`java/insecure-smtp-ssl`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3491) \ No newline at end of file +* The query "Insecure JavaMail SSL Configuration" (`java/insecure-smtp-ssl`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3491). diff --git a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql index 9697b2ae588..3c6fff0678d 100644 --- a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql +++ b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql @@ -1,8 +1,8 @@ /** * @name Insecure JavaMail SSL Configuration - * @description Java application configured to use authenticated mail session - * over SSL does not validate the SSL certificate to properly - * ensure that it is actually associated with that host. + * @description Configuring a Java application to use authenticated mail session + * over SSL without certificate validation + * makes the session susceptible to a man-in-the-middle attack. * @kind problem * @problem.severity warning * @precision medium From 3323f7ab1afeba4ef470b9f0b4575306fcb40f14 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Thu, 29 Jul 2021 17:34:08 +0200 Subject: [PATCH 138/361] Fix qhelp --- java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp index 06a3df57b18..406d9666ce6 100644 --- a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp +++ b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp @@ -3,7 +3,7 @@ <overview> <p>JavaMail is commonly used in Java applications to send emails. There are popular third-party libraries like Apache Commons Email which are built on JavaMail and facilitate integration. Authenticated mail sessions require user credentials and mail sessions can require SSL/TLS authentication. It is a common security vulnerability that host-specific certificate data is not validated or is incorrectly validated. Failing to validate the certificate makes the SSL session susceptible to a man-in-the-middle attack.</p> - <p>This query checks whether SSL certificate is validated when username/password is sent in authenticator and when SSL is enabled.</p> + <p>This query checks whether the SSL certificate is validated when credentials are used and SSL is enabled in email communications.</p> <p>The query has code for both plain JavaMail invocation and mailing through Apache SimpleMail to make it more comprehensive.</p> </overview> From a86cbd884edf9a2a92593481c359ba51ce888ade Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Tue, 5 Oct 2021 09:40:22 +0200 Subject: [PATCH 139/361] Apply suggestions from code review Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com> --- .../semmle/code/java/frameworks/Mail.qll | 0 .../semmle/code/java/security/Mail.qll | 18 ++++++++++-------- .../Security/CWE/CWE-297/InsecureJavaMail.ql | 5 +++-- .../security/CWE-297/InsecureJavaMailTest.ql | 5 +++-- 4 files changed, 16 insertions(+), 12 deletions(-) rename java/ql/{src => lib}/semmle/code/java/frameworks/Mail.qll (100%) rename java/ql/{src => lib}/semmle/code/java/security/Mail.qll (78%) diff --git a/java/ql/src/semmle/code/java/frameworks/Mail.qll b/java/ql/lib/semmle/code/java/frameworks/Mail.qll similarity index 100% rename from java/ql/src/semmle/code/java/frameworks/Mail.qll rename to java/ql/lib/semmle/code/java/frameworks/Mail.qll diff --git a/java/ql/src/semmle/code/java/security/Mail.qll b/java/ql/lib/semmle/code/java/security/Mail.qll similarity index 78% rename from java/ql/src/semmle/code/java/security/Mail.qll rename to java/ql/lib/semmle/code/java/security/Mail.qll index c100e5c49dc..e126ca57dff 100644 --- a/java/ql/src/semmle/code/java/security/Mail.qll +++ b/java/ql/lib/semmle/code/java/security/Mail.qll @@ -10,10 +10,10 @@ private import semmle.code.java.frameworks.Properties * set the `mail.smtp.ssl.socketFactory`/`mail.smtp.ssl.socketFactory.class` property to create an SMTP SSL socket. * 2. No `mail.smtp.ssl.checkserveridentity` property is enabled. */ -predicate isInsecureMailPropertyConfig(VarAccess propertiesVarAccess) { +predicate isInsecureMailPropertyConfig(Variable properties) { exists(MethodAccess ma | ma.getMethod() instanceof SetPropertyMethod and - ma.getQualifier() = propertiesVarAccess.getVariable().getAnAccess() + ma.getQualifier() = properties.getAnAccess() | getStringValue(ma.getArgument(0)).matches("%.auth%") and //mail.smtp.auth getStringValue(ma.getArgument(1)) = "true" @@ -22,7 +22,7 @@ predicate isInsecureMailPropertyConfig(VarAccess propertiesVarAccess) { ) and not exists(MethodAccess ma | ma.getMethod() instanceof SetPropertyMethod and - ma.getQualifier() = propertiesVarAccess.getVariable().getAnAccess() + ma.getQualifier() = properties.getAnAccess() | getStringValue(ma.getArgument(0)).matches("%.ssl.checkserveridentity%") and //mail.smtp.ssl.checkserveridentity getStringValue(ma.getArgument(1)) = "true" @@ -39,11 +39,11 @@ predicate enablesEmailSsl(MethodAccess ma) { } /** - * Holds if a SSL certificate check is enabled on `va` with Apache Email + * Holds if a SSL certificate check is enabled on an access of `apacheEmail` with Apache Email. */ -predicate hasSslCertificateCheck(VarAccess va) { +predicate hasSslCertificateCheck(Variable apacheEmail) { exists(MethodAccess ma | - ma.getQualifier() = va.getVariable().getAnAccess() and + ma.getQualifier() = apacheEmail.getAnAccess() and ma.getMethod().hasName("setSSLCheckServerIdentity") and ma.getMethod().getDeclaringType() instanceof ApacheEmail and ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true @@ -51,7 +51,8 @@ predicate hasSslCertificateCheck(VarAccess va) { } /** - * Helper method to get string value of an argument + * Returns the string value of `expr` if it is a `CompileTimeConstantExpr`, + * or the string value of its operands if it is an `AddExpr`. */ private string getStringValue(Expr expr) { result = expr.(CompileTimeConstantExpr).getStringValue() @@ -60,7 +61,8 @@ private string getStringValue(Expr expr) { } /** - * A method to set Java properties + * A method to set Java properties, either using the `Properties` class + * or the `Dictionary` class. */ private class SetPropertyMethod extends Method { SetPropertyMethod() { diff --git a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql index 3c6fff0678d..10e122d31c7 100644 --- a/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql +++ b/java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql @@ -5,6 +5,7 @@ * makes the session susceptible to a man-in-the-middle attack. * @kind problem * @problem.severity warning + * @security-severity 5.9 * @precision medium * @id java/insecure-smtp-ssl * @tags security @@ -17,7 +18,7 @@ import semmle.code.java.security.Mail from MethodAccess ma where ma.getMethod() instanceof MailSessionGetInstanceMethod and - isInsecureMailPropertyConfig(ma.getArgument(0)) + isInsecureMailPropertyConfig(ma.getArgument(0).(VarAccess).getVariable()) or - enablesEmailSsl(ma) and not hasSslCertificateCheck(ma.getQualifier()) + enablesEmailSsl(ma) and not hasSslCertificateCheck(ma.getQualifier().(VarAccess).getVariable()) select ma, "Java mailing has insecure SSL configuration" diff --git a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.ql b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.ql index 061aa6711f6..137dde369f9 100644 --- a/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.ql +++ b/java/ql/test/query-tests/security/CWE-297/InsecureJavaMailTest.ql @@ -15,9 +15,10 @@ class InsecureJavaMailTest extends InlineExpectationsTest { value = "" | ma.getMethod() instanceof MailSessionGetInstanceMethod and - isInsecureMailPropertyConfig(ma.getArgument(0)) + isInsecureMailPropertyConfig(ma.getArgument(0).(VarAccess).getVariable()) or - enablesEmailSsl(ma) and not hasSslCertificateCheck(ma.getQualifier()) + enablesEmailSsl(ma) and + not hasSslCertificateCheck(ma.getQualifier().(VarAccess).getVariable()) ) } } From 83ca4ef6d9dd36ed55262fd26df24663f74991c2 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Tue, 5 Oct 2021 08:11:57 +0200 Subject: [PATCH 140/361] JS: Lower security-severity of queries with speculative threat model In the CVSS calculator we model this by setting 'Attack Complexity' to High and 'User Interaction' to Low (as opposed to None). CVSS vector: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:N/I:H/A:N --- javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql | 2 +- .../Security/CWE-078/ShellCommandInjectionFromEnvironment.ql | 2 +- .../ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql | 2 +- javascript/ql/src/Security/CWE-078/UselessUseOfCat.ql | 2 +- javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql b/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql index eb29b56cac3..7520a95ed9c 100644 --- a/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql +++ b/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql @@ -5,7 +5,7 @@ * command-line injection vulnerabilities. * @kind path-problem * @problem.severity warning - * @security-severity 9.8 + * @security-severity 6.3 * @precision medium * @id js/indirect-command-line-injection * @tags correctness diff --git a/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql b/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql index b4bd735d493..cad1039814c 100644 --- a/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql +++ b/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql @@ -4,7 +4,7 @@ * environment may cause subtle bugs or vulnerabilities. * @kind path-problem * @problem.severity warning - * @security-severity 9.8 + * @security-severity 6.3 * @precision high * @id js/shell-command-injection-from-environment * @tags correctness diff --git a/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql b/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql index b0b22a96704..e29a75c1163 100644 --- a/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql +++ b/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql @@ -4,7 +4,7 @@ * user to change the meaning of the command. * @kind path-problem * @problem.severity error - * @security-severity 9.8 + * @security-severity 6.3 * @precision high * @id js/shell-command-constructed-from-input * @tags correctness diff --git a/javascript/ql/src/Security/CWE-078/UselessUseOfCat.ql b/javascript/ql/src/Security/CWE-078/UselessUseOfCat.ql index fd29399546a..e0678b4142b 100644 --- a/javascript/ql/src/Security/CWE-078/UselessUseOfCat.ql +++ b/javascript/ql/src/Security/CWE-078/UselessUseOfCat.ql @@ -3,7 +3,7 @@ * @description Using the `cat` process to read a file is unnecessarily complex, inefficient, unportable, and can lead to subtle bugs, or even security vulnerabilities. * @kind problem * @problem.severity error - * @security-severity 9.8 + * @security-severity 6.3 * @precision high * @id js/unnecessary-use-of-cat * @tags correctness diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql index 9a8ac7b4b73..772297dda63 100644 --- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql +++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql @@ -3,7 +3,7 @@ * @description Writing network data directly to the file system allows arbitrary file upload and might indicate a backdoor. * @kind path-problem * @problem.severity warning - * @security-severity 9.8 + * @security-severity 6.3 * @precision medium * @id js/http-to-file-access * @tags security From 682a71176d15d3baa6ce1625f464768766272633 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Tue, 5 Oct 2021 08:27:03 +0200 Subject: [PATCH 141/361] JS: Make TaintedFormatString have same severity as LogInjection The CWE number for this query is associated with buffer overflows from printf/scanf-style functions in C++, which has likely determined its derived security score. But in JavaScript, a tainted format string is unlikely to lead to anything worse than log injection so we're manually update its score to reflect this. --- javascript/ql/src/Security/CWE-134/TaintedFormatString.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql index 25cb62bd9b1..06f44703a5d 100644 --- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql +++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql @@ -3,7 +3,7 @@ * @description Using external input in format strings can lead to garbled output. * @kind path-problem * @problem.severity warning - * @security-severity 9.3 + * @security-severity 7.3 * @precision high * @id js/tainted-format-string * @tags security From c4e8af983a6a506a1bf7851fccf0d1d564edd0b2 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Tue, 5 Oct 2021 08:42:41 +0200 Subject: [PATCH 142/361] JS: Update score and add CWE-730 to LoopBoundInjection This is a denial-of-service query, but was missing the CWE-730 tag ("denial of service") and consequently had a lower score than the other DoS queries. --- javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql b/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql index 028835343c1..638829de15e 100644 --- a/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql +++ b/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql @@ -4,10 +4,11 @@ * property can cause indefinite looping. * @kind path-problem * @problem.severity warning - * @security-severity 6.5 + * @security-severity 7.5 * @id js/loop-bound-injection * @tags security * external/cwe/cwe-834 + * external/cwe/cwe-730 * @precision high */ From 3a20ca96c4e378a4384fabfe6f551de588f6f93e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Tue, 5 Oct 2021 08:50:32 +0200 Subject: [PATCH 143/361] JS: Update CWE tags and severity score of code injection query The derived security-severity score of the JS code injection query was much lower than for other languages (6.1 versus 9.3), possibly due some differences in CWE tags, such as the inclusion of CWE-079. We also add the more specific CWE-095 ("eval injection") for consistency with other languages. It is a child of CWE-094 ("code injection") which was already tagged. --- javascript/ql/src/Security/CWE-094/CodeInjection.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql index 2934107f1bb..fbf39beaca4 100644 --- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql +++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql @@ -4,11 +4,12 @@ * code execution. * @kind path-problem * @problem.severity error - * @security-severity 6.1 + * @security-severity 9.3 * @precision high * @id js/code-injection * @tags security * external/cwe/cwe-094 + * external/cwe/cwe-095 * external/cwe/cwe-079 * external/cwe/cwe-116 */ From b089e6d84e6165b634320c7b49d1b14d809367a6 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 5 Oct 2021 09:14:20 +0100 Subject: [PATCH 144/361] C++/C#: Fix QLDoc of 'CopyInstruction'. --- .../code/cpp/ir/implementation/aliased_ssa/Instruction.qll | 2 +- .../lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll | 2 +- .../code/cpp/ir/implementation/unaliased_ssa/Instruction.qll | 2 +- .../ql/src/experimental/ir/implementation/raw/Instruction.qll | 2 +- .../ir/implementation/unaliased_ssa/Instruction.qll | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 2fb3edad602..6f471d8a7e8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -821,7 +821,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * * There are several different copy instructions, depending on the source and destination of the * copy operation: - * - `CopyInstruction` - Copies a register operand to a register result. + * - `CopyValueInstruction` - Copies a register operand to a register result. * - `LoadInstruction` - Copies a memory operand to a register result. * - `StoreInstruction` - Copies a register operand to a memory result. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 2fb3edad602..6f471d8a7e8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -821,7 +821,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * * There are several different copy instructions, depending on the source and destination of the * copy operation: - * - `CopyInstruction` - Copies a register operand to a register result. + * - `CopyValueInstruction` - Copies a register operand to a register result. * - `LoadInstruction` - Copies a memory operand to a register result. * - `StoreInstruction` - Copies a register operand to a memory result. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 2fb3edad602..6f471d8a7e8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -821,7 +821,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * * There are several different copy instructions, depending on the source and destination of the * copy operation: - * - `CopyInstruction` - Copies a register operand to a register result. + * - `CopyValueInstruction` - Copies a register operand to a register result. * - `LoadInstruction` - Copies a memory operand to a register result. * - `StoreInstruction` - Copies a register operand to a memory result. */ diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll index 2fb3edad602..6f471d8a7e8 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll @@ -821,7 +821,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * * There are several different copy instructions, depending on the source and destination of the * copy operation: - * - `CopyInstruction` - Copies a register operand to a register result. + * - `CopyValueInstruction` - Copies a register operand to a register result. * - `LoadInstruction` - Copies a memory operand to a register result. * - `StoreInstruction` - Copies a register operand to a memory result. */ diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll index 2fb3edad602..6f471d8a7e8 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll @@ -821,7 +821,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * * There are several different copy instructions, depending on the source and destination of the * copy operation: - * - `CopyInstruction` - Copies a register operand to a register result. + * - `CopyValueInstruction` - Copies a register operand to a register result. * - `LoadInstruction` - Copies a memory operand to a register result. * - `StoreInstruction` - Copies a register operand to a memory result. */ From a17b0d4e5c84bcc22e8b97fc2fe3956d67f93fc7 Mon Sep 17 00:00:00 2001 From: haby0 <ha_yub@163.com> Date: Tue, 5 Oct 2021 17:12:04 +0800 Subject: [PATCH 145/361] Modify Sanitizer --- .../Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql index 270a0444cfb..9f840132fa3 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql @@ -39,10 +39,9 @@ class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configura override predicate isSanitizer(DataFlow::Node node) { exists(Subscript ss | - not ss.getIndex().(IntegerLiteral).getText() = "0" and ss.getObject().(Call).getFunc().(Attribute).getName() = "split" and - ss.getObject().(Call).getArg(0).(StrConst).getText() = "," and - ss.getObject().(Call).getFunc().(Attribute).getObject() = node.asExpr() + ss.getObject().(Call).getAnArg().(StrConst).getText() = "," and + ss = node.asExpr() ) } } From b956238efa5ba77e51a52b28713a0a4dbdf9600c Mon Sep 17 00:00:00 2001 From: Joe Farebrother <joefarebrother@github.com> Date: Tue, 5 Oct 2021 12:01:25 +0100 Subject: [PATCH 146/361] Fill in gen/get methods for tests --- .../frameworks/android/intent/Test.java | 378 +++++++++--------- .../frameworks/android/intent/test.ql | 10 +- 2 files changed, 194 insertions(+), 194 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/android/intent/Test.java b/java/ql/test/library-tests/frameworks/android/intent/Test.java index 725f4880da0..cdee36af212 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/Test.java +++ b/java/ql/test/library-tests/frameworks/android/intent/Test.java @@ -17,13 +17,15 @@ import java.util.Set; public class Test { <T> T getElement(Iterable<T> it) { return it.iterator().next(); } - Object getIntent_extrasDefault(Object container) { return null; } - Object getMapKeyDefault(Object container) { return null; } - Object getMapValueDefault(Object container) { return null; } - Object newWithIntent_extrasDefault(Object element) { return null; } - Object newWithMapKeyDefault(Object element) { return null; } - Object newWithMapValueDefault(Object element) { return null; } - Object source() { return null; } + Bundle getIntent_extras(Intent i) { return i.getExtras(); } + String getMapKey(BaseBundle b) { return b.keySet().iterator().next(); } + Object getMapValue(BaseBundle b) { return null; } + Intent newWithIntent_extras(Bundle b) { return null; } + Bundle newBundleWithMapKey(String k) { Bundle b = new Bundle(); b.putInt(k, 0); return b; } + PersistableBundle newPersistableBundleWithMapKey(String k) { PersistableBundle b = new PersistableBundle(); b.putInt(k, 0); return b; } + Bundle newBundleWithMapValue(Object element) { return null; } + PersistableBundle newPersistableBundleWithMapValue(Object element) { return null; } + <T> T source() { return null; } void sink(Object o) { } public void test() throws Exception { @@ -31,16 +33,16 @@ public class Test { { // "android.content;Intent;false;Intent;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapKeyDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapKey(source())); out = new Intent(in); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;false;Intent;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = new Intent(in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value" @@ -59,98 +61,98 @@ public class Test { { // "android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Bundle out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getBundleExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" byte[] out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getByteArrayExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getCharArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" char[] out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getCharArrayExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getCharSequenceArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" CharSequence[] out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getCharSequenceArrayExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getCharSequenceArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" ArrayList out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getCharSequenceArrayListExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getCharSequenceExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" CharSequence out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getCharSequenceExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Bundle out = null; - Intent in = (Intent)newWithIntent_extrasDefault(source()); + Intent in = (Intent)newWithIntent_extras(source()); out = in.getExtras(); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Parcelable[] out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getParcelableArrayExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getParcelableArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" ArrayList out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getParcelableArrayListExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getParcelableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Parcelable out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getParcelableExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getSerializableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Serializable out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getSerializableExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getStringArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" String[] out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getStringArrayExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getStringArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" ArrayList out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getStringArrayListExtra(null); sink(out); // $ hasValueFlow } { // "android.content;Intent;true;getStringExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" String out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out = in.getStringExtra(null); sink(out); // $ hasValueFlow } @@ -166,14 +168,14 @@ public class Test { Intent out = null; String in = (String)source(); out.putCharSequenceArrayListExtra(in, null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; ArrayList in = (ArrayList)source(); out.putCharSequenceArrayListExtra(null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value" @@ -348,336 +350,336 @@ public class Test { Intent out = null; String in = (String)source(); out.putExtra(in, false); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, 0L); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, 0.0f); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, 0.0); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, 0); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (short[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (short)0); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (long[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (int[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (float[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (double[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (char[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (byte[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (byte)0); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (boolean[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (String[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (String)null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (Serializable)null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (Parcelable[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (Parcelable)null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (CharSequence[])null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (CharSequence)null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, (Bundle)null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra(in, '\0'); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; short[] in = (short[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; short in = (short)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; long[] in = (long[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; long in = (long)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; int[] in = (int[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; int in = (int)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; float[] in = (float[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; float in = (float)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; double[] in = (double[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; double in = (double)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; char[] in = (char[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; char in = (char)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; byte[] in = (byte[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; byte in = (byte)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; boolean[] in = (boolean[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; boolean in = (boolean)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String[] in = (String[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; String in = (String)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; Serializable in = (Serializable)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; Parcelable[] in = (Parcelable[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; Parcelable in = (Parcelable)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; CharSequence[] in = (CharSequence[])source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; CharSequence in = (CharSequence)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; Bundle in = (Bundle)source(); out.putExtra((String)null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtras;(Bundle);;Argument[-1];ReturnValue;value" @@ -689,16 +691,16 @@ public class Test { { // "android.content;Intent;true;putExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Bundle in = (Bundle)newWithMapKeyDefault(source()); + Bundle in = (Bundle)newBundleWithMapKey(source()); out.putExtras(in); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out.putExtras(in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtras;(Intent);;Argument[-1];ReturnValue;value" @@ -710,16 +712,16 @@ public class Test { { // "android.content;Intent;true;putExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapKeyDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapKey(source())); out.putExtras(in); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out.putExtras(in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putIntegerArrayListExtra;;;Argument[-1];ReturnValue;value" @@ -733,7 +735,7 @@ public class Test { Intent out = null; String in = (String)source(); out.putIntegerArrayListExtra(in, null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[-1];ReturnValue;value" @@ -747,14 +749,14 @@ public class Test { Intent out = null; String in = (String)source(); out.putParcelableArrayListExtra(in, null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; ArrayList in = (ArrayList)source(); out.putParcelableArrayListExtra(null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putStringArrayListExtra;;;Argument[-1];ReturnValue;value" @@ -768,14 +770,14 @@ public class Test { Intent out = null; String in = (String)source(); out.putStringArrayListExtra(in, null); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;putStringArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; ArrayList in = (ArrayList)source(); out.putStringArrayListExtra(null, in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;replaceExtras;(Bundle);;Argument[-1];ReturnValue;value" @@ -787,16 +789,16 @@ public class Test { { // "android.content;Intent;true;replaceExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Bundle in = (Bundle)newWithMapKeyDefault(source()); + Bundle in = (Bundle)newBundleWithMapKey(source()); out.replaceExtras(in); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;replaceExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out.replaceExtras(in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;replaceExtras;(Intent);;Argument[-1];ReturnValue;value" @@ -808,16 +810,16 @@ public class Test { { // "android.content;Intent;true;replaceExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapKeyDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapKey(source())); out.replaceExtras(in); - sink(getMapKeyDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapKey(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;replaceExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value" Intent out = null; - Intent in = (Intent)newWithIntent_extrasDefault(newWithMapValueDefault(source())); + Intent in = (Intent)newWithIntent_extras(newBundleWithMapValue(source())); out.replaceExtras(in); - sink(getMapValueDefault(getIntent_extrasDefault(out))); // $ hasValueFlow + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } { // "android.content;Intent;true;setAction;;;Argument[-1];ReturnValue;value" @@ -920,14 +922,14 @@ public class Test { { // "android.os;BaseBundle;true;get;(String);;MapValue of Argument[-1];ReturnValue;value" Object out = null; - BaseBundle in = (BaseBundle)newWithMapValueDefault(source()); + BaseBundle in = (BaseBundle)newBundleWithMapValue(source()); out = in.get(null); sink(out); // $ hasValueFlow } { // "android.os;BaseBundle;true;getString;(String);;MapValue of Argument[-1];ReturnValue;value" String out = null; - BaseBundle in = (BaseBundle)newWithMapValueDefault(source()); + BaseBundle in = (BaseBundle)newBundleWithMapValue(source()); out = in.getString(null); sink(out); // $ hasValueFlow } @@ -942,210 +944,210 @@ public class Test { { // "android.os;BaseBundle;true;getString;(String,String);;MapValue of Argument[-1];ReturnValue;value" String out = null; - BaseBundle in = (BaseBundle)newWithMapValueDefault(source()); + BaseBundle in = (BaseBundle)newBundleWithMapValue(source()); out = in.getString(null, null); sink(out); // $ hasValueFlow } { // "android.os;BaseBundle;true;getStringArray;(String);;MapValue of Argument[-1];ReturnValue;value" String[] out = null; - BaseBundle in = (BaseBundle)newWithMapValueDefault(source()); + BaseBundle in = (BaseBundle)newBundleWithMapValue(source()); out = in.getStringArray(null); sink(out); // $ hasValueFlow } { // "android.os;BaseBundle;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value" Set out = null; - BaseBundle in = (BaseBundle)newWithMapKeyDefault(source()); + BaseBundle in = (BaseBundle)newBundleWithMapKey(source()); out = in.keySet(); sink(getElement(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putAll;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; - PersistableBundle in = (PersistableBundle)newWithMapKeyDefault(source()); + PersistableBundle in = newPersistableBundleWithMapKey(source()); out.putAll(in); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putAll;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value" BaseBundle out = null; - PersistableBundle in = (PersistableBundle)newWithMapValueDefault(source()); + PersistableBundle in = newPersistableBundleWithMapValue(source()); out.putAll(in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putBoolean;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putBoolean(in, false); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putBooleanArray;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putBooleanArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putDouble;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putDouble(in, 0.0); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putDoubleArray;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putDoubleArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putInt;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putInt(in, 0); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putIntArray;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putIntArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putLong;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putLong(in, 0L); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putLongArray;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putLongArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putString;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putString(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putString;;;Argument[1];MapValue of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putString(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putStringArray;;;Argument[0];MapKey of Argument[-1];value" BaseBundle out = null; String in = (String)source(); out.putStringArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;BaseBundle;true;putStringArray;;;Argument[1];MapValue of Argument[-1];value" BaseBundle out = null; String[] in = (String[])source(); out.putStringArray(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;false;Bundle;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value" Bundle out = null; - Bundle in = (Bundle)newWithMapKeyDefault(source()); + Bundle in = (Bundle)newBundleWithMapKey(source()); out = new Bundle(in); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;false;Bundle;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value" Bundle out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = new Bundle(in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;false;Bundle;(PersistableBundle);;MapKey of Argument[0];MapKey of Argument[-1];value" Bundle out = null; - PersistableBundle in = (PersistableBundle)newWithMapKeyDefault(source()); + PersistableBundle in = newPersistableBundleWithMapKey(source()); out = new Bundle(in); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;false;Bundle;(PersistableBundle);;MapValue of Argument[0];MapValue of Argument[-1];value" Bundle out = null; - PersistableBundle in = (PersistableBundle)newWithMapValueDefault(source()); + PersistableBundle in = newPersistableBundleWithMapValue(source()); out = new Bundle(in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;clone;();;MapKey of Argument[-1];MapKey of ReturnValue;value" Object out = null; - Bundle in = (Bundle)newWithMapKeyDefault(source()); + Bundle in = (Bundle)newBundleWithMapKey(source()); out = in.clone(); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey((Bundle)out)); // $ hasValueFlow } { // "android.os;Bundle;true;clone;();;MapValue of Argument[-1];MapValue of ReturnValue;value" Object out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.clone(); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue((Bundle)out)); // $ hasValueFlow } { // "android.os;Bundle;true;deepCopy;();;MapKey of Argument[-1];MapKey of ReturnValue;value" Bundle out = null; - Bundle in = (Bundle)newWithMapKeyDefault(source()); + Bundle in = (Bundle)newBundleWithMapKey(source()); out = in.deepCopy(); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;deepCopy;();;MapValue of Argument[-1];MapValue of ReturnValue;value" Bundle out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.deepCopy(); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;getBinder;(String);;MapValue of Argument[-1];ReturnValue;value" IBinder out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getBinder(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getBundle;(String);;MapValue of Argument[-1];ReturnValue;value" Bundle out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getBundle(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getByteArray;(String);;MapValue of Argument[-1];ReturnValue;value" byte[] out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getByteArray(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getCharArray;(String);;MapValue of Argument[-1];ReturnValue;value" char[] out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getCharArray(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getCharSequence;(String);;MapValue of Argument[-1];ReturnValue;value" CharSequence out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getCharSequence(null); sink(out); // $ hasValueFlow } @@ -1160,338 +1162,338 @@ public class Test { { // "android.os;Bundle;true;getCharSequence;(String,CharSequence);;MapValue of Argument[-1];ReturnValue;value" CharSequence out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getCharSequence(null, null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getCharSequenceArray;(String);;MapValue of Argument[-1];ReturnValue;value" CharSequence[] out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getCharSequenceArray(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getCharSequenceArrayList;(String);;MapValue of Argument[-1];ReturnValue;value" ArrayList out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getCharSequenceArrayList(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getParcelable;(String);;MapValue of Argument[-1];ReturnValue;value" Parcelable out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getParcelable(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value" Parcelable[] out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getParcelableArray(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getParcelableArrayList;(String);;MapValue of Argument[-1];ReturnValue;value" ArrayList out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getParcelableArrayList(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getSerializable;(String);;MapValue of Argument[-1];ReturnValue;value" Serializable out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getSerializable(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getSparseParcelableArray;(String);;MapValue of Argument[-1];ReturnValue;value" SparseArray out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getSparseParcelableArray(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;getStringArrayList;(String);;MapValue of Argument[-1];ReturnValue;value" ArrayList out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out = in.getStringArrayList(null); sink(out); // $ hasValueFlow } { // "android.os;Bundle;true;putAll;(Bundle);;MapKey of Argument[0];MapKey of Argument[-1];value" Bundle out = null; - Bundle in = (Bundle)newWithMapKeyDefault(source()); + Bundle in = (Bundle)newBundleWithMapKey(source()); out.putAll(in); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putAll;(Bundle);;MapValue of Argument[0];MapValue of Argument[-1];value" Bundle out = null; - Bundle in = (Bundle)newWithMapValueDefault(source()); + Bundle in = (Bundle)newBundleWithMapValue(source()); out.putAll(in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putBinder;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putBinder(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putBinder;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; IBinder in = (IBinder)source(); out.putBinder(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putBundle;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putBundle(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putBundle;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; Bundle in = (Bundle)source(); out.putBundle(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putByte;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putByte(in, (byte)0); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putByteArray;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putByteArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putByteArray;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; byte[] in = (byte[])source(); out.putByteArray(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putChar;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putChar(in, '\0'); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putCharArray;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putCharArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putCharArray;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; char[] in = (char[])source(); out.putCharArray(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putCharSequence;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putCharSequence(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putCharSequence;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; CharSequence in = (CharSequence)source(); out.putCharSequence(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putCharSequenceArray;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putCharSequenceArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putCharSequenceArray;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; CharSequence[] in = (CharSequence[])source(); out.putCharSequenceArray(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putCharSequenceArrayList;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putCharSequenceArrayList(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putCharSequenceArrayList;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; ArrayList in = (ArrayList)source(); out.putCharSequenceArrayList(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putFloat;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putFloat(in, 0.0f); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putFloatArray;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putFloatArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putIntegerArrayList;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putIntegerArrayList(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putParcelable;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putParcelable(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putParcelable;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; Parcelable in = (Parcelable)source(); out.putParcelable(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putParcelableArray;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putParcelableArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putParcelableArray;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; Parcelable[] in = (Parcelable[])source(); out.putParcelableArray(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putParcelableArrayList;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putParcelableArrayList(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putParcelableArrayList;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; ArrayList in = (ArrayList)source(); out.putParcelableArrayList(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putSerializable;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putSerializable(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putSerializable;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; Serializable in = (Serializable)source(); out.putSerializable(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putShort;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putShort(in, (short)0); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putShortArray;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putShortArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putSize;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putSize(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putSizeF;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putSizeF(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putSparseParcelableArray;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putSparseParcelableArray(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putSparseParcelableArray;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; SparseArray in = (SparseArray)source(); out.putSparseParcelableArray(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putStringArrayList;;;Argument[0];MapKey of Argument[-1];value" Bundle out = null; String in = (String)source(); out.putStringArrayList(in, null); - sink(getMapKeyDefault(out)); // $ hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value" Bundle out = null; ArrayList in = (ArrayList)source(); out.putStringArrayList(null, in); - sink(getMapValueDefault(out)); // $ hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint" Bundle out = null; Parcel in = (Parcel)source(); out.readFromParcel(in); - sink(getMapKeyDefault(out)); // $ hasTaintFlow + sink(getMapKey(out)); // $ hasTaintFlow } { // "android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint" Bundle out = null; Parcel in = (Parcel)source(); out.readFromParcel(in); - sink(getMapValueDefault(out)); // $ hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/android/intent/test.ql b/java/ql/test/library-tests/frameworks/android/intent/test.ql index e89ac1ba290..d4bdcaf9335 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/test.ql +++ b/java/ql/test/library-tests/frameworks/android/intent/test.ql @@ -6,12 +6,10 @@ class SummaryModelTest extends SummaryModelCsv { row = [ //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", - "generatedtest;Test;false;newWithMapKeyDefault;(Object);;Argument[0];MapKey of ReturnValue;value", - "generatedtest;Test;false;getMapKeyDefault;(Object);;MapKey of Argument[0];ReturnValue;value", - "generatedtest;Test;false;newWithMapValueDefault;(Object);;Argument[0];MapValue of ReturnValue;value", - "generatedtest;Test;false;getMapValueDefault;(Object);;MapValue of Argument[0];ReturnValue;value", - "generatedtest;Test;false;newWithIntent_extrasDefault;(Object);;Argument[0];SyntheticField[android.content.Intent.extras] of ReturnValue;value", - "generatedtest;Test;false;getIntent_extrasDefault;(Object);;SyntheticField[android.content.Intent.extras] of Argument[0];ReturnValue;value" + "generatedtest;Test;false;newBundleWithMapValue;(Object);;Argument[0];MapValue of ReturnValue;value", + "generatedtest;Test;false;newPersistableBundleWithMapValue;(Object);;Argument[0];MapValue of ReturnValue;value", + "generatedtest;Test;false;getMapValue;(BaseBundle);;MapValue of Argument[0];ReturnValue;value", + "generatedtest;Test;false;newWithIntent_extras;(Bundle);;Argument[0];SyntheticField[android.content.Intent.extras] of ReturnValue;value" ] } } From ef8026310685e74b690d9329218d2429612d7fd9 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Tue, 28 Sep 2021 15:20:56 +0200 Subject: [PATCH 147/361] Java: Add models for java.util.stream. --- .../code/java/dataflow/ExternalFlow.qll | 1 + .../semmle/code/java/frameworks/Stream.qll | 87 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 java/ql/lib/semmle/code/java/frameworks/Stream.qll diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index b57f341dd5c..57297949a6a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -91,6 +91,7 @@ private module Frameworks { private import semmle.code.java.frameworks.JsonJava private import semmle.code.java.frameworks.Objects private import semmle.code.java.frameworks.Optional + private import semmle.code.java.frameworks.Stream private import semmle.code.java.frameworks.Strings private import semmle.code.java.frameworks.spring.SpringCache private import semmle.code.java.frameworks.spring.SpringHttp diff --git a/java/ql/lib/semmle/code/java/frameworks/Stream.qll b/java/ql/lib/semmle/code/java/frameworks/Stream.qll new file mode 100644 index 00000000000..586240a3e31 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/Stream.qll @@ -0,0 +1,87 @@ +/** Definitions related to `java.util.stream`. */ + +import semmle.code.java.dataflow.ExternalFlow + +private class StreamModel extends SummaryModelCsv { + override predicate row(string s) { + s = + [ + "java.util.stream;BaseStream;false;iterator;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;false;onClose;(Runnable);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;false;parallel;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;false;sequential;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;false;spliterator;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;false;unordered;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;allMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;anyMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;ReturnValue of Argument[0];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];ReturnValue;value", + "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];Parameter[0..1] of Argument[2];value", + "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0..1] of Argument[2];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;Element of Argument[-1];Parameter[1] of Argument[1];value", + // Missing: collect(Collector<T,A,R> collector) + "java.util.stream;Stream;false;concat;(Stream,Stream);;Element of Argument[0..1];Element of ReturnValue;value", + "java.util.stream;Stream;false;distinct;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;dropWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;dropWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;filter;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;filter;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;findAny;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;findFirst;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;flatMap;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;flatMap;(Function);;Element of ReturnValue of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;flatMapToDouble;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;flatMapToInt;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;flatMapToLong;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;forEach;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;forEachOrdered;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;generate;(Supplier);;ReturnValue of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Parameter[0] of Argument[1..2];value", + "java.util.stream;Stream;false;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Element of ReturnValue;value", + "java.util.stream;Stream;false;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Parameter[0] of Argument[1..2];value", + "java.util.stream;Stream;false;iterate;(Object,UnaryOperator);;Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;iterate;(Object,UnaryOperator);;Argument[0];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;false;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Element of ReturnValue;value", + "java.util.stream;Stream;false;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;false;limit;(long);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;map;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;map;(Function);;ReturnValue of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;mapToDouble;(ToDoubleFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;mapToInt;(ToIntFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;mapToLong;(ToLongFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;max;(Comparator);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;max;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;false;min;(Comparator);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;min;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;false;noneMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;of;(Object);;Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;ofNullable;(Object);;Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;peek;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;peek;(Consumer);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;reduce;(BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;false;reduce;(BinaryOperator);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;reduce;(BinaryOperator);;ReturnValue of Argument[0];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;false;reduce;(BinaryOperator);;ReturnValue of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[1];value", + "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[1];value", + "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;Argument[0];ReturnValue;value", + "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];Parameter[0..1] of Argument[1];value", + "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];ReturnValue;value", + "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;Element of Argument[-1];Parameter[1] of Argument[1];value", + "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[2];value", + "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];ReturnValue;value", + "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0..1] of Argument[2];value", + "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];ReturnValue;value", + "java.util.stream;Stream;false;skip;(long);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;sorted;;;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;sorted;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;false;takeWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;takeWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;false;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value" + ] + } +} From af7d633f2f8acbed231d3eb8369256c850dfb5d0 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Thu, 30 Sep 2021 11:22:49 +0200 Subject: [PATCH 148/361] Java: Add Stream::mapMulti* and Stream::toList. --- java/ql/lib/semmle/code/java/frameworks/Stream.qll | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/Stream.qll b/java/ql/lib/semmle/code/java/frameworks/Stream.qll index 586240a3e31..7a8c6811552 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Stream.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Stream.qll @@ -47,6 +47,13 @@ private class StreamModel extends SummaryModelCsv { "java.util.stream;Stream;false;limit;(long);;Element of Argument[-1];Element of ReturnValue;value", "java.util.stream;Stream;false;map;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", "java.util.stream;Stream;false;map;(Function);;ReturnValue of Argument[0];Element of ReturnValue;value", + // Missing for mapMulti(BiConsumer) (not currently supported): + // Argument[0] of Parameter[1] of Argument[0] -> Element of Parameter[1] of Argument[0] + // Element of Parameter[1] of Argument[0] -> Element of ReturnValue + "java.util.stream;Stream;false;mapMulti;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;mapMultiToDouble;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;mapMultiToInt;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;false;mapMultiToLong;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", "java.util.stream;Stream;false;mapToDouble;(ToDoubleFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", "java.util.stream;Stream;false;mapToInt;(ToIntFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", "java.util.stream;Stream;false;mapToLong;(ToLongFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", @@ -81,7 +88,8 @@ private class StreamModel extends SummaryModelCsv { "java.util.stream;Stream;false;sorted;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", "java.util.stream;Stream;false;takeWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", "java.util.stream;Stream;false;takeWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value" + "java.util.stream;Stream;false;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + "java.util.stream;Stream;false;toList;();;Element of Argument[-1];Element of ReturnValue;value" ] } } From 04892df45ae6ed5da801b7b23d71710f2e868b53 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Thu, 30 Sep 2021 11:33:24 +0200 Subject: [PATCH 149/361] Java: Include stream method overrides. --- .../semmle/code/java/frameworks/Stream.qll | 160 +++++++++--------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/Stream.qll b/java/ql/lib/semmle/code/java/frameworks/Stream.qll index 7a8c6811552..6f2faafa9bc 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Stream.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Stream.qll @@ -6,90 +6,90 @@ private class StreamModel extends SummaryModelCsv { override predicate row(string s) { s = [ - "java.util.stream;BaseStream;false;iterator;();;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;BaseStream;false;onClose;(Runnable);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;BaseStream;false;parallel;();;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;BaseStream;false;sequential;();;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;BaseStream;false;spliterator;();;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;BaseStream;false;unordered;();;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;allMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;anyMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;ReturnValue of Argument[0];Parameter[0] of Argument[1];value", - "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];ReturnValue;value", - "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];Parameter[0..1] of Argument[2];value", - "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0..1] of Argument[2];Parameter[0] of Argument[1];value", - "java.util.stream;Stream;false;collect;(Supplier,BiConsumer,BiConsumer);;Element of Argument[-1];Parameter[1] of Argument[1];value", + "java.util.stream;BaseStream;true;iterator;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;true;onClose;(Runnable);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;true;parallel;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;true;sequential;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;true;spliterator;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;BaseStream;true;unordered;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;allMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;anyMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;ReturnValue of Argument[0];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];ReturnValue;value", + "java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];Parameter[0..1] of Argument[2];value", + "java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0..1] of Argument[2];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Element of Argument[-1];Parameter[1] of Argument[1];value", // Missing: collect(Collector<T,A,R> collector) - "java.util.stream;Stream;false;concat;(Stream,Stream);;Element of Argument[0..1];Element of ReturnValue;value", - "java.util.stream;Stream;false;distinct;();;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;dropWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;dropWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;filter;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;filter;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;findAny;();;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;findFirst;();;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;flatMap;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;flatMap;(Function);;Element of ReturnValue of Argument[0];Element of ReturnValue;value", - "java.util.stream;Stream;false;flatMapToDouble;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;flatMapToInt;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;flatMapToLong;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;forEach;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;forEachOrdered;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;generate;(Supplier);;ReturnValue of Argument[0];Element of ReturnValue;value", - "java.util.stream;Stream;false;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Element of ReturnValue;value", - "java.util.stream;Stream;false;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Parameter[0] of Argument[1..2];value", - "java.util.stream;Stream;false;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Element of ReturnValue;value", - "java.util.stream;Stream;false;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Parameter[0] of Argument[1..2];value", - "java.util.stream;Stream;false;iterate;(Object,UnaryOperator);;Argument[0];Element of ReturnValue;value", - "java.util.stream;Stream;false;iterate;(Object,UnaryOperator);;Argument[0];Parameter[0] of Argument[1];value", - "java.util.stream;Stream;false;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Element of ReturnValue;value", - "java.util.stream;Stream;false;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Parameter[0] of Argument[1];value", - "java.util.stream;Stream;false;limit;(long);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;map;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;map;(Function);;ReturnValue of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;concat;(Stream,Stream);;Element of Argument[0..1];Element of ReturnValue;value", + "java.util.stream;Stream;true;distinct;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;dropWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;dropWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;filter;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;filter;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;findAny;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;findFirst;();;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;flatMap;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;flatMap;(Function);;Element of ReturnValue of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;flatMapToDouble;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;flatMapToInt;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;flatMapToLong;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;forEach;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;forEachOrdered;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;generate;(Supplier);;ReturnValue of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Parameter[0] of Argument[1..2];value", + "java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Element of ReturnValue;value", + "java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Parameter[0] of Argument[1..2];value", + "java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Element of ReturnValue;value", + "java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;true;limit;(long);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;map;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;map;(Function);;ReturnValue of Argument[0];Element of ReturnValue;value", // Missing for mapMulti(BiConsumer) (not currently supported): // Argument[0] of Parameter[1] of Argument[0] -> Element of Parameter[1] of Argument[0] // Element of Parameter[1] of Argument[0] -> Element of ReturnValue - "java.util.stream;Stream;false;mapMulti;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;mapMultiToDouble;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;mapMultiToInt;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;mapMultiToLong;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;mapToDouble;(ToDoubleFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;mapToInt;(ToIntFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;mapToLong;(ToLongFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;max;(Comparator);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;max;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", - "java.util.stream;Stream;false;min;(Comparator);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;min;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", - "java.util.stream;Stream;false;noneMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;of;(Object);;Argument[0];Element of ReturnValue;value", - "java.util.stream;Stream;false;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", - "java.util.stream;Stream;false;ofNullable;(Object);;Argument[0];Element of ReturnValue;value", - "java.util.stream;Stream;false;peek;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;peek;(Consumer);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;reduce;(BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", - "java.util.stream;Stream;false;reduce;(BinaryOperator);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;reduce;(BinaryOperator);;ReturnValue of Argument[0];Parameter[0..1] of Argument[0];value", - "java.util.stream;Stream;false;reduce;(BinaryOperator);;ReturnValue of Argument[0];Element of ReturnValue;value", - "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[1];value", - "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[1];value", - "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;Argument[0];ReturnValue;value", - "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];Parameter[0..1] of Argument[1];value", - "java.util.stream;Stream;false;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];ReturnValue;value", - "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;Element of Argument[-1];Parameter[1] of Argument[1];value", - "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0] of Argument[1];value", - "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[2];value", - "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];ReturnValue;value", - "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0] of Argument[1];value", - "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0..1] of Argument[2];value", - "java.util.stream;Stream;false;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];ReturnValue;value", - "java.util.stream;Stream;false;skip;(long);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;sorted;;;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;sorted;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", - "java.util.stream;Stream;false;takeWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", - "java.util.stream;Stream;false;takeWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", - "java.util.stream;Stream;false;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", - "java.util.stream;Stream;false;toList;();;Element of Argument[-1];Element of ReturnValue;value" + "java.util.stream;Stream;true;mapMulti;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;mapMultiToDouble;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;mapMultiToInt;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;mapMultiToLong;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;mapToDouble;(ToDoubleFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;mapToInt;(ToIntFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;mapToLong;(ToLongFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;max;(Comparator);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;max;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;true;min;(Comparator);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;min;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;true;noneMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;of;(Object);;Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;ofNullable;(Object);;Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;peek;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;peek;(Consumer);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;reduce;(BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;true;reduce;(BinaryOperator);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;reduce;(BinaryOperator);;ReturnValue of Argument[0];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;true;reduce;(BinaryOperator);;ReturnValue of Argument[0];Element of ReturnValue;value", + "java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[1];value", + "java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[1];value", + "java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];ReturnValue;value", + "java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];Parameter[0..1] of Argument[1];value", + "java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];ReturnValue;value", + "java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Element of Argument[-1];Parameter[1] of Argument[1];value", + "java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[2];value", + "java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];ReturnValue;value", + "java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0] of Argument[1];value", + "java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0..1] of Argument[2];value", + "java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];ReturnValue;value", + "java.util.stream;Stream;true;skip;(long);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;sorted;;;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;sorted;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value", + "java.util.stream;Stream;true;takeWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value", + "java.util.stream;Stream;true;takeWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value", + "java.util.stream;Stream;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + "java.util.stream;Stream;true;toList;();;Element of Argument[-1];Element of ReturnValue;value" ] } } From 9133adac3046e167fc8155f2f0e6dd68ad4f41a4 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Fri, 1 Oct 2021 14:03:35 +0200 Subject: [PATCH 150/361] Java: Adjust csv validation. --- java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index 57297949a6a..84b583156da 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -574,7 +574,7 @@ module CsvValidation { not (part = "Argument" and pred = "sink") and not parseArg(part, _) or - specSplit(input, part, _) and + part = specLast(input) and parseParam(part, _) ) and msg = "Unrecognized input specification \"" + part + "\" in " + pred + " model." From 0590e2a5fb48629301e9c83055e715f53aecaba5 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg <aeisenberg@github.com> Date: Tue, 5 Oct 2021 13:42:36 -0700 Subject: [PATCH 151/361] Ignore .codeql folder --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 0951496d45c..bf37ce08333 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ /codeql/ csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json + +# Avoid committing cached package components +.codeql From 57ef989a892531dcd4f9393e66d16dca21673561 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg <aeisenberg@github.com> Date: Tue, 5 Oct 2021 11:30:39 -0700 Subject: [PATCH 152/361] Fixes compile errors by moving files The two files moved in this commit are referenced from the javascript/lib qlpack, but they are located in the javascript/src qlpack. This causes compile errors when running compile-ish commands for javascript queries. Moving the files fixes it. --- javascript/ql/{src => lib}/Declarations/UnusedVariable.qll | 0 javascript/ql/{src => lib}/Expressions/DOMProperties.qll | 0 javascript/ql/{src => lib}/Expressions/ExprHasNoEffect.qll | 0 .../ql/{src => lib}/LanguageFeatures/UnusedIndexVariable.qll | 0 javascript/ql/src/Declarations/UnusedProperty.ql | 2 +- javascript/ql/src/Declarations/UnusedVariable.ql | 2 +- javascript/ql/src/Expressions/ExprHasNoEffect.ql | 2 +- javascript/ql/src/Expressions/SelfAssignment.ql | 2 +- javascript/ql/src/LanguageFeatures/UnusedIndexVariable.ql | 2 +- 9 files changed, 5 insertions(+), 5 deletions(-) rename javascript/ql/{src => lib}/Declarations/UnusedVariable.qll (100%) rename javascript/ql/{src => lib}/Expressions/DOMProperties.qll (100%) rename javascript/ql/{src => lib}/Expressions/ExprHasNoEffect.qll (100%) rename javascript/ql/{src => lib}/LanguageFeatures/UnusedIndexVariable.qll (100%) diff --git a/javascript/ql/src/Declarations/UnusedVariable.qll b/javascript/ql/lib/Declarations/UnusedVariable.qll similarity index 100% rename from javascript/ql/src/Declarations/UnusedVariable.qll rename to javascript/ql/lib/Declarations/UnusedVariable.qll diff --git a/javascript/ql/src/Expressions/DOMProperties.qll b/javascript/ql/lib/Expressions/DOMProperties.qll similarity index 100% rename from javascript/ql/src/Expressions/DOMProperties.qll rename to javascript/ql/lib/Expressions/DOMProperties.qll diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.qll b/javascript/ql/lib/Expressions/ExprHasNoEffect.qll similarity index 100% rename from javascript/ql/src/Expressions/ExprHasNoEffect.qll rename to javascript/ql/lib/Expressions/ExprHasNoEffect.qll diff --git a/javascript/ql/src/LanguageFeatures/UnusedIndexVariable.qll b/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll similarity index 100% rename from javascript/ql/src/LanguageFeatures/UnusedIndexVariable.qll rename to javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll diff --git a/javascript/ql/src/Declarations/UnusedProperty.ql b/javascript/ql/src/Declarations/UnusedProperty.ql index e9e38409bcb..19d43a09db2 100644 --- a/javascript/ql/src/Declarations/UnusedProperty.ql +++ b/javascript/ql/src/Declarations/UnusedProperty.ql @@ -10,7 +10,7 @@ import javascript import semmle.javascript.dataflow.LocalObjects -import UnusedVariable +import Declarations.UnusedVariable import UnusedParameter import Expressions.ExprHasNoEffect diff --git a/javascript/ql/src/Declarations/UnusedVariable.ql b/javascript/ql/src/Declarations/UnusedVariable.ql index 773672197a1..8fb405a7cf9 100644 --- a/javascript/ql/src/Declarations/UnusedVariable.ql +++ b/javascript/ql/src/Declarations/UnusedVariable.ql @@ -10,7 +10,7 @@ */ import javascript -import UnusedVariable +import Declarations.UnusedVariable /** * Holds if `v` is mentioned in a JSDoc comment in the same file, and that file diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.ql b/javascript/ql/src/Expressions/ExprHasNoEffect.ql index 5ef6be7ba14..f0cd3addcb6 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.ql +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.ql @@ -13,7 +13,7 @@ */ import javascript -import ExprHasNoEffect +import Expressions.ExprHasNoEffect import semmle.javascript.RestrictedLocations from Expr e diff --git a/javascript/ql/src/Expressions/SelfAssignment.ql b/javascript/ql/src/Expressions/SelfAssignment.ql index ff324831cf6..6aab4c46bb2 100644 --- a/javascript/ql/src/Expressions/SelfAssignment.ql +++ b/javascript/ql/src/Expressions/SelfAssignment.ql @@ -12,7 +12,7 @@ */ import Clones -import DOMProperties +import Expressions.DOMProperties /** * Gets a description of expression `e`, which is assumed to be the left-hand diff --git a/javascript/ql/src/LanguageFeatures/UnusedIndexVariable.ql b/javascript/ql/src/LanguageFeatures/UnusedIndexVariable.ql index da3c1d4b4cf..ba39738a777 100644 --- a/javascript/ql/src/LanguageFeatures/UnusedIndexVariable.ql +++ b/javascript/ql/src/LanguageFeatures/UnusedIndexVariable.ql @@ -10,7 +10,7 @@ */ import javascript -import UnusedIndexVariable +import LanguageFeatures.UnusedIndexVariable from RelationalComparison rel, Variable idx, Variable v where unusedIndexVariable(rel, idx, v) From 33ee947f8dcb62f68f1539163df2ae5f1b902fe1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 Oct 2021 00:08:24 +0000 Subject: [PATCH 153/361] Add changed framework coverage reports --- java/documentation/library-coverage/coverage.csv | 3 ++- java/documentation/library-coverage/coverage.rst | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index 08c55d973dd..7d57763fefb 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -1,7 +1,8 @@ package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:jexl,sink:jndi-injection,sink:ldap,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value -android.content,8,27,4,,,,,,,,,,,,,8,,,,,,27,,4, +android.content,8,27,61,,,,,,,,,,,,,8,,,,,,27,,4,57 android.database,59,,30,,,,,,,,,,,,,59,,,,,,,,30, android.net,,,60,,,,,,,,,,,,,,,,,,,,,45,15 +android.os,,,82,,,,,,,,,,,,,,,,,,,,,2,80 android.util,,16,,,,,,,,,,,,,,,,,,,,,16,, android.webkit,3,2,,,,,,,,,,,,,,,,,,,3,,2,, cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,1, diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index a39dba6452b..be2984fa4c0 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -7,7 +7,7 @@ Java framework & library support :widths: auto Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :sub:`Cleartext transmission` - Android,``android.*``,45,94,70,,,3,67,,, + Android,``android.*``,45,233,70,,,3,67,,, `Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,, `Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,22,,,,,,,, `Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,423,,,,,,,, @@ -19,5 +19,5 @@ Java framework & library support Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2 `Spring <https://spring.io/>`_,``org.springframework.*``,29,469,91,,,,19,14,,29 Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,28,151,,,,14,18,, - Totals,,143,4986,408,13,6,10,107,33,1,66 + Totals,,143,5125,408,13,6,10,107,33,1,66 From 4c6f4ef14b865debd18b163d05f7d7c881b71693 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Oct 2021 10:20:32 +0100 Subject: [PATCH 154/361] Revert "C++: change note" and "C++: Exclusion rules for system macros" This reverts commit a055c86c4f9618fc6a368696a1f3562e18c18db7. This reverts commit 237a7d34b8c45965d5c8c819b88be3bfdd1e3177. --- cpp/change-notes/2021-09-21-jpl24.md | 3 -- .../semmle/code/cpp/commons/Exclusions.qll | 44 ++----------------- .../LOC-4/Rule 24/MultipleStmtsPerLine.ql | 6 +-- .../LOC-4/Rule 24/MultipleVarDeclsPerLine.ql | 6 +-- 4 files changed, 6 insertions(+), 53 deletions(-) delete mode 100644 cpp/change-notes/2021-09-21-jpl24.md diff --git a/cpp/change-notes/2021-09-21-jpl24.md b/cpp/change-notes/2021-09-21-jpl24.md deleted file mode 100644 index 51af4db8b31..00000000000 --- a/cpp/change-notes/2021-09-21-jpl24.md +++ /dev/null @@ -1,3 +0,0 @@ -lgtm,codescanning -* The opt-in queries for JPL C coding standards Rule 24 now exclude macros from - system headers. diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Exclusions.qll b/cpp/ql/lib/semmle/code/cpp/commons/Exclusions.qll index 6ace4aa49e6..a0dfea20046 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Exclusions.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Exclusions.qll @@ -81,8 +81,8 @@ predicate functionContainsPreprocCode(Function f) { } /** - * Holds if `e` is completely or partially from a macro invocation `mi`, as - * opposed to being passed in as an argument. + * Holds if `e` is completely or partially from a macro definition, as opposed + * to being passed in as an argument. * * In the following example, the call to `f` is from a macro definition, * while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart @@ -93,8 +93,8 @@ predicate functionContainsPreprocCode(Function f) { * M(y + 1); * ``` */ -private predicate isFromMacroInvocation(Element e, MacroInvocation mi) { - exists(Location eLocation, Location miLocation | +predicate isFromMacroDefinition(Element e) { + exists(MacroInvocation mi, Location eLocation, Location miLocation | mi.getAnExpandedElement() = e and eLocation = e.getLocation() and miLocation = mi.getLocation() and @@ -109,39 +109,3 @@ private predicate isFromMacroInvocation(Element e, MacroInvocation mi) { eLocation.getEndColumn() >= miLocation.getEndColumn() ) } - -/** - * Holds if `e` is completely or partially from a macro definition, as opposed - * to being passed in as an argument. - * - * In the following example, the call to `f` is from a macro definition, - * while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart - * from `M` refers to a macro. - * ``` - * #define M(x) f(x) - * ... - * M(y + 1); - * ``` - */ -predicate isFromMacroDefinition(Element e) { - isFromMacroInvocation(e, _) -} - -/** - * Holds if `e` is completely or partially from a _system macro_ definition, as - * opposed to being passed in as an argument. A system macro is a macro whose - * definition is outside the source directory of the database. - * - * If the system macro is invoked through a non-system macro, then this - * predicate does not hold. That's a limitation of how macros are represented - * in the database. - * - * See also `isFromMacroDefinition`. - */ -predicate isFromSystemMacroDefinition(Element e) { - exists(MacroInvocation mi | - isFromMacroInvocation(e, mi) and - // Has no relative path in the database, meaning it's a system file. - not exists(mi.getMacro().getFile().getRelativePath()) - ) -} diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql index c99c3de470e..5eccd2c5cad 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql @@ -10,7 +10,6 @@ */ import cpp -import semmle.code.cpp.commons.Exclusions class OneLineStmt extends Stmt { OneLineStmt() { @@ -35,8 +34,5 @@ where other.onLine(f, line) and toMin = other.getLocation().getStartColumn() | toMin - ) and - // Exclude statements that are from invocations of system-header macros. - // Example: FD_ISSET from glibc. - not isFromSystemMacroDefinition(o) + ) select o, "This line contains " + cnt + " statements; only one is allowed." diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql index 41413353346..fcdb2471b76 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql @@ -10,15 +10,11 @@ */ import cpp -import semmle.code.cpp.commons.Exclusions from DeclStmt d where exists(Variable v1, Variable v2 | v1 = d.getADeclaration() and v2 = d.getADeclaration() | v1 != v2 and v1.getLocation().getStartLine() = v2.getLocation().getStartLine() - ) and - // Exclude declarations that are from invocations of system-header macros. - // Example: FD_ZERO from glibc. - not isFromSystemMacroDefinition(d) + ) select d, "Multiple variable declarations on the same line." From 0621e6582758ba5bd4c61a5052b49e5d99fc74a6 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Sun, 29 Aug 2021 18:52:33 +0000 Subject: [PATCH 155/361] Query to detect exposure of sensitive information from android file intent --- .../CWE/CWE-200/AndroidFileIntentSink.qll | 64 ++ .../CWE/CWE-200/AndroidFileIntentSource.qll | 118 ++++ .../CWE/CWE-200/LoadFileFromAppActivity.java | 31 + .../CWE-200/SensitiveAndroidFileLeak.qhelp | 38 ++ .../CWE/CWE-200/SensitiveAndroidFileLeak.ql | 78 +++ .../security/CWE-200/FileService.java | 64 ++ .../security/CWE-200/GetFileActivity.java | 20 + .../security/CWE-200/LeakFileActivity.java | 26 + .../security/CWE-200/LeakFileActivity2.java | 19 + .../security/CWE-200/SafeFileActivity.java | 28 + .../CWE-200/SensitiveAndroidFileLeak.expected | 34 ++ .../CWE-200/SensitiveAndroidFileLeak.qlref | 1 + .../query-tests/security/CWE-200/options | 1 + .../android/app/Activity.java | 46 +- .../android/app/Service.java | 344 +++++++++++ .../android/content/ComponentName.java | 29 + .../android/content/Context.java | 89 ++- .../android/content/ContextWrapper.java | 186 ++++++ .../android/content/Intent.java | 553 ++++++++++++++++++ .../android/os/AsyncTask.java | 406 +++++++++++++ 20 files changed, 2173 insertions(+), 2 deletions(-) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll create mode 100644 java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll create mode 100644 java/ql/src/experimental/Security/CWE/CWE-200/LoadFileFromAppActivity.java create mode 100644 java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.qhelp create mode 100644 java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql create mode 100644 java/ql/test/experimental/query-tests/security/CWE-200/FileService.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-200/GetFileActivity.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-200/LeakFileActivity.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-200/LeakFileActivity2.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-200/SafeFileActivity.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-200/options create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/app/Service.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/AsyncTask.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll new file mode 100644 index 00000000000..95b11e34849 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll @@ -0,0 +1,64 @@ +/** Provides Android sink models related to file creation. */ + +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.ExternalFlow +import semmle.code.java.frameworks.android.Android +import semmle.code.java.frameworks.android.Intent + +/** A sink representing methods creating a file in Android. */ +class AndroidFileSink extends DataFlow::Node { + AndroidFileSink() { sinkNode(this, "create-file") } +} + +/** + * The Android class `android.os.AsyncTask` for running tasks off the UI thread to achieve + * better user experience. + */ +class AsyncTask extends RefType { + AsyncTask() { this.hasQualifiedName("android.os", "AsyncTask") } +} + +/** The `execute` method of Android `AsyncTask`. */ +class AsyncTaskExecuteMethod extends Method { + AsyncTaskExecuteMethod() { + this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and + this.getName() = "execute" + } + + int getParamIndex() { result = 0 } +} + +/** The `executeOnExecutor` method of Android `AsyncTask`. */ +class AsyncTaskExecuteOnExecutorMethod extends Method { + AsyncTaskExecuteOnExecutorMethod() { + this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and + this.getName() = "executeOnExecutor" + } + + int getParamIndex() { result = 1 } +} + +/** The `doInBackground` method of Android `AsyncTask`. */ +class AsyncTaskRunInBackgroundMethod extends Method { + AsyncTaskRunInBackgroundMethod() { + this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and + this.getName() = "doInBackground" + } +} + +/** The service start method of Android context. */ +class ContextStartServiceMethod extends Method { + ContextStartServiceMethod() { + this.getName() = ["startService", "startForegroundService"] and + this.getDeclaringType().getASupertype*() instanceof TypeContext + } +} + +/** The `onStartCommand` method of Android service. */ +class ServiceOnStartCommandMethod extends Method { + ServiceOnStartCommandMethod() { + this.hasName("onStartCommand") and + this.getDeclaringType() instanceof AndroidService + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll new file mode 100644 index 00000000000..6df48f530a5 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll @@ -0,0 +1,118 @@ +/** Provides summary models relating to file content inputs of Android. */ + +import java +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.frameworks.android.Android + +/** The `startActivityForResult` method of Android `Activity`. */ +class StartActivityForResultMethod extends Method { + StartActivityForResultMethod() { + this.getDeclaringType().getASupertype*() instanceof AndroidActivity and + this.getName() = "startActivityForResult" + } +} + +/** Android class instance of `GET_CONTENT` intent. */ +class GetContentIntent extends ClassInstanceExpr { + GetContentIntent() { + this.getConstructedType().getASupertype*() instanceof TypeIntent and + this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = + "android.intent.action.GET_CONTENT" + or + exists(Field f | + this.getArgument(0) = f.getAnAccess() and + f.hasName("ACTION_GET_CONTENT") and + f.getDeclaringType() instanceof TypeIntent + ) + } +} + +/** Android intent data model in the new CSV format. */ +private class AndroidIntentDataModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;taint", + "android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;taint", + "android.content;Intent;true;createChooser;;;Argument[0];ReturnValue;taint", + "android.content;Intent;true;getData;;;Argument[-1];ReturnValue;taint", + "android.content;Intent;true;getDataString;;;Argument[-1];ReturnValue;taint", + "android.content;Intent;true;getExtras;;;Argument[-1];ReturnValue;taint", + "android.content;Intent;true;getIntent;;;Argument[-1];ReturnValue;taint", + "android.content;Intent;true;get" + + [ + "ParcelableArray", "ParcelableArrayList", "Parcelable", "Serializable", "StringArray", + "StringArrayList", "String" + ] + "Extra;;;Argument[-1..1];ReturnValue;taint", + "android.content;Intent;true;put" + + [ + "", "CharSequenceArrayList", "IntegerArrayList", "ParcelableArrayList", + "StringArrayList" + ] + "Extra;;;Argument[1];Argument[-1];taint", + "android.content;Intent;true;putExtras;;;Argument[1];Argument[-1];taint", + "android.content;Intent;true;setData;;;Argument[0];ReturnValue;taint", + "android.content;Intent;true;setDataAndType;;;Argument[-1];ReturnValue;taint", + "android.content;Intent;true;setFlags;;;Argument[-1];ReturnValue;taint", + "android.content;Intent;true;setType;;;Argument[-1];ReturnValue;taint", + "android.net;Uri;true;getEncodedPath;;;Argument[-1];ReturnValue;taint", + "android.net;Uri;true;getEncodedQuery;;;Argument[-1];ReturnValue;taint", + "android.net;Uri;true;getLastPathSegment;;;Argument[-1];ReturnValue;taint", + "android.net;Uri;true;getPath;;;Argument[-1];ReturnValue;taint", + "android.net;Uri;true;getPathSegments;;;Argument[-1];ReturnValue;taint", + "android.net;Uri;true;getQuery;;;Argument[-1];ReturnValue;taint", + "android.net;Uri;true;getQueryParameter;;;Argument[-1];ReturnValue;taint", + "android.net;Uri;true;getQueryParameters;;;Argument[-1];ReturnValue;taint", + "android.os;AsyncTask;true;execute;;;Argument[0];ReturnValue;taint", + "android.os;AsyncTask;true;doInBackground;;;Argument[0];ReturnValue;taint" + ] + } +} + +/** Taint configuration for getting content intent. */ +class GetContentIntentConfig extends TaintTracking::Configuration { + GetContentIntentConfig() { this = "GetContentIntentConfig" } + + override predicate isSource(DataFlow::Node src) { + exists(GetContentIntent gi | src.asExpr() = gi) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma | + ma.getMethod() instanceof StartActivityForResultMethod and sink.asExpr() = ma.getArgument(0) + ) + } +} + +/** Android `Intent` input to request file loading. */ +class AndroidFileIntentInput extends LocalUserInput { + MethodAccess ma; + + AndroidFileIntentInput() { + this.asExpr() = ma.getArgument(0) and + ma.getMethod() instanceof StartActivityForResultMethod and + exists(GetContentIntentConfig cc, GetContentIntent gi | + cc.hasFlow(DataFlow::exprNode(gi), DataFlow::exprNode(ma.getArgument(0))) + ) + } + + /** The request code identifying a specific intent, which is to be matched in `onActivityResult()`. */ + int getRequestCode() { result = ma.getArgument(1).(CompileTimeConstantExpr).getIntValue() } +} + +/** The `onActivityForResult` method of Android `Activity` */ +class OnActivityForResultMethod extends Method { + OnActivityForResultMethod() { + this.getDeclaringType().getASupertype*() instanceof AndroidActivity and + this.getName() = "onActivityResult" + } +} + +/** Input of Android activity result from the same application or another application. */ +class AndroidActivityResultInput extends DataFlow::Node { + OnActivityForResultMethod m; + + AndroidActivityResultInput() { this.asExpr() = m.getParameter(2).getAnAccess() } + + /** The request code matching a specific intent request. */ + VarAccess getRequestCodeVar() { result = m.getParameter(0).getAnAccess() } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/LoadFileFromAppActivity.java b/java/ql/src/experimental/Security/CWE/CWE-200/LoadFileFromAppActivity.java new file mode 100644 index 00000000000..8c4d2a2f0da --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-200/LoadFileFromAppActivity.java @@ -0,0 +1,31 @@ +public class LoadFileFromAppActivity extends Activity { + public static final int REQUEST_CODE__SELECT_CONTENT_FROM_APPS = 99; + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == LoadFileFromAppActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS && + resultCode == RESULT_OK) { + + { + // BAD: Load file without validation + loadOfContentFromApps(data, resultCode); + } + + { + // GOOD: load file with validation + if (!data.getData().getPath().startsWith("/data/data")) { + loadOfContentFromApps(data, resultCode); + } + } + } + } + + private void loadOfContentFromApps(Intent contentIntent, int resultCode) { + Uri streamsToUpload = contentIntent.getData(); + try { + RandomAccessFile file = new RandomAccessFile(streamsToUpload.getPath(), "r"); + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.qhelp b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.qhelp new file mode 100644 index 00000000000..7b6e60d7ca0 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.qhelp @@ -0,0 +1,38 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> +<overview> +<p>The Android API allows to start an activity in another mobile application and receive a result back. +When starting an activity to retrieve a file from another application, missing input validation can +lead to leaking of sensitive configuration file or user data because the intent is from the application +itself that is allowed to access its protected data therefore bypassing the access control. +</p> +</overview> + +<recommendation> +<p> +When loading file data from an activity of another application, validate that the file path is not its own +protected directory, which is a subdirectory of the Android application directory <code>/data/data/</code>. +</p> +</recommendation> + +<example> +<p> +The following examples show the bad situation and the good situation respectively. In bad situation, a +file is loaded without path validation. In good situation, a file is loaded with path validation. +</p> +<sample src="LoadFileFromAppActivity.java" /> +</example> + +<references> +<li> +Google: +<a href="https://developer.android.com/training/basics/intents">Android: Interacting with Other Apps</a>. +</li> +<li> +CVE: +<a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-32695">CVE-2021-32695: File Sharing Flow Initiated by a Victim Leaks Sensitive Data to a Malicious App</a>. +</li> +</references> +</qhelp> \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql new file mode 100644 index 00000000000..c4bdde170ba --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql @@ -0,0 +1,78 @@ +/** + * @name Leaking sensitive Android file + * @description Getting file intent from user input without path validation could leak arbitrary + * Android configuration file and sensitive user data. + * @kind path-problem + * @id java/sensitive_android_file_leak + * @tags security + * external/cwe/cwe-200 + */ + +import java +import AndroidFileIntentSink +import AndroidFileIntentSource +import DataFlow2::PathGraph +import semmle.code.java.dataflow.TaintTracking2 + +class AndroidFileLeakConfig extends TaintTracking2::Configuration { + AndroidFileLeakConfig() { this = "AndroidFileLeakConfig" } + + /** Holds if it is an access to file intent result. */ + override predicate isSource(DataFlow2::Node src) { + exists( + AndroidActivityResultInput ai, AndroidFileIntentInput fi, IfStmt ifs, VarAccess intentVar // if (requestCode == REQUEST_CODE__SELECT_CONTENT_FROM_APPS) + | + ifs.getCondition().getAChildExpr().getAChildExpr().(CompileTimeConstantExpr).getIntValue() = + fi.getRequestCode() and + ifs.getCondition().getAChildExpr().getAChildExpr() = ai.getRequestCodeVar() and + intentVar.getType() instanceof TypeIntent and + intentVar.(Argument).getAnEnclosingStmt() = ifs.getThen() and + src.asExpr() = intentVar + ) + } + + /** Holds if it is a sink of file access in Android. */ + override predicate isSink(DataFlow2::Node sink) { sink instanceof AndroidFileSink } + + override predicate isAdditionalTaintStep(DataFlow2::Node prev, DataFlow2::Node succ) { + exists(MethodAccess aema, AsyncTaskRunInBackgroundMethod arm | + // fileAsyncTask.execute(params) will invoke doInBackground(params) of FileAsyncTask + aema.getQualifier().getType() = arm.getDeclaringType() and + ( + aema.getMethod() instanceof AsyncTaskExecuteMethod and + prev.asExpr() = aema.getArgument(0) + or + aema.getMethod() instanceof AsyncTaskExecuteOnExecutorMethod and + prev.asExpr() = aema.getArgument(1) + ) and + succ.asExpr() = arm.getParameter(0).getAnAccess() + ) + or + exists(MethodAccess csma, ServiceOnStartCommandMethod ssm, ClassInstanceExpr ce | + csma.getMethod() instanceof ContextStartServiceMethod and + ce.getConstructedType() instanceof TypeIntent and // Intent intent = new Intent(context, FileUploader.class); + ce.getArgument(1).getType().(ParameterizedType).getTypeArgument(0) = ssm.getDeclaringType() and + DataFlow2::localExprFlow(ce, csma.getArgument(0)) and // context.startService(intent); + prev.asExpr() = csma.getArgument(0) and + succ.asExpr() = ssm.getParameter(0).getAnAccess() // public int onStartCommand(Intent intent, int flags, int startId) {...} in FileUploader + ) + } + + override predicate isSanitizer(DataFlow2::Node node) { + exists( + MethodAccess startsWith // "startsWith" path check + | + startsWith.getMethod().hasName("startsWith") and + ( + DataFlow2::localExprFlow(node.asExpr(), startsWith.getQualifier()) or + DataFlow2::localExprFlow(node.asExpr(), + startsWith.getQualifier().(MethodAccess).getQualifier()) + ) + ) + } +} + +from DataFlow2::PathNode source, DataFlow2::PathNode sink, AndroidFileLeakConfig conf +where conf.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Leaking arbitrary Android file from $@.", source.getNode(), + "this user input" diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/FileService.java b/java/ql/test/experimental/query-tests/security/CWE-200/FileService.java new file mode 100644 index 00000000000..1e2895001e4 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-200/FileService.java @@ -0,0 +1,64 @@ +import java.io.FileOutputStream; + +import android.app.Service; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.AsyncTask; + +public class FileService extends Service { + public static String KEY_LOCAL_FILE = "local_file"; + /** + * Service initialization + */ + @Override + public void onCreate() { + super.onCreate(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + String localPath = intent.getStringExtra(KEY_LOCAL_FILE); + CopyAndUploadContentUrisTask copyTask = new CopyAndUploadContentUrisTask(); + + copyTask.execute( + copyTask.makeParamsToExecute(localPath) + ); + return 2; + } + + public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, String> { + public Object[] makeParamsToExecute( + String sourceUri + ) { + return new Object[] { + sourceUri + }; + } + + @Override + protected String doInBackground(Object[] params) { + FileOutputStream outputStream = null; + + try { + String[] uris = (String[]) params[1]; + outputStream = new FileOutputStream(uris[0]); + return "success"; + } catch (Exception e) { + } + return "failure"; + } + + @Override + protected void onPostExecute(String result) { + } + + @Override + protected void onPreExecute() { + } + + @Override + protected void onProgressUpdate(Void... values) { + } + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/GetFileActivity.java b/java/ql/test/experimental/query-tests/security/CWE-200/GetFileActivity.java new file mode 100644 index 00000000000..762ac1f43db --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-200/GetFileActivity.java @@ -0,0 +1,20 @@ +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class GetFileActivity extends Activity { + public static final int REQUEST_CODE__SELECT_CONTENT_FROM_APPS = 99; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(-1); + + Intent action = new Intent(Intent.ACTION_GET_CONTENT); + action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); + action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + + startActivityForResult( + Intent.createChooser(action, "Open File From Selected Application"), REQUEST_CODE__SELECT_CONTENT_FROM_APPS + ); + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/LeakFileActivity.java b/java/ql/test/experimental/query-tests/security/CWE-200/LeakFileActivity.java new file mode 100644 index 00000000000..3520ed0fd40 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-200/LeakFileActivity.java @@ -0,0 +1,26 @@ +import java.io.RandomAccessFile; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +public class LeakFileActivity extends Activity { + @Override + // BAD: Load file from activity without validation + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == GetFileActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS && + resultCode == RESULT_OK) { + loadOfContentFromApps(data, resultCode); + } + } + + private void loadOfContentFromApps(Intent contentIntent, int resultCode) { + Uri streamsToUpload = contentIntent.getData(); + try { + RandomAccessFile file = new RandomAccessFile(streamsToUpload.getPath(), "r"); + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/LeakFileActivity2.java b/java/ql/test/experimental/query-tests/security/CWE-200/LeakFileActivity2.java new file mode 100644 index 00000000000..56e695ec97a --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-200/LeakFileActivity2.java @@ -0,0 +1,19 @@ +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +public class LeakFileActivity2 extends Activity { + @Override + // BAD: Load file in a service without validation + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Uri localPath = data.getData(); + + if (requestCode == GetFileActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS && + resultCode == RESULT_OK) { + Intent intent = new Intent(this, FileService.class); + intent.putExtra(FileService.KEY_LOCAL_FILE, localPath); + startService(intent); + } + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SafeFileActivity.java b/java/ql/test/experimental/query-tests/security/CWE-200/SafeFileActivity.java new file mode 100644 index 00000000000..a919888a658 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SafeFileActivity.java @@ -0,0 +1,28 @@ +import java.io.RandomAccessFile; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +public class SafeFileActivity extends Activity { + @Override + // GOOD: Load file from activity with path validation + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == GetFileActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS && + resultCode == RESULT_OK) { + safeLoadOfContentFromApps(data, resultCode); + } + } + + private void safeLoadOfContentFromApps(Intent contentIntent, int resultCode) { + Uri streamsToUpload = contentIntent.getData(); + try { + if (!streamsToUpload.getPath().startsWith("/data/data")) { + RandomAccessFile file = new RandomAccessFile(streamsToUpload.getPath(), "r"); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected new file mode 100644 index 00000000000..db29fd64568 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -0,0 +1,34 @@ +edges +| FileService.java:21:28:21:33 | intent : Intent | FileService.java:21:28:21:64 | getStringExtra(...) : String | +| FileService.java:21:28:21:33 | intent : Intent | FileService.java:25:42:25:50 | localPath : String | +| FileService.java:21:28:21:64 | getStringExtra(...) : String | FileService.java:25:42:25:50 | localPath : String | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:44:44:44:49 | params : Object[] | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | +| FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | +| FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | +| FileService.java:44:44:44:49 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | +| LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:21:28:21:33 | intent : Intent | +| LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | +| LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | +| LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | +| LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | +| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | LeakFileActivity.java:21:58:21:82 | getPath(...) | +nodes +| FileService.java:21:28:21:33 | intent : Intent | semmle.label | intent : Intent | +| FileService.java:21:28:21:64 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | semmle.label | makeParamsToExecute(...) [[]] : String | +| FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String | +| FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | +| FileService.java:44:44:44:49 | params : Object[] | semmle.label | params : Object[] | +| FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] | +| LeakFileActivity2.java:16:26:16:31 | intent : Intent | semmle.label | intent : Intent | +| LeakFileActivity.java:14:35:14:38 | data : Intent | semmle.label | data : Intent | +| LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | semmle.label | contentIntent : Intent | +| LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | semmle.label | contentIntent : Intent | +| LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | semmle.label | getData(...) : Uri | +| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | semmle.label | streamsToUpload : Uri | +| LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) | +#select +| FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:16:26:16:31 | intent | this user input | +| LeakFileActivity.java:21:58:21:82 | getPath(...) | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:21:58:21:82 | getPath(...) | Leaking arbitrary Android file from $@. | LeakFileActivity.java:14:35:14:38 | data | this user input | diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.qlref b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.qlref new file mode 100644 index 00000000000..2959fb2e85c --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/options b/java/ql/test/experimental/query-tests/security/CWE-200/options new file mode 100644 index 00000000000..43e25f608b6 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-200/options @@ -0,0 +1 @@ +// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java b/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java index e04f68a203d..99b797fb2a8 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java @@ -15,6 +15,8 @@ */ package android.app; +import android.content.Context; +import android.content.ContextWrapper; import android.content.Intent; import android.os.Bundle; import android.view.View; @@ -675,7 +677,16 @@ import android.view.View; * upload, independent of whether the original activity is paused, stopped, or * finished. */ -public class Activity { +public class Activity extends ContextWrapper { + /** Standard activity result: operation canceled. */ + public static final int RESULT_CANCELED = 0; + + /** Standard activity result: operation succeeded. */ + public static final int RESULT_OK = -1; + + /** Start of user-defined activity results. */ + public static final int RESULT_FIRST_USER = 1; + /** Return the intent that started this activity. */ public Intent getIntent() { return null; @@ -1142,4 +1153,37 @@ public class Activity { */ public void startActivities(Intent[] intents, Bundle options) { } + + /** + * Called when an activity you launched exits, giving you the requestCode + * you started it with, the resultCode it returned, and any additional + * data from it. The <var>resultCode</var> will be + * {@link #RESULT_CANCELED} if the activity explicitly returned that, + * didn't return any result, or crashed during its operation. + * + * <p>An activity can never receive a result in the resumed state. You can count on + * {@link #onResume} being called after this method, though not necessarily immediately after. + * If the activity was resumed, it will be paused and the result will be delivered, followed + * by {@link #onResume}. If the activity wasn't in the resumed state, then the result will + * be delivered, with {@link #onResume} called sometime later when the activity becomes active + * again. + * + * <p>This method is never invoked if your activity sets + * {@link android.R.styleable#AndroidManifestActivity_noHistory noHistory} to + * <code>true</code>. + * + * @param requestCode The integer request code originally supplied to + * startActivityForResult(), allowing you to identify who this + * result came from. + * @param resultCode The integer result code returned by the child activity + * through its setResult(). + * @param data An Intent, which can return result data to the caller + * (various data can be attached to Intent "extras"). + * + * @see #startActivityForResult + * @see #createPendingResult + * @see #setResult(int) + */ + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + } } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/app/Service.java b/java/ql/test/stubs/google-android-9.0.0/android/app/Service.java new file mode 100644 index 00000000000..370d7c5e4fe --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/app/Service.java @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app; + +import android.content.Intent; +import android.content.ContextWrapper; + +/** + * A Service is an application component representing either an application's desire + * to perform a longer-running operation while not interacting with the user + * or to supply functionality for other applications to use. Each service + * class must have a corresponding + * {@link android.R.styleable#AndroidManifestService <service>} + * declaration in its package's <code>AndroidManifest.xml</code>. Services + * can be started with + * {@link android.content.Context#startService Context.startService()} and + * {@link android.content.Context#bindService Context.bindService()}. + * + * <p>Note that services, like other application objects, run in the main + * thread of their hosting process. This means that, if your service is going + * to do any CPU intensive (such as MP3 playback) or blocking (such as + * networking) operations, it should spawn its own thread in which to do that + * work. More information on this can be found in + * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and + * Threads</a>. The {@link IntentService} class is available + * as a standard implementation of Service that has its own thread where it + * schedules its work to be done.</p> + * + * <p>Topics covered here: + * <ol> + * <li><a href="#WhatIsAService">What is a Service?</a> + * <li><a href="#ServiceLifecycle">Service Lifecycle</a> + * <li><a href="#Permissions">Permissions</a> + * <li><a href="#ProcessLifecycle">Process Lifecycle</a> + * <li><a href="#LocalServiceSample">Local Service Sample</a> + * <li><a href="#RemoteMessengerServiceSample">Remote Messenger Service Sample</a> + * </ol> + * + * <div class="special reference"> + * <h3>Developer Guides</h3> + * <p>For a detailed discussion about how to create services, read the + * <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> developer guide.</p> + * </div> + * + * <a name="WhatIsAService"></a> + * <h3>What is a Service?</h3> + * + * <p>Most confusion about the Service class actually revolves around what + * it is <em>not</em>:</p> + * + * <ul> + * <li> A Service is <b>not</b> a separate process. The Service object itself + * does not imply it is running in its own process; unless otherwise specified, + * it runs in the same process as the application it is part of. + * <li> A Service is <b>not</b> a thread. It is not a means itself to do work off + * of the main thread (to avoid Application Not Responding errors). + * </ul> + * + * <p>Thus a Service itself is actually very simple, providing two main features:</p> + * + * <ul> + * <li>A facility for the application to tell the system <em>about</em> + * something it wants to be doing in the background (even when the user is not + * directly interacting with the application). This corresponds to calls to + * {@link android.content.Context#startService Context.startService()}, which + * ask the system to schedule work for the service, to be run until the service + * or someone else explicitly stop it. + * <li>A facility for an application to expose some of its functionality to + * other applications. This corresponds to calls to + * {@link android.content.Context#bindService Context.bindService()}, which + * allows a long-standing connection to be made to the service in order to + * interact with it. + * </ul> + * + * <p>When a Service component is actually created, for either of these reasons, + * all that the system actually does is instantiate the component + * and call its {@link #onCreate} and any other appropriate callbacks on the + * main thread. It is up to the Service to implement these with the appropriate + * behavior, such as creating a secondary thread in which it does its work.</p> + * + * <p>Note that because Service itself is so simple, you can make your + * interaction with it as simple or complicated as you want: from treating it + * as a local Java object that you make direct method calls on (as illustrated + * by <a href="#LocalServiceSample">Local Service Sample</a>), to providing + * a full remoteable interface using AIDL.</p> + * + * <a name="ServiceLifecycle"></a> + * <h3>Service Lifecycle</h3> + * + * <p>There are two reasons that a service can be run by the system. If someone + * calls {@link android.content.Context#startService Context.startService()} then the system will + * retrieve the service (creating it and calling its {@link #onCreate} method + * if needed) and then call its {@link #onStartCommand} method with the + * arguments supplied by the client. The service will at this point continue + * running until {@link android.content.Context#stopService Context.stopService()} or + * {@link #stopSelf()} is called. Note that multiple calls to + * Context.startService() do not nest (though they do result in multiple corresponding + * calls to onStartCommand()), so no matter how many times it is started a service + * will be stopped once Context.stopService() or stopSelf() is called; however, + * services can use their {@link #stopSelf(int)} method to ensure the service is + * not stopped until started intents have been processed. + * + * <p>For started services, there are two additional major modes of operation + * they can decide to run in, depending on the value they return from + * onStartCommand(): {@link #START_STICKY} is used for services that are + * explicitly started and stopped as needed, while {@link #START_NOT_STICKY} + * or {@link #START_REDELIVER_INTENT} are used for services that should only + * remain running while processing any commands sent to them. See the linked + * documentation for more detail on the semantics. + * + * <p>Clients can also use {@link android.content.Context#bindService Context.bindService()} to + * obtain a persistent connection to a service. This likewise creates the + * service if it is not already running (calling {@link #onCreate} while + * doing so), but does not call onStartCommand(). The client will receive the + * {@link android.os.IBinder} object that the service returns from its + * {@link #onBind} method, allowing the client to then make calls back + * to the service. The service will remain running as long as the connection + * is established (whether or not the client retains a reference on the + * service's IBinder). Usually the IBinder returned is for a complex + * interface that has been <a href="{@docRoot}guide/components/aidl.html">written + * in aidl</a>. + * + * <p>A service can be both started and have connections bound to it. In such + * a case, the system will keep the service running as long as either it is + * started <em>or</em> there are one or more connections to it with the + * {@link android.content.Context#BIND_AUTO_CREATE Context.BIND_AUTO_CREATE} + * flag. Once neither + * of these situations hold, the service's {@link #onDestroy} method is called + * and the service is effectively terminated. All cleanup (stopping threads, + * unregistering receivers) should be complete upon returning from onDestroy(). + * + * <a name="Permissions"></a> + * <h3>Permissions</h3> + * + * <p>Global access to a service can be enforced when it is declared in its + * manifest's {@link android.R.styleable#AndroidManifestService <service>} + * tag. By doing so, other applications will need to declare a corresponding + * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} + * element in their own manifest to be able to start, stop, or bind to + * the service. + * + * <p>As of {@link android.os.Build.VERSION_CODES#GINGERBREAD}, when using + * {@link Context#startService(Intent) Context.startService(Intent)}, you can + * also set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION + * Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION + * Intent.FLAG_GRANT_WRITE_URI_PERMISSION} on the Intent. This will grant the + * Service temporary access to the specific URIs in the Intent. Access will + * remain until the Service has called {@link #stopSelf(int)} for that start + * command or a later one, or until the Service has been completely stopped. + * This works for granting access to the other apps that have not requested + * the permission protecting the Service, or even when the Service is not + * exported at all. + * + * <p>In addition, a service can protect individual IPC calls into it with + * permissions, by calling the + * {@link #checkCallingPermission} + * method before executing the implementation of that call. + * + * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> + * document for more information on permissions and security in general. + * + * <a name="ProcessLifecycle"></a> + * <h3>Process Lifecycle</h3> + * + * <p>The Android system will attempt to keep the process hosting a service + * around as long as the service has been started or has clients bound to it. + * When running low on memory and needing to kill existing processes, the + * priority of a process hosting the service will be the higher of the + * following possibilities: + * + * <ul> + * <li><p>If the service is currently executing code in its + * {@link #onCreate onCreate()}, {@link #onStartCommand onStartCommand()}, + * or {@link #onDestroy onDestroy()} methods, then the hosting process will + * be a foreground process to ensure this code can execute without + * being killed. + * <li><p>If the service has been started, then its hosting process is considered + * to be less important than any processes that are currently visible to the + * user on-screen, but more important than any process not visible. Because + * only a few processes are generally visible to the user, this means that + * the service should not be killed except in low memory conditions. However, since + * the user is not directly aware of a background service, in that state it <em>is</em> + * considered a valid candidate to kill, and you should be prepared for this to + * happen. In particular, long-running services will be increasingly likely to + * kill and are guaranteed to be killed (and restarted if appropriate) if they + * remain started long enough. + * <li><p>If there are clients bound to the service, then the service's hosting + * process is never less important than the most important client. That is, + * if one of its clients is visible to the user, then the service itself is + * considered to be visible. The way a client's importance impacts the service's + * importance can be adjusted through {@link Context#BIND_ABOVE_CLIENT}, + * {@link Context#BIND_ALLOW_OOM_MANAGEMENT}, {@link Context#BIND_WAIVE_PRIORITY}, + * {@link Context#BIND_IMPORTANT}, and {@link Context#BIND_ADJUST_WITH_ACTIVITY}. + * <li><p>A started service can use the {@link #startForeground(int, Notification)} + * API to put the service in a foreground state, where the system considers + * it to be something the user is actively aware of and thus not a candidate + * for killing when low on memory. (It is still theoretically possible for + * the service to be killed under extreme memory pressure from the current + * foreground application, but in practice this should not be a concern.) + * </ul> + * + * <p>Note this means that most of the time your service is running, it may + * be killed by the system if it is under heavy memory pressure. If this + * happens, the system will later try to restart the service. An important + * consequence of this is that if you implement {@link #onStartCommand onStartCommand()} + * to schedule work to be done asynchronously or in another thread, then you + * may want to use {@link #START_FLAG_REDELIVERY} to have the system + * re-deliver an Intent for you so that it does not get lost if your service + * is killed while processing it. + * + * <p>Other application components running in the same process as the service + * (such as an {@link android.app.Activity}) can, of course, increase the + * importance of the overall + * process beyond just the importance of the service itself. + * + * <a name="LocalServiceSample"></a> + * <h3>Local Service Sample</h3> + * + * <p>One of the most common uses of a Service is as a secondary component + * running alongside other parts of an application, in the same process as + * the rest of the components. All components of an .apk run in the same + * process unless explicitly stated otherwise, so this is a typical situation. + * + * <p>When used in this way, by assuming the + * components are in the same process, you can greatly simplify the interaction + * between them: clients of the service can simply cast the IBinder they + * receive from it to a concrete class published by the service. + * + * <p>An example of this use of a Service is shown here. First is the Service + * itself, publishing a custom class when bound: + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java + * service} + * + * <p>With that done, one can now write client code that directly accesses the + * running service, such as: + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.java + * bind} + * + * <a name="RemoteMessengerServiceSample"></a> + * <h3>Remote Messenger Service Sample</h3> + * + * <p>If you need to be able to write a Service that can perform complicated + * communication with clients in remote processes (beyond simply the use of + * {@link Context#startService(Intent) Context.startService} to send + * commands to it), then you can use the {@link android.os.Messenger} class + * instead of writing full AIDL files. + * + * <p>An example of a Service that uses Messenger as its client interface + * is shown here. First is the Service itself, publishing a Messenger to + * an internal Handler when bound: + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.java + * service} + * + * <p>If we want to make this service run in a remote process (instead of the + * standard one for its .apk), we can use <code>android:process</code> in its + * manifest tag to specify one: + * + * {@sample development/samples/ApiDemos/AndroidManifest.xml remote_service_declaration} + * + * <p>Note that the name "remote" chosen here is arbitrary, and you can use + * other names if you want additional processes. The ':' prefix appends the + * name to your package's standard process name. + * + * <p>With that done, clients can now bind to the service and send messages + * to it. Note that this allows clients to register with it to receive + * messages back as well: + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.java + * bind} + */ +public abstract class Service extends ContextWrapper { + /** + * Called by the system when the service is first created. Do not call this method directly. + */ + public void onCreate() { + } + + /** + * @deprecated Implement {@link #onStartCommand(Intent, int, int)} instead. + */ + @Deprecated + public void onStart(Intent intent, int startId) { + } + + /** + * Called by the system every time a client explicitly starts the service by calling + * {@link android.content.Context#startService}, providing the arguments it supplied and a + * unique integer token representing the start request. Do not call this method directly. + * + * <p>For backwards compatibility, the default implementation calls + * {@link #onStart} and returns either {@link #START_STICKY} + * or {@link #START_STICKY_COMPATIBILITY}. + * + * <p class="caution">Note that the system calls this on your + * service's main thread. A service's main thread is the same + * thread where UI operations take place for Activities running in the + * same process. You should always avoid stalling the main + * thread's event loop. When doing long-running operations, + * network calls, or heavy disk I/O, you should kick off a new + * thread, or use {@link android.os.AsyncTask}.</p> + * + * @param intent The Intent supplied to {@link android.content.Context#startService}, + * as given. This may be null if the service is being restarted after + * its process has gone away, and it had previously returned anything + * except {@link #START_STICKY_COMPATIBILITY}. + * @param flags Additional data about this start request. + * @param startId A unique integer representing this specific request to + * start. Use with {@link #stopSelfResult(int)}. + * + * @return The return value indicates what semantics the system should + * use for the service's current started state. It may be one of the + * constants associated with the {@link #START_CONTINUATION_MASK} bits. + * + * @see #stopSelfResult(int) + */ + public int onStartCommand(Intent intent, int flags, int startId) { + return -1; + } + + /** + * Called by the system to notify a Service that it is no longer used and is being removed. The + * service should clean up any resources it holds (threads, registered + * receivers, etc) at this point. Upon return, there will be no more calls + * in to this Service object and it is effectively dead. Do not call this method directly. + */ + public void onDestroy() { + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java new file mode 100644 index 00000000000..adb50343ca4 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.content; + +/** + * Identifier for a specific application component + * ({@link android.app.Activity}, {@link android.app.Service}, + * {@link android.content.BroadcastReceiver}, or + * {@link android.content.ContentProvider}) that is available. Two + * pieces of information, encapsulated here, are required to identify + * a component: the package (a String) it exists in, and the class (a String) + * name inside of that package. + * + */ +public final class ComponentName { +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java b/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java index 6507cbd371d..8ddd1f2c8ef 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java @@ -961,4 +961,91 @@ public abstract class Context { * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) */ public abstract void sendOrderedBroadcast(Intent intent, String receiverPermission); -} \ No newline at end of file + + /** + * Request that a given application service be started. The Intent + * should either contain the complete class name of a specific service + * implementation to start, or a specific package name to target. If the + * Intent is less specified, it logs a warning about this. In this case any of the + * multiple matching services may be used. If this service + * is not already running, it will be instantiated and started (creating a + * process for it if needed); if it is running then it remains running. + * + * <p>Every call to this method will result in a corresponding call to + * the target service's {@link android.app.Service#onStartCommand} method, + * with the <var>intent</var> given here. This provides a convenient way + * to submit jobs to a service without having to bind and call on to its + * interface. + * + * <p>Using startService() overrides the default service lifetime that is + * managed by {@link #bindService}: it requires the service to remain + * running until {@link #stopService} is called, regardless of whether + * any clients are connected to it. Note that calls to startService() + * do not nest: no matter how many times you call startService(), + * a single call to {@link #stopService} will stop it. + * + * <p>The system attempts to keep running services around as much as + * possible. The only time they should be stopped is if the current + * foreground application is using so many resources that the service needs + * to be killed. If any errors happen in the service's process, it will + * automatically be restarted. + * + * <p>This function will throw {@link SecurityException} if you do not + * have permission to start the given service. + * + * <p class="note"><strong>Note:</strong> Each call to startService() + * results in significant work done by the system to manage service + * lifecycle surrounding the processing of the intent, which can take + * multiple milliseconds of CPU time. Due to this cost, startService() + * should not be used for frequent intent delivery to a service, and only + * for scheduling significant work. Use {@link #bindService bound services} + * for high frequency calls. + * </p> + * + * @param service Identifies the service to be started. The Intent must be + * fully explicit (supplying a component name). Additional values + * may be included in the Intent extras to supply arguments along with + * this specific start call. + * + * @return If the service is being started or is already running, the + * {@link ComponentName} of the actual service that was started is + * returned; else if the service does not exist null is returned. + * + * @throws SecurityException If the caller does not have permission to access the service + * or the service can not be found. + * @throws IllegalStateException If the application is in a state where the service + * can not be started (such as not in the foreground in a state when services are allowed). + * + * @see #stopService + * @see #bindService + */ + public abstract ComponentName startService(Intent service); + + /** + * Similar to {@link #startService(Intent)}, but with an implicit promise that the + * Service will call {@link android.app.Service#startForeground(int, android.app.Notification) + * startForeground(int, android.app.Notification)} once it begins running. The service is given + * an amount of time comparable to the ANR interval to do this, otherwise the system + * will automatically stop the service and declare the app ANR. + * + * <p>Unlike the ordinary {@link #startService(Intent)}, this method can be used + * at any time, regardless of whether the app hosting the service is in a foreground + * state. + * + * @param service Identifies the service to be started. The Intent must be + * fully explicit (supplying a component name). Additional values + * may be included in the Intent extras to supply arguments along with + * this specific start call. + * + * @return If the service is being started or is already running, the + * {@link ComponentName} of the actual service that was started is + * returned; else if the service does not exist null is returned. + * + * @throws SecurityException If the caller does not have permission to access the service + * or the service can not be found. + * + * @see #stopService + * @see android.app.Service#startForeground(int, android.app.Notification) + */ + public abstract ComponentName startForegroundService(Intent service); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java new file mode 100644 index 00000000000..d3e23384cbd --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.content; + +import java.io.File; +import android.os.Bundle; + +/** + * Proxying implementation of Context that simply delegates all of its calls to + * another Context. Can be subclassed to modify behavior without changing + * the original Context. + */ +public class ContextWrapper extends Context { + public ContextWrapper() { + } + + public ContextWrapper(Context base) { + } + + @Override + public Context getApplicationContext() { + return null; + } + + @Override + public File getFileStreamPath(String name) { + return null; + } + + @Override + public SharedPreferences getSharedPreferences(String name, int mode) { + return null; + } + + @Override + public File getSharedPrefsFile(String name) { + return null; + } + + @Override + public String[] fileList() { + return null; + } + + @Override + public File getDataDir() { + return null; + } + + @Override + public File getFilesDir() { + return null; + } + + @Override + public File getNoBackupFilesDir() { + return null; + } + + @Override + public File getExternalFilesDir(String type) { + return null; + } + + @Override + public File[] getExternalFilesDirs(String type) { + return null; + } + + @Override + public File getObbDir() { + return null; + } + + @Override + public File[] getObbDirs() { + return null; + } + + @Override + public File getCacheDir() { + return null; + } + + @Override + public File getCodeCacheDir() { + return null; + } + + @Override + public File getExternalCacheDir() { + return null; + } + + @Override + public File[] getExternalCacheDirs() { + return null; + } + + @Override + public File[] getExternalMediaDirs() { + return null; + } + + @Override + public File getDir(String name, int mode) { + return null; + } + + /** @hide **/ + @Override + public File getPreloadsFileCache() { + return null; + } + + @Override + public void startActivity(Intent intent) { + } + + /** @hide **/ + public void startActivityForResult( + String who, Intent intent, int requestCode, Bundle options) { + } + + /** @hide **/ + public boolean canStartActivityForResult() { + return false; + } + @Override + + public void startActivity(Intent intent, Bundle options) { + } + + @Override + public void startActivities(Intent[] intents) { + } + + @Override + public void startActivities(Intent[] intents, Bundle options) { + } + + @Override + public void sendBroadcast(Intent intent) { + } + + @Override + public void sendBroadcast(Intent intent, String receiverPermission) { + } + + @Override + public void sendBroadcastWithMultiplePermissions(Intent intent, String[] receiverPermissions) { + } + + /** @hide */ + @Override + public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { + } + + @Override + public void sendOrderedBroadcast(Intent intent, + String receiverPermission) { + } + + @Override + public ComponentName startService(Intent service) { + return null; + } + + @Override + public ComponentName startForegroundService(Intent service) { + return null; + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java b/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java index 09422c7a48a..03004b437d2 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java @@ -723,6 +723,511 @@ import java.util.Set; */ public class Intent implements Parcelable, Cloneable { + /** + * Activity Action: Start as a main entry point, does not expect to + * receive data. + * <p>Input: nothing + * <p>Output: nothing + */ + public static final String ACTION_MAIN = "android.intent.action.MAIN"; + + /** + * Activity Action: Display the data to the user. This is the most common + * action performed on data -- it is the generic action you can use on + * a piece of data to get the most reasonable thing to occur. For example, + * when used on a contacts entry it will view the entry; when used on a + * mailto: URI it will bring up a compose window filled with the information + * supplied by the URI; when used with a tel: URI it will invoke the + * dialer. + * <p>Input: {@link #getData} is URI from which to retrieve data. + * <p>Output: nothing. + */ + public static final String ACTION_VIEW = "android.intent.action.VIEW"; + + /** + * A synonym for {@link #ACTION_VIEW}, the "standard" action that is + * performed on a piece of data. + */ + public static final String ACTION_DEFAULT = ACTION_VIEW; + + /** + * Used to indicate that some piece of data should be attached to some other + * place. For example, image data could be attached to a contact. It is up + * to the recipient to decide where the data should be attached; the intent + * does not specify the ultimate destination. + * <p>Input: {@link #getData} is URI of data to be attached. + * <p>Output: nothing. + */ + public static final String ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA"; + + /** + * Activity Action: Provide explicit editable access to the given data. + * <p>Input: {@link #getData} is URI of data to be edited. + * <p>Output: nothing. + */ + public static final String ACTION_EDIT = "android.intent.action.EDIT"; + + /** + * Activity Action: Pick an existing item, or insert a new item, and then edit it. + * <p>Input: {@link #getType} is the desired MIME type of the item to create or edit. + * The extras can contain type specific data to pass through to the editing/creating + * activity. + * <p>Output: The URI of the item that was picked. This must be a content: + * URI so that any receiver can access it. + */ + public static final String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT"; + + /** + * Activity Action: Pick an item from the data, returning what was selected. + * <p>Input: {@link #getData} is URI containing a directory of data + * (vnd.android.cursor.dir/*) from which to pick an item. + * <p>Output: The URI of the item that was picked. + */ + public static final String ACTION_PICK = "android.intent.action.PICK"; + + /** + * Activity Action: Creates a shortcut. + * <p>Input: Nothing.</p> + * <p>Output: An Intent representing the shortcut. The intent must contain three + * extras: SHORTCUT_INTENT (value: Intent), SHORTCUT_NAME (value: String), + * and SHORTCUT_ICON (value: Bitmap) or SHORTCUT_ICON_RESOURCE + * (value: ShortcutIconResource).</p> + * + * @see #EXTRA_SHORTCUT_INTENT + * @see #EXTRA_SHORTCUT_NAME + * @see #EXTRA_SHORTCUT_ICON + * @see #EXTRA_SHORTCUT_ICON_RESOURCE + * @see android.content.Intent.ShortcutIconResource + */ + public static final String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT"; + + /** + * Activity Action: Display an activity chooser, allowing the user to pick + * what they want to before proceeding. This can be used as an alternative + * to the standard activity picker that is displayed by the system when + * you try to start an activity with multiple possible matches, with these + * differences in behavior: + * <ul> + * <li>You can specify the title that will appear in the activity chooser. + * <li>The user does not have the option to make one of the matching + * activities a preferred activity, and all possible activities will + * always be shown even if one of them is currently marked as the + * preferred activity. + * </ul> + * <p> + * This action should be used when the user will naturally expect to + * select an activity in order to proceed. An example if when not to use + * it is when the user clicks on a "mailto:" link. They would naturally + * expect to go directly to their mail app, so startActivity() should be + * called directly: it will + * either launch the current preferred app, or put up a dialog allowing the + * user to pick an app to use and optionally marking that as preferred. + * <p> + * In contrast, if the user is selecting a menu item to send a picture + * they are viewing to someone else, there are many different things they + * may want to do at this point: send it through e-mail, upload it to a + * web service, etc. In this case the CHOOSER action should be used, to + * always present to the user a list of the things they can do, with a + * nice title given by the caller such as "Send this photo with:". + * <p> + * As a convenience, an Intent of this form can be created with the + * {@link #createChooser} function. + * <p>Input: No data should be specified. get*Extra must have + * a {@link #EXTRA_INTENT} field containing the Intent being executed, + * and can optionally have a {@link #EXTRA_TITLE} field containing the + * title text to display in the chooser. + * <p>Output: Depends on the protocol of {@link #EXTRA_INTENT}. + */ + public static final String ACTION_CHOOSER = "android.intent.action.CHOOSER"; + + /** + * Convenience function for creating a {@link #ACTION_CHOOSER} Intent. + * + * @param target The Intent that the user will be selecting an activity + * to perform. + * @param title Optional title that will be displayed in the chooser. + * @return Return a new Intent object that you can hand to + * {@link Context#startActivity(Intent) Context.startActivity()} and + * related methods. + */ + public static Intent createChooser(Intent target, CharSequence title) { + return null; + } + + /** + * Activity Action: Allow the user to select a particular kind of data and + * return it. This is different than {@link #ACTION_PICK} in that here we + * just say what kind of data is desired, not a URI of existing data from + * which the user can pick. A ACTION_GET_CONTENT could allow the user to + * create the data as it runs (for example taking a picture or recording a + * sound), let them browse over the web and download the desired data, + * etc. + * <p> + * There are two main ways to use this action: if you want a specific kind + * of data, such as a person contact, you set the MIME type to the kind of + * data you want and launch it with {@link Context#startActivity(Intent)}. + * The system will then launch the best application to select that kind + * of data for you. + * <p> + * You may also be interested in any of a set of types of content the user + * can pick. For example, an e-mail application that wants to allow the + * user to add an attachment to an e-mail message can use this action to + * bring up a list of all of the types of content the user can attach. + * <p> + * In this case, you should wrap the GET_CONTENT intent with a chooser + * (through {@link #createChooser}), which will give the proper interface + * for the user to pick how to send your data and allow you to specify + * a prompt indicating what they are doing. You will usually specify a + * broad MIME type (such as image/* or {@literal *}/*), resulting in a + * broad range of content types the user can select from. + * <p> + * When using such a broad GET_CONTENT action, it is often desirable to + * only pick from data that can be represented as a stream. This is + * accomplished by requiring the {@link #CATEGORY_OPENABLE} in the Intent. + * <p> + * Callers can optionally specify {@link #EXTRA_LOCAL_ONLY} to request that + * the launched content chooser only returns results representing data that + * is locally available on the device. For example, if this extra is set + * to true then an image picker should not show any pictures that are available + * from a remote server but not already on the local device (thus requiring + * they be downloaded when opened). + * <p> + * Input: {@link #getType} is the desired MIME type to retrieve. Note + * that no URI is supplied in the intent, as there are no constraints on + * where the returned data originally comes from. You may also include the + * {@link #CATEGORY_OPENABLE} if you can only accept data that can be + * opened as a stream. You may use {@link #EXTRA_LOCAL_ONLY} to limit content + * selection to local data. + * <p> + * Output: The URI of the item that was picked. This must be a content: + * URI so that any receiver can access it. + */ + public static final String ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT"; + + /** + * Activity Action: Dial a number as specified by the data. This shows a + * UI with the number being dialed, allowing the user to explicitly + * initiate the call. + * <p>Input: If nothing, an empty dialer is started; else {@link #getData} + * is URI of a phone number to be dialed or a tel: URI of an explicit phone + * number. + * <p>Output: nothing. + */ + public static final String ACTION_DIAL = "android.intent.action.DIAL"; + + /** + * Activity Action: Perform a call to someone specified by the data. + * <p>Input: If nothing, an empty dialer is started; else {@link #getData} + * is URI of a phone number to be dialed or a tel: URI of an explicit phone + * number. + * <p>Output: nothing. + * + * <p>Note: there will be restrictions on which applications can initiate a + * call; most applications should use the {@link #ACTION_DIAL}. + * <p>Note: this Intent <strong>cannot</strong> be used to call emergency + * numbers. Applications can <strong>dial</strong> emergency numbers using + * {@link #ACTION_DIAL}, however. + */ + public static final String ACTION_CALL = "android.intent.action.CALL"; + + /** + * Activity Action: Perform a call to an emergency number specified by the + * data. + * <p>Input: {@link #getData} is URI of a phone number to be dialed or a + * tel: URI of an explicit phone number. + * <p>Output: nothing. + * @hide + */ + public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY"; + + /** + * Activity action: Perform a call to any number (emergency or not) + * specified by the data. + * <p>Input: {@link #getData} is URI of a phone number to be dialed or a + * tel: URI of an explicit phone number. + * <p>Output: nothing. + * @hide + */ + public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED"; + + /** + * Activity Action: Send a message to someone specified by the data. + * <p>Input: {@link #getData} is URI describing the target. + * <p>Output: nothing. + */ + public static final String ACTION_SENDTO = "android.intent.action.SENDTO"; + + /** + * Activity Action: Deliver some data to someone else. Who the data is + * being delivered to is not specified; it is up to the receiver of this + * action to ask the user where the data should be sent. + * <p> + * When launching a SEND intent, you should usually wrap it in a chooser + * (through {@link #createChooser}), which will give the proper interface + * for the user to pick how to send your data and allow you to specify + * a prompt indicating what they are doing. + * <p> + * Input: {@link #getType} is the MIME type of the data being sent. + * get*Extra can have either a {@link #EXTRA_TEXT} + * or {@link #EXTRA_STREAM} field, containing the data to be sent. If + * using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it + * should be the MIME type of the data in EXTRA_STREAM. Use {@literal *}/* + * if the MIME type is unknown (this will only allow senders that can + * handle generic data streams). + * <p> + * Optional standard extras, which may be interpreted by some recipients as + * appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC}, + * {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}. + * <p> + * Output: nothing. + */ + public static final String ACTION_SEND = "android.intent.action.SEND"; + + /** + * Activity Action: Deliver multiple data to someone else. + * <p> + * Like ACTION_SEND, except the data is multiple. + * <p> + * Input: {@link #getType} is the MIME type of the data being sent. + * get*ArrayListExtra can have either a {@link #EXTRA_TEXT} or {@link + * #EXTRA_STREAM} field, containing the data to be sent. + * <p> + * Multiple types are supported, and receivers should handle mixed types + * whenever possible. The right way for the receiver to check them is to + * use the content resolver on each URI. The intent sender should try to + * put the most concrete mime type in the intent type, but it can fall + * back to {@literal <type>/*} or {@literal *}/* as needed. + * <p> + * e.g. if you are sending image/jpg and image/jpg, the intent's type can + * be image/jpg, but if you are sending image/jpg and image/png, then the + * intent's type should be image/*. + * <p> + * Optional standard extras, which may be interpreted by some recipients as + * appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC}, + * {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}. + * <p> + * Output: nothing. + */ + public static final String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE"; + + /** + * Activity Action: Handle an incoming phone call. + * <p>Input: nothing. + * <p>Output: nothing. + */ + public static final String ACTION_ANSWER = "android.intent.action.ANSWER"; + + /** + * Activity Action: Insert an empty item into the given container. + * <p>Input: {@link #getData} is URI of the directory (vnd.android.cursor.dir/*) + * in which to place the data. + * <p>Output: URI of the new data that was created. + */ + public static final String ACTION_INSERT = "android.intent.action.INSERT"; + + /** + * Activity Action: Create a new item in the given container, initializing it + * from the current contents of the clipboard. + * <p>Input: {@link #getData} is URI of the directory (vnd.android.cursor.dir/*) + * in which to place the data. + * <p>Output: URI of the new data that was created. + */ + public static final String ACTION_PASTE = "android.intent.action.PASTE"; + + /** + * Activity Action: Delete the given data from its container. + * <p>Input: {@link #getData} is URI of data to be deleted. + * <p>Output: nothing. + */ + public static final String ACTION_DELETE = "android.intent.action.DELETE"; + /** + * Activity Action: Run the data, whatever that means. + * <p>Input: ? (Note: this is currently specific to the test harness.) + * <p>Output: nothing. + */ + public static final String ACTION_RUN = "android.intent.action.RUN"; + + /** + * Activity Action: Perform a data synchronization. + * <p>Input: ? + * <p>Output: ? + */ + public static final String ACTION_SYNC = "android.intent.action.SYNC"; + + /** + * Activity Action: Pick an activity given an intent, returning the class + * selected. + * <p>Input: get*Extra field {@link #EXTRA_INTENT} is an Intent + * used with {@link PackageManager#queryIntentActivities} to determine the + * set of activities from which to pick. + * <p>Output: Class name of the activity that was selected. + */ + public static final String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY"; + + /** + * Activity Action: Perform a search. + * <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)} + * is the text to search for. If empty, simply + * enter your search results Activity with the search UI activated. + * <p>Output: nothing. + */ + public static final String ACTION_SEARCH = "android.intent.action.SEARCH"; + + /** + * Activity Action: Start the platform-defined tutorial + * <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)} + * is the text to search for. If empty, simply + * enter your search results Activity with the search UI activated. + * <p>Output: nothing. + */ + public static final String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL"; + + /** + * Activity Action: Perform a web search. + * <p> + * Input: {@link android.app.SearchManager#QUERY + * getStringExtra(SearchManager.QUERY)} is the text to search for. If it is + * a url starts with http or https, the site will be opened. If it is plain + * text, Google search will be applied. + * <p> + * Output: nothing. + */ + public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH"; + + /** + * Activity Action: List all available applications + * <p>Input: Nothing. + * <p>Output: nothing. + */ + public static final String ACTION_ALL_APPS = "android.intent.action.ALL_APPS"; + + /** + * Activity Action: Show settings for choosing wallpaper + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + public static final String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER"; + + /** + * Activity Action: Show activity for reporting a bug. + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + public static final String ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT"; + + /** + * Activity Action: Main entry point for factory tests. Only used when + * the device is booting in factory test node. The implementing package + * must be installed in the system image. + * <p>Input: nothing + * <p>Output: nothing + */ + public static final String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST"; + + /** + * Activity Action: The user pressed the "call" button to go to the dialer + * or other appropriate UI for placing a call. + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + public static final String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON"; + + /** + * Activity Action: Start Voice Command. + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND"; + + /** + * Activity Action: Start action associated with long pressing on the + * search key. + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS"; + + /** + * Activity Action: The user pressed the "Report" button in the crash/ANR dialog. + * This intent is delivered to the package which installed the application, usually + * Google Play. + * <p>Input: No data is specified. The bug report is passed in using + * an {@link #EXTRA_BUG_REPORT} field. + * <p>Output: Nothing. + * + * @see #EXTRA_BUG_REPORT + */ + public static final String ACTION_APP_ERROR = "android.intent.action.APP_ERROR"; + + /** + * Activity Action: Show power usage information to the user. + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + public static final String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY"; + + /** + * Activity Action: Setup wizard to launch after a platform update. This + * activity should have a string meta-data field associated with it, + * {@link #METADATA_SETUP_VERSION}, which defines the current version of + * the platform for setup. The activity will be launched only if + * {@link android.provider.Settings.Secure#LAST_SETUP_SHOWN} is not the + * same value. + * <p>Input: Nothing. + * <p>Output: Nothing. + * @hide + */ + public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP"; + + /** + * Activity Action: Show settings for managing network data usage of a + * specific application. Applications should define an activity that offers + * options to control data usage. + */ + public static final String ACTION_MANAGE_NETWORK_USAGE = + "android.intent.action.MANAGE_NETWORK_USAGE"; + + /** + * Activity Action: Launch application installer. + * <p> + * Input: The data must be a content: or file: URI at which the application + * can be retrieved. You can optionally supply + * {@link #EXTRA_INSTALLER_PACKAGE_NAME}, {@link #EXTRA_NOT_UNKNOWN_SOURCE}, + * {@link #EXTRA_ALLOW_REPLACE}, and {@link #EXTRA_RETURN_RESULT}. + * <p> + * Output: If {@link #EXTRA_RETURN_RESULT}, returns whether the install + * succeeded. + * + * @see #EXTRA_INSTALLER_PACKAGE_NAME + * @see #EXTRA_NOT_UNKNOWN_SOURCE + * @see #EXTRA_RETURN_RESULT + */ + public static final String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE"; + + /** + * Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a + * package. Tells the installer UI to skip the confirmation with the user + * if the .apk is replacing an existing one. + */ + public static final String EXTRA_ALLOW_REPLACE + = "android.intent.extra.ALLOW_REPLACE"; + + /** + * Extra used to indicate that an intent can allow the user to select and return multiple items. + * This is a boolean extra; the default is false. If true, an implementation is allowed to present + * the user with a UI where they can pick multiple items that are all returned to the caller. + * When this happens, they should be returned as the getClipData() part of the result Intent. + */ + public static final String EXTRA_ALLOW_MULTIPLE + = "android.intent.extra.ALLOW_MULTIPLE"; + + /** + * Used to indicate that a GET_CONTENT intent only wants URIs that can be opened with + * ContentResolver.openInputStream. Openable URIs must support the columns in OpenableColumns + * when queried, though it is allowable for those columns to be blank. + */ + public static final String CATEGORY_OPENABLE = "android.intent.category.OPENABLE"; + /** * Create an empty intent. */ @@ -1407,6 +1912,35 @@ public class Intent implements Parcelable, Cloneable { return null; } + /** + * Set an explicit MIME data type. + * + * <p>This is used to create intents that only specify a type and not data, + * for example to indicate the type of data to return. + * + * <p>This method automatically clears any data that was + * previously set (for example by {@link #setData}). + * + * <p><em>Note: MIME type matching in the Android framework is + * case-sensitive, unlike formal RFC MIME types. As a result, + * you should always write your MIME types with lower case letters, + * or use {@link #normalizeMimeType} or {@link #setTypeAndNormalize} + * to ensure that it is converted to lower case.</em> + * + * @param type The MIME type of the data being handled by this intent. + * + * @return Returns the same Intent object, for chaining multiple calls + * into a single statement. + * + * @see #getType + * @see #setTypeAndNormalize + * @see #setDataAndType + * @see #normalizeMimeType + */ + public Intent setType(String type) { + return null; + } + /** * Add extended data to the intent. The name must include a package prefix, for * example the app com.android.contacts would use names like @@ -2071,4 +2605,23 @@ public class Intent implements Parcelable, Cloneable { return null; } + /** + * Add a new category to the intent. Categories provide additional detail + * about the action the intent performs. When resolving an intent, only + * activities that provide <em>all</em> of the requested categories will be + * used. + * + * @param category The desired category. This can be either one of the + * predefined Intent categories, or a custom category in your own + * namespace. + * + * @return Returns the same Intent object, for chaining multiple calls + * into a single statement. + * + * @see #hasCategory + * @see #removeCategory + */ + public Intent addCategory(String category) { + return null; + } } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/AsyncTask.java b/java/ql/test/stubs/google-android-9.0.0/android/os/AsyncTask.java new file mode 100644 index 00000000000..23ca3179bbc --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/AsyncTask.java @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.os; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; + +/** + * <p>AsyncTask enables proper and easy use of the UI thread. This class allows you + * to perform background operations and publish results on the UI thread without + * having to manipulate threads and/or handlers.</p> + * + * <p>AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler} + * and does not constitute a generic threading framework. AsyncTasks should ideally be + * used for short operations (a few seconds at the most.) If you need to keep threads + * running for long periods of time, it is highly recommended you use the various APIs + * provided by the <code>java.util.concurrent</code> package such as {@link Executor}, + * {@link ThreadPoolExecutor} and {@link FutureTask}.</p> + * + * <p>An asynchronous task is defined by a computation that runs on a background thread and + * whose result is published on the UI thread. An asynchronous task is defined by 3 generic + * types, called <code>Params</code>, <code>Progress</code> and <code>Result</code>, + * and 4 steps, called <code>onPreExecute</code>, <code>doInBackground</code>, + * <code>onProgressUpdate</code> and <code>onPostExecute</code>.</p> + * + * <div class="special reference"> + * <h3>Developer Guides</h3> + * <p>For more information about using tasks and threads, read the + * <a href="{@docRoot}guide/components/processes-and-threads.html">Processes and + * Threads</a> developer guide.</p> + * </div> + * + * <h2>Usage</h2> + * <p>AsyncTask must be subclassed to be used. The subclass will override at least + * one method ({@link #doInBackground}), and most often will override a + * second one ({@link #onPostExecute}.)</p> + * + * <p>Here is an example of subclassing:</p> + * <pre class="prettyprint"> + * private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { + * protected Long doInBackground(URL... urls) { + * int count = urls.length; + * long totalSize = 0; + * for (int i = 0; i < count; i++) { + * totalSize += Downloader.downloadFile(urls[i]); + * publishProgress((int) ((i / (float) count) * 100)); + * // Escape early if cancel() is called + * if (isCancelled()) break; + * } + * return totalSize; + * } + * + * protected void onProgressUpdate(Integer... progress) { + * setProgressPercent(progress[0]); + * } + * + * protected void onPostExecute(Long result) { + * showDialog("Downloaded " + result + " bytes"); + * } + * } + * </pre> + * + * <p>Once created, a task is executed very simply:</p> + * <pre class="prettyprint"> + * new DownloadFilesTask().execute(url1, url2, url3); + * </pre> + * + * <h2>AsyncTask's generic types</h2> + * <p>The three types used by an asynchronous task are the following:</p> + * <ol> + * <li><code>Params</code>, the type of the parameters sent to the task upon + * execution.</li> + * <li><code>Progress</code>, the type of the progress units published during + * the background computation.</li> + * <li><code>Result</code>, the type of the result of the background + * computation.</li> + * </ol> + * <p>Not all types are always used by an asynchronous task. To mark a type as unused, + * simply use the type {@link Void}:</p> + * <pre> + * private class MyTask extends AsyncTask<Void, Void, Void> { ... } + * </pre> + * + * <h2>The 4 steps</h2> + * <p>When an asynchronous task is executed, the task goes through 4 steps:</p> + * <ol> + * <li>{@link #onPreExecute()}, invoked on the UI thread before the task + * is executed. This step is normally used to setup the task, for instance by + * showing a progress bar in the user interface.</li> + * <li>{@link #doInBackground}, invoked on the background thread + * immediately after {@link #onPreExecute()} finishes executing. This step is used + * to perform background computation that can take a long time. The parameters + * of the asynchronous task are passed to this step. The result of the computation must + * be returned by this step and will be passed back to the last step. This step + * can also use {@link #publishProgress} to publish one or more units + * of progress. These values are published on the UI thread, in the + * {@link #onProgressUpdate} step.</li> + * <li>{@link #onProgressUpdate}, invoked on the UI thread after a + * call to {@link #publishProgress}. The timing of the execution is + * undefined. This method is used to display any form of progress in the user + * interface while the background computation is still executing. For instance, + * it can be used to animate a progress bar or show logs in a text field.</li> + * <li>{@link #onPostExecute}, invoked on the UI thread after the background + * computation finishes. The result of the background computation is passed to + * this step as a parameter.</li> + * </ol> + * + * <h2>Cancelling a task</h2> + * <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking + * this method will cause subsequent calls to {@link #isCancelled()} to return true. + * After invoking this method, {@link #onCancelled(Object)}, instead of + * {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])} + * returns. To ensure that a task is cancelled as quickly as possible, you should always + * check the return value of {@link #isCancelled()} periodically from + * {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p> + * + * <h2>Threading rules</h2> + * <p>There are a few threading rules that must be followed for this class to + * work properly:</p> + * <ul> + * <li>The AsyncTask class must be loaded on the UI thread. This is done + * automatically as of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}.</li> + * <li>The task instance must be created on the UI thread.</li> + * <li>{@link #execute} must be invoked on the UI thread.</li> + * <li>Do not call {@link #onPreExecute()}, {@link #onPostExecute}, + * {@link #doInBackground}, {@link #onProgressUpdate} manually.</li> + * <li>The task can be executed only once (an exception will be thrown if + * a second execution is attempted.)</li> + * </ul> + * + * <h2>Memory observability</h2> + * <p>AsyncTask guarantees that all callback calls are synchronized in such a way that the following + * operations are safe without explicit synchronizations.</p> + * <ul> + * <li>Set member fields in the constructor or {@link #onPreExecute}, and refer to them + * in {@link #doInBackground}. + * <li>Set member fields in {@link #doInBackground}, and refer to them in + * {@link #onProgressUpdate} and {@link #onPostExecute}. + * </ul> + * + * <h2>Order of execution</h2> + * <p>When first introduced, AsyncTasks were executed serially on a single background + * thread. Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed + * to a pool of threads allowing multiple tasks to operate in parallel. Starting with + * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are executed on a single + * thread to avoid common application errors caused by parallel execution.</p> + * <p>If you truly want parallel execution, you can invoke + * {@link #executeOnExecutor(java.util.concurrent.Executor, Object[])} with + * {@link #THREAD_POOL_EXECUTOR}.</p> + */ +public abstract class AsyncTask<Params, Progress, Result> { + /** + * Creates a new asynchronous task. This constructor must be invoked on the UI thread. + */ + public AsyncTask() { + } + + /** + * Override this method to perform a computation on a background thread. The + * specified parameters are the parameters passed to {@link #execute} + * by the caller of this task. + * + * This method can call {@link #publishProgress} to publish updates + * on the UI thread. + * + * @param params The parameters of the task. + * + * @return A result, defined by the subclass of this task. + * + * @see #onPreExecute() + * @see #onPostExecute + * @see #publishProgress + */ + protected abstract Result doInBackground(Params... params); + + /** + * Runs on the UI thread before {@link #doInBackground}. + * + * @see #onPostExecute + * @see #doInBackground + */ + protected void onPreExecute() { + } + + /** + * <p>Runs on the UI thread after {@link #doInBackground}. The + * specified result is the value returned by {@link #doInBackground}.</p> + * + * <p>This method won't be invoked if the task was cancelled.</p> + * + * @param result The result of the operation computed by {@link #doInBackground}. + * + * @see #onPreExecute + * @see #doInBackground + * @see #onCancelled(Object) + */ + protected void onPostExecute(Result result) { + } + + /** + * Runs on the UI thread after {@link #publishProgress} is invoked. + * The specified values are the values passed to {@link #publishProgress}. + * + * @param values The values indicating progress. + * + * @see #publishProgress + * @see #doInBackground + */ + protected void onProgressUpdate(Progress... values) { + } + + /** + * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and + * {@link #doInBackground(Object[])} has finished.</p> + * + * <p>The default implementation simply invokes {@link #onCancelled()} and + * ignores the result. If you write your own implementation, do not call + * <code>super.onCancelled(result)</code>.</p> + * + * @param result The result, if any, computed in + * {@link #doInBackground(Object[])}, can be null + * + * @see #cancel(boolean) + * @see #isCancelled() + */ + protected void onCancelled(Result result) { + onCancelled(); + } + + /** + * <p>Applications should preferably override {@link #onCancelled(Object)}. + * This method is invoked by the default implementation of + * {@link #onCancelled(Object)}.</p> + * + * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and + * {@link #doInBackground(Object[])} has finished.</p> + * + * @see #onCancelled(Object) + * @see #cancel(boolean) + * @see #isCancelled() + */ + protected void onCancelled() { + } + + /** + * Returns <tt>true</tt> if this task was cancelled before it completed + * normally. If you are calling {@link #cancel(boolean)} on the task, + * the value returned by this method should be checked periodically from + * {@link #doInBackground(Object[])} to end the task as soon as possible. + * + * @return <tt>true</tt> if task was cancelled before it completed + * + * @see #cancel(boolean) + */ + public final boolean isCancelled() { + return false; + } + + /** + * <p>Attempts to cancel execution of this task. This attempt will + * fail if the task has already completed, already been cancelled, + * or could not be cancelled for some other reason. If successful, + * and this task has not started when <tt>cancel</tt> is called, + * this task should never run. If the task has already started, + * then the <tt>mayInterruptIfRunning</tt> parameter determines + * whether the thread executing this task should be interrupted in + * an attempt to stop the task.</p> + * + * <p>Calling this method will result in {@link #onCancelled(Object)} being + * invoked on the UI thread after {@link #doInBackground(Object[])} + * returns. Calling this method guarantees that {@link #onPostExecute(Object)} + * is never invoked. After invoking this method, you should check the + * value returned by {@link #isCancelled()} periodically from + * {@link #doInBackground(Object[])} to finish the task as early as + * possible.</p> + * + * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this + * task should be interrupted; otherwise, in-progress tasks are allowed + * to complete. + * + * @return <tt>false</tt> if the task could not be cancelled, + * typically because it has already completed normally; + * <tt>true</tt> otherwise + * + * @see #isCancelled() + * @see #onCancelled(Object) + */ + public final boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + /** + * Waits if necessary for the computation to complete, and then + * retrieves its result. + * + * @return The computed result. + * + * @throws CancellationException If the computation was cancelled. + * @throws ExecutionException If the computation threw an exception. + * @throws InterruptedException If the current thread was interrupted + * while waiting. + */ + public final Result get() throws InterruptedException, ExecutionException { + return null; + } + + /** + * Executes the task with the specified parameters. The task returns + * itself (this) so that the caller can keep a reference to it. + * + * <p>Note: this function schedules the task on a queue for a single background + * thread or pool of threads depending on the platform version. When first + * introduced, AsyncTasks were executed serially on a single background thread. + * Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed + * to a pool of threads allowing multiple tasks to operate in parallel. Starting + * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being + * executed on a single thread to avoid common application errors caused + * by parallel execution. If you truly want parallel execution, you can use + * the {@link #executeOnExecutor} version of this method + * with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings + * on its use. + * + * <p>This method must be invoked on the UI thread. + * + * @param params The parameters of the task. + * + * @return This instance of AsyncTask. + * + * @throws IllegalStateException If {@link #getStatus()} returns either + * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. + * + * @see #executeOnExecutor(java.util.concurrent.Executor, Object[]) + * @see #execute(Runnable) + */ + public final AsyncTask<Params, Progress, Result> execute(Params... params) { + return null; + } + + /** + * Executes the task with the specified parameters. The task returns + * itself (this) so that the caller can keep a reference to it. + * + * <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to + * allow multiple tasks to run in parallel on a pool of threads managed by + * AsyncTask, however you can also use your own {@link Executor} for custom + * behavior. + * + * <p><em>Warning:</em> Allowing multiple tasks to run in parallel from + * a thread pool is generally <em>not</em> what one wants, because the order + * of their operation is not defined. For example, if these tasks are used + * to modify any state in common (such as writing a file due to a button click), + * there are no guarantees on the order of the modifications. + * Without careful work it is possible in rare cases for the newer version + * of the data to be over-written by an older one, leading to obscure data + * loss and stability issues. Such changes are best + * executed in serial; to guarantee such work is serialized regardless of + * platform version you can use this function with {@link #SERIAL_EXECUTOR}. + * + * <p>This method must be invoked on the UI thread. + * + * @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a + * convenient process-wide thread pool for tasks that are loosely coupled. + * @param params The parameters of the task. + * + * @return This instance of AsyncTask. + * + * @throws IllegalStateException If {@link #getStatus()} returns either + * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. + * + * @see #execute(Object[]) + */ + public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, + Params... params) { + return null; + } + + /** + * This method can be invoked from {@link #doInBackground} to + * publish updates on the UI thread while the background computation is + * still running. Each call to this method will trigger the execution of + * {@link #onProgressUpdate} on the UI thread. + * + * {@link #onProgressUpdate} will not be called if the task has been + * canceled. + * + * @param values The progress values to update the UI with. + * + * @see #onProgressUpdate + * @see #doInBackground + */ + protected final void publishProgress(Progress... values) { + } +} From 02bfa1ca57afd6a06cade438961483ee39ce8c6c Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Fri, 10 Sep 2021 15:04:29 +0000 Subject: [PATCH 156/361] Optimize the query --- .../CWE/CWE-200/AndroidFileIntentSink.qll | 14 ++++-- .../CWE/CWE-200/AndroidFileIntentSource.qll | 2 +- .../CWE/CWE-200/SensitiveAndroidFileLeak.ql | 43 +++++++++---------- .../CWE-200/SensitiveAndroidFileLeak.expected | 12 +++--- 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll index 95b11e34849..c31a2fb235e 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll @@ -19,24 +19,30 @@ class AsyncTask extends RefType { AsyncTask() { this.hasQualifiedName("android.os", "AsyncTask") } } +/** The method that executes `AsyncTask` of Android. */ +abstract class ExecuteAsyncTaskMethod extends Method { + /** Returns index of the parameter that is tainted. */ + abstract int getParamIndex(); +} + /** The `execute` method of Android `AsyncTask`. */ -class AsyncTaskExecuteMethod extends Method { +class AsyncTaskExecuteMethod extends ExecuteAsyncTaskMethod { AsyncTaskExecuteMethod() { this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and this.getName() = "execute" } - int getParamIndex() { result = 0 } + override int getParamIndex() { result = 0 } } /** The `executeOnExecutor` method of Android `AsyncTask`. */ -class AsyncTaskExecuteOnExecutorMethod extends Method { +class AsyncTaskExecuteOnExecutorMethod extends ExecuteAsyncTaskMethod { AsyncTaskExecuteOnExecutorMethod() { this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and this.getName() = "executeOnExecutor" } - int getParamIndex() { result = 1 } + override int getParamIndex() { result = 1 } } /** The `doInBackground` method of Android `AsyncTask`. */ diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll index 6df48f530a5..46b6e1059bb 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll @@ -15,7 +15,7 @@ class StartActivityForResultMethod extends Method { /** Android class instance of `GET_CONTENT` intent. */ class GetContentIntent extends ClassInstanceExpr { GetContentIntent() { - this.getConstructedType().getASupertype*() instanceof TypeIntent and + this.getConstructedType() instanceof TypeIntent and this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "android.intent.action.GET_CONTENT" or diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql index c4bdde170ba..a216892826d 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql @@ -3,7 +3,7 @@ * @description Getting file intent from user input without path validation could leak arbitrary * Android configuration file and sensitive user data. * @kind path-problem - * @id java/sensitive_android_file_leak + * @id java/sensitive-android-file-leak * @tags security * external/cwe/cwe-200 */ @@ -14,6 +14,19 @@ import AndroidFileIntentSource import DataFlow2::PathGraph import semmle.code.java.dataflow.TaintTracking2 +private class StartsWithSanitizer extends DataFlow2::BarrierGuard { + StartsWithSanitizer() { this.(MethodAccess).getMethod().hasName("startsWith") } + + override predicate checks(Expr e, boolean branch) { + e = + [ + this.(MethodAccess).getQualifier(), + this.(MethodAccess).getQualifier().(MethodAccess).getQualifier() + ] and + branch = false + } +} + class AndroidFileLeakConfig extends TaintTracking2::Configuration { AndroidFileLeakConfig() { this = "AndroidFileLeakConfig" } @@ -38,37 +51,23 @@ class AndroidFileLeakConfig extends TaintTracking2::Configuration { exists(MethodAccess aema, AsyncTaskRunInBackgroundMethod arm | // fileAsyncTask.execute(params) will invoke doInBackground(params) of FileAsyncTask aema.getQualifier().getType() = arm.getDeclaringType() and - ( - aema.getMethod() instanceof AsyncTaskExecuteMethod and - prev.asExpr() = aema.getArgument(0) - or - aema.getMethod() instanceof AsyncTaskExecuteOnExecutorMethod and - prev.asExpr() = aema.getArgument(1) - ) and - succ.asExpr() = arm.getParameter(0).getAnAccess() + aema.getMethod() instanceof ExecuteAsyncTaskMethod and + prev.asExpr() = aema.getArgument(aema.getMethod().(ExecuteAsyncTaskMethod).getParamIndex()) and + succ.asParameter() = arm.getParameter(0) ) or exists(MethodAccess csma, ServiceOnStartCommandMethod ssm, ClassInstanceExpr ce | csma.getMethod() instanceof ContextStartServiceMethod and ce.getConstructedType() instanceof TypeIntent and // Intent intent = new Intent(context, FileUploader.class); - ce.getArgument(1).getType().(ParameterizedType).getTypeArgument(0) = ssm.getDeclaringType() and + ce.getArgument(1).(TypeLiteral).getReferencedType() = ssm.getDeclaringType() and DataFlow2::localExprFlow(ce, csma.getArgument(0)) and // context.startService(intent); prev.asExpr() = csma.getArgument(0) and - succ.asExpr() = ssm.getParameter(0).getAnAccess() // public int onStartCommand(Intent intent, int flags, int startId) {...} in FileUploader + succ.asParameter() = ssm.getParameter(0) // public int onStartCommand(Intent intent, int flags, int startId) {...} in FileUploader ) } - override predicate isSanitizer(DataFlow2::Node node) { - exists( - MethodAccess startsWith // "startsWith" path check - | - startsWith.getMethod().hasName("startsWith") and - ( - DataFlow2::localExprFlow(node.asExpr(), startsWith.getQualifier()) or - DataFlow2::localExprFlow(node.asExpr(), - startsWith.getQualifier().(MethodAccess).getQualifier()) - ) - ) + override predicate isSanitizerGuard(DataFlow2::BarrierGuard guard) { + guard instanceof StartsWithSanitizer } } diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected index db29fd64568..47f27356d87 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -1,26 +1,28 @@ edges +| FileService.java:20:31:20:43 | intent : Intent | FileService.java:21:28:21:33 | intent : Intent | +| FileService.java:20:31:20:43 | intent : Intent | FileService.java:25:42:25:50 | localPath : String | | FileService.java:21:28:21:33 | intent : Intent | FileService.java:21:28:21:64 | getStringExtra(...) : String | -| FileService.java:21:28:21:33 | intent : Intent | FileService.java:25:42:25:50 | localPath : String | | FileService.java:21:28:21:64 | getStringExtra(...) : String | FileService.java:25:42:25:50 | localPath : String | -| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:44:44:44:49 | params : Object[] | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:40:41:40:55 | params : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | | FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | +| FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | | FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | -| FileService.java:44:44:44:49 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | -| LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:21:28:21:33 | intent : Intent | +| LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:20:31:20:43 | intent : Intent | | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | LeakFileActivity.java:21:58:21:82 | getPath(...) | nodes +| FileService.java:20:31:20:43 | intent : Intent | semmle.label | intent : Intent | | FileService.java:21:28:21:33 | intent : Intent | semmle.label | intent : Intent | | FileService.java:21:28:21:64 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | semmle.label | makeParamsToExecute(...) [[]] : String | | FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String | +| FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] | | FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | -| FileService.java:44:44:44:49 | params : Object[] | semmle.label | params : Object[] | | FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] | | LeakFileActivity2.java:16:26:16:31 | intent : Intent | semmle.label | intent : Intent | | LeakFileActivity.java:14:35:14:38 | data : Intent | semmle.label | data : Intent | From 3607d50994c419a4749b9627d949710450b8828f Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Mon, 13 Sep 2021 11:45:33 +0100 Subject: [PATCH 157/361] Update remote flow source locations --- .../library-tests/dataflow/taintsources/remote.expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.expected b/java/ql/test/library-tests/dataflow/taintsources/remote.expected index f1e5b4e3ff1..55268b63bad 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.expected @@ -5,15 +5,15 @@ | A.java:41:5:41:53 | getInputStream(...) | A.java:41:5:41:53 | getInputStream(...) | | A.java:42:5:42:45 | getInputStream(...) | A.java:42:5:42:45 | getInputStream(...) | | A.java:43:5:43:47 | getHostName(...) | A.java:43:5:43:47 | getHostName(...) | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:35 | getIntent(...) | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:57 | getStringExtra(...) | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:10:29:10:35 | trouble | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:30 | getIntent(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:52 | getStringExtra(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:17:29:17:35 | trouble | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1358:19:1358:27 | parameter this | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | parameter this | | IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] read: <map.value> of argument -1 in getString | | IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] to write: return (return) in getString | | IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | parameter this | @@ -21,7 +21,7 @@ | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:42 | getExtras(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:59 | getString(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:24:29:24:35 | trouble | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:33 | getIntent(...) | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:55 | getStringExtra(...) | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:34:29:34:35 | trouble | From 9e0cf5a2fd340ccd0e6db4e0a00e837c24756bf3 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Mon, 13 Sep 2021 11:47:07 +0100 Subject: [PATCH 158/361] Update test expectations to include subpaths --- .../security/CWE-200/SensitiveAndroidFileLeak.expected | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected index 47f27356d87..d7800b31556 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -6,6 +6,10 @@ edges | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:40:41:40:55 | params : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | | FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | +| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | +| FileService.java:32:13:32:28 | sourceUri : String | FileService.java:35:17:35:25 | sourceUri : String | +| FileService.java:34:20:36:13 | {...} [[]] : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | +| FileService.java:35:17:35:25 | sourceUri : String | FileService.java:34:20:36:13 | {...} [[]] : String | | FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | | FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:20:31:20:43 | intent : Intent | @@ -21,6 +25,10 @@ nodes | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | semmle.label | makeParamsToExecute(...) [[]] : String | | FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String | +| FileService.java:32:13:32:28 | sourceUri : String | semmle.label | sourceUri : String | +| FileService.java:34:20:36:13 | new Object[] [[]] : String | semmle.label | new Object[] [[]] : String | +| FileService.java:34:20:36:13 | {...} [[]] : String | semmle.label | {...} [[]] : String | +| FileService.java:35:17:35:25 | sourceUri : String | semmle.label | sourceUri : String | | FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] | | FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | | FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] | @@ -31,6 +39,8 @@ nodes | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | semmle.label | getData(...) : Uri | | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | semmle.label | streamsToUpload : Uri | | LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) | +subpaths +| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | #select | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:16:26:16:31 | intent | this user input | | LeakFileActivity.java:21:58:21:82 | getPath(...) | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:21:58:21:82 | getPath(...) | Leaking arbitrary Android file from $@. | LeakFileActivity.java:14:35:14:38 | data | this user input | From b0e652a3af94b5825ae3ec797359eb9a85450039 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Mon, 13 Sep 2021 11:51:46 +0100 Subject: [PATCH 159/361] Remove AsyncTask models --- .../Security/CWE/CWE-200/AndroidFileIntentSource.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll index 46b6e1059bb..af7fb485814 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll @@ -61,9 +61,7 @@ private class AndroidIntentDataModel extends SummaryModelCsv { "android.net;Uri;true;getPathSegments;;;Argument[-1];ReturnValue;taint", "android.net;Uri;true;getQuery;;;Argument[-1];ReturnValue;taint", "android.net;Uri;true;getQueryParameter;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getQueryParameters;;;Argument[-1];ReturnValue;taint", - "android.os;AsyncTask;true;execute;;;Argument[0];ReturnValue;taint", - "android.os;AsyncTask;true;doInBackground;;;Argument[0];ReturnValue;taint" + "android.net;Uri;true;getQueryParameters;;;Argument[-1];ReturnValue;taint" ] } } From 8c2fddb2979dad0983a12011144ad53b303846c9 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Mon, 4 Oct 2021 16:46:44 +0000 Subject: [PATCH 160/361] Update the condition check and use DataFlow in the ql file --- .../CWE/CWE-200/AndroidFileIntentSink.qll | 30 ++++++---------- .../CWE/CWE-200/AndroidFileIntentSource.qll | 7 ++-- .../CWE/CWE-200/SensitiveAndroidFileLeak.ql | 36 +++++++++++-------- .../CWE-200/SensitiveAndroidFileLeak.expected | 10 ------ 4 files changed, 35 insertions(+), 48 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll index c31a2fb235e..c3f5eebccc4 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll @@ -19,30 +19,20 @@ class AsyncTask extends RefType { AsyncTask() { this.hasQualifiedName("android.os", "AsyncTask") } } -/** The method that executes `AsyncTask` of Android. */ -abstract class ExecuteAsyncTaskMethod extends Method { - /** Returns index of the parameter that is tainted. */ - abstract int getParamIndex(); -} +/** The `execute` or `executeOnExecutor` method of Android `AsyncTask`. */ +class ExecuteAsyncTaskMethod extends Method { + int paramIndex; -/** The `execute` method of Android `AsyncTask`. */ -class AsyncTaskExecuteMethod extends ExecuteAsyncTaskMethod { - AsyncTaskExecuteMethod() { + ExecuteAsyncTaskMethod() { this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and - this.getName() = "execute" + ( + this.getName() = "execute" and paramIndex = 0 + or + this.getName() = "executeOnExecutor" and paramIndex = 1 + ) } - override int getParamIndex() { result = 0 } -} - -/** The `executeOnExecutor` method of Android `AsyncTask`. */ -class AsyncTaskExecuteOnExecutorMethod extends ExecuteAsyncTaskMethod { - AsyncTaskExecuteOnExecutorMethod() { - this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and - this.getName() = "executeOnExecutor" - } - - override int getParamIndex() { result = 1 } + int getParamIndex() { result = paramIndex } } /** The `doInBackground` method of Android `AsyncTask`. */ diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll index af7fb485814..8ef29014c8e 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll @@ -2,6 +2,7 @@ import java import semmle.code.java.dataflow.FlowSources +import semmle.code.java.dataflow.TaintTracking2 import semmle.code.java.frameworks.android.Android /** The `startActivityForResult` method of Android `Activity`. */ @@ -67,14 +68,14 @@ private class AndroidIntentDataModel extends SummaryModelCsv { } /** Taint configuration for getting content intent. */ -class GetContentIntentConfig extends TaintTracking::Configuration { +class GetContentIntentConfig extends TaintTracking2::Configuration { GetContentIntentConfig() { this = "GetContentIntentConfig" } - override predicate isSource(DataFlow::Node src) { + override predicate isSource(DataFlow2::Node src) { exists(GetContentIntent gi | src.asExpr() = gi) } - override predicate isSink(DataFlow::Node sink) { + override predicate isSink(DataFlow2::Node sink) { exists(MethodAccess ma | ma.getMethod() instanceof StartActivityForResultMethod and sink.asExpr() = ma.getArgument(0) ) diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql index a216892826d..2fb5642d8eb 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql @@ -4,17 +4,18 @@ * Android configuration file and sensitive user data. * @kind path-problem * @id java/sensitive-android-file-leak + * @problem.severity warning * @tags security * external/cwe/cwe-200 */ import java +import semmle.code.java.controlflow.Guards import AndroidFileIntentSink import AndroidFileIntentSource -import DataFlow2::PathGraph -import semmle.code.java.dataflow.TaintTracking2 +import DataFlow::PathGraph -private class StartsWithSanitizer extends DataFlow2::BarrierGuard { +private class StartsWithSanitizer extends DataFlow::BarrierGuard { StartsWithSanitizer() { this.(MethodAccess).getMethod().hasName("startsWith") } override predicate checks(Expr e, boolean branch) { @@ -27,27 +28,32 @@ private class StartsWithSanitizer extends DataFlow2::BarrierGuard { } } -class AndroidFileLeakConfig extends TaintTracking2::Configuration { +class AndroidFileLeakConfig extends TaintTracking::Configuration { AndroidFileLeakConfig() { this = "AndroidFileLeakConfig" } - /** Holds if it is an access to file intent result. */ - override predicate isSource(DataFlow2::Node src) { + /** + * Holds if `src` is a read of some Intent-typed method argument guarded by a check like + * `requestCode == REQUEST_CODE__SELECT_CONTENT_FROM_APPS`, where `requestCode` is the first + * argument to `Activity.onActivityResult`. + */ + override predicate isSource(DataFlow::Node src) { exists( - AndroidActivityResultInput ai, AndroidFileIntentInput fi, IfStmt ifs, VarAccess intentVar // if (requestCode == REQUEST_CODE__SELECT_CONTENT_FROM_APPS) + AndroidActivityResultInput ai, AndroidFileIntentInput fi, ConditionBlock cb, + VarAccess intentVar | - ifs.getCondition().getAChildExpr().getAChildExpr().(CompileTimeConstantExpr).getIntValue() = + cb.getCondition().getAChildExpr().(CompileTimeConstantExpr).getIntValue() = fi.getRequestCode() and - ifs.getCondition().getAChildExpr().getAChildExpr() = ai.getRequestCodeVar() and + cb.getCondition().getAChildExpr() = ai.getRequestCodeVar() and intentVar.getType() instanceof TypeIntent and - intentVar.(Argument).getAnEnclosingStmt() = ifs.getThen() and + cb.getBasicBlock() = intentVar.(Argument).getAnEnclosingStmt() and src.asExpr() = intentVar ) } /** Holds if it is a sink of file access in Android. */ - override predicate isSink(DataFlow2::Node sink) { sink instanceof AndroidFileSink } + override predicate isSink(DataFlow::Node sink) { sink instanceof AndroidFileSink } - override predicate isAdditionalTaintStep(DataFlow2::Node prev, DataFlow2::Node succ) { + override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) { exists(MethodAccess aema, AsyncTaskRunInBackgroundMethod arm | // fileAsyncTask.execute(params) will invoke doInBackground(params) of FileAsyncTask aema.getQualifier().getType() = arm.getDeclaringType() and @@ -60,18 +66,18 @@ class AndroidFileLeakConfig extends TaintTracking2::Configuration { csma.getMethod() instanceof ContextStartServiceMethod and ce.getConstructedType() instanceof TypeIntent and // Intent intent = new Intent(context, FileUploader.class); ce.getArgument(1).(TypeLiteral).getReferencedType() = ssm.getDeclaringType() and - DataFlow2::localExprFlow(ce, csma.getArgument(0)) and // context.startService(intent); + DataFlow::localExprFlow(ce, csma.getArgument(0)) and // context.startService(intent); prev.asExpr() = csma.getArgument(0) and succ.asParameter() = ssm.getParameter(0) // public int onStartCommand(Intent intent, int flags, int startId) {...} in FileUploader ) } - override predicate isSanitizerGuard(DataFlow2::BarrierGuard guard) { + override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { guard instanceof StartsWithSanitizer } } -from DataFlow2::PathNode source, DataFlow2::PathNode sink, AndroidFileLeakConfig conf +from DataFlow::PathNode source, DataFlow::PathNode sink, AndroidFileLeakConfig conf where conf.hasFlowPath(source, sink) select sink.getNode(), source, sink, "Leaking arbitrary Android file from $@.", source.getNode(), "this user input" diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected index d7800b31556..47f27356d87 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -6,10 +6,6 @@ edges | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:40:41:40:55 | params : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | | FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | -| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | -| FileService.java:32:13:32:28 | sourceUri : String | FileService.java:35:17:35:25 | sourceUri : String | -| FileService.java:34:20:36:13 | {...} [[]] : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | -| FileService.java:35:17:35:25 | sourceUri : String | FileService.java:34:20:36:13 | {...} [[]] : String | | FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | | FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:20:31:20:43 | intent : Intent | @@ -25,10 +21,6 @@ nodes | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | semmle.label | makeParamsToExecute(...) [[]] : String | | FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String | -| FileService.java:32:13:32:28 | sourceUri : String | semmle.label | sourceUri : String | -| FileService.java:34:20:36:13 | new Object[] [[]] : String | semmle.label | new Object[] [[]] : String | -| FileService.java:34:20:36:13 | {...} [[]] : String | semmle.label | {...} [[]] : String | -| FileService.java:35:17:35:25 | sourceUri : String | semmle.label | sourceUri : String | | FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] | | FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | | FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] | @@ -39,8 +31,6 @@ nodes | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | semmle.label | getData(...) : Uri | | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | semmle.label | streamsToUpload : Uri | | LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) | -subpaths -| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | #select | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:16:26:16:31 | intent | this user input | | LeakFileActivity.java:21:58:21:82 | getPath(...) | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:21:58:21:82 | getPath(...) | Leaking arbitrary Android file from $@. | LeakFileActivity.java:14:35:14:38 | data | this user input | From 987bfa6ca707c5ba66af2803959f24813007be71 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Wed, 6 Oct 2021 01:52:28 +0000 Subject: [PATCH 161/361] Update condition check and qldoc --- .../CWE/CWE-200/SensitiveAndroidFileLeak.ql | 15 ++++++++------- .../CWE-200/SensitiveAndroidFileLeak.expected | 3 +++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql index 2fb5642d8eb..82968d33678 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql @@ -34,18 +34,19 @@ class AndroidFileLeakConfig extends TaintTracking::Configuration { /** * Holds if `src` is a read of some Intent-typed method argument guarded by a check like * `requestCode == REQUEST_CODE__SELECT_CONTENT_FROM_APPS`, where `requestCode` is the first - * argument to `Activity.onActivityResult`. + * argument to `Activity.onActivityResult` and `REQUEST_CODE__SELECT_CONTENT_FROM_APPS` is + * any request code in a call to `startActivityForResult(intent, code)`. */ override predicate isSource(DataFlow::Node src) { exists( - AndroidActivityResultInput ai, AndroidFileIntentInput fi, ConditionBlock cb, - VarAccess intentVar + AndroidActivityResultInput ai, AndroidFileIntentInput fi, ConditionBlock cb, EQExpr ee, + CompileTimeConstantExpr cc, VarAccess intentVar | - cb.getCondition().getAChildExpr().(CompileTimeConstantExpr).getIntValue() = - fi.getRequestCode() and - cb.getCondition().getAChildExpr() = ai.getRequestCodeVar() and + cb.getCondition() = ee and + ee.hasOperands(ai.getRequestCodeVar(), cc) and + cc.getIntValue() = fi.getRequestCode() and intentVar.getType() instanceof TypeIntent and - cb.getBasicBlock() = intentVar.(Argument).getAnEnclosingStmt() and + cb.controls(intentVar.getBasicBlock(), true) and src.asExpr() = intentVar ) } diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected index 47f27356d87..05400330dd7 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -8,6 +8,7 @@ edges | FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | | FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | | FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | +| LeakFileActivity2.java:15:13:15:18 | intent : Intent | LeakFileActivity2.java:16:26:16:31 | intent : Intent | | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:20:31:20:43 | intent : Intent | | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | @@ -24,6 +25,7 @@ nodes | FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] | | FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | | FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] | +| LeakFileActivity2.java:15:13:15:18 | intent : Intent | semmle.label | intent : Intent | | LeakFileActivity2.java:16:26:16:31 | intent : Intent | semmle.label | intent : Intent | | LeakFileActivity.java:14:35:14:38 | data : Intent | semmle.label | data : Intent | | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | semmle.label | contentIntent : Intent | @@ -32,5 +34,6 @@ nodes | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | semmle.label | streamsToUpload : Uri | | LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) | #select +| FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:15:13:15:18 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:15:13:15:18 | intent | this user input | | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:16:26:16:31 | intent | this user input | | LeakFileActivity.java:21:58:21:82 | getPath(...) | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:21:58:21:82 | getPath(...) | Leaking arbitrary Android file from $@. | LeakFileActivity.java:14:35:14:38 | data | this user input | From ffdfc0549af3d85309fe0e9988c73c50b863e1f1 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Wed, 6 Oct 2021 12:15:34 +0100 Subject: [PATCH 162/361] Update comment --- .../Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql index 82968d33678..906d3505444 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql @@ -32,7 +32,7 @@ class AndroidFileLeakConfig extends TaintTracking::Configuration { AndroidFileLeakConfig() { this = "AndroidFileLeakConfig" } /** - * Holds if `src` is a read of some Intent-typed method argument guarded by a check like + * Holds if `src` is a read of some Intent-typed variable guarded by a check like * `requestCode == REQUEST_CODE__SELECT_CONTENT_FROM_APPS`, where `requestCode` is the first * argument to `Activity.onActivityResult` and `REQUEST_CODE__SELECT_CONTENT_FROM_APPS` is * any request code in a call to `startActivityForResult(intent, code)`. From f24e310ace2ae0003a65b661158182991db2ef48 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Wed, 6 Oct 2021 12:25:23 +0100 Subject: [PATCH 163/361] Update test expectation details --- .../security/CWE-200/SensitiveAndroidFileLeak.expected | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected index 05400330dd7..472a0cae215 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -6,6 +6,10 @@ edges | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:40:41:40:55 | params : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | | FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | +| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | +| FileService.java:32:13:32:28 | sourceUri : String | FileService.java:35:17:35:25 | sourceUri : String | +| FileService.java:34:20:36:13 | {...} [[]] : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | +| FileService.java:35:17:35:25 | sourceUri : String | FileService.java:34:20:36:13 | {...} [[]] : String | | FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | | FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | | LeakFileActivity2.java:15:13:15:18 | intent : Intent | LeakFileActivity2.java:16:26:16:31 | intent : Intent | @@ -22,6 +26,10 @@ nodes | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | semmle.label | makeParamsToExecute(...) [[]] : String | | FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String | +| FileService.java:32:13:32:28 | sourceUri : String | semmle.label | sourceUri : String | +| FileService.java:34:20:36:13 | new Object[] [[]] : String | semmle.label | new Object[] [[]] : String | +| FileService.java:34:20:36:13 | {...} [[]] : String | semmle.label | {...} [[]] : String | +| FileService.java:35:17:35:25 | sourceUri : String | semmle.label | sourceUri : String | | FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] | | FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | | FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] | @@ -33,6 +41,8 @@ nodes | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | semmle.label | getData(...) : Uri | | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | semmle.label | streamsToUpload : Uri | | LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) | +subpaths +| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | #select | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:15:13:15:18 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:15:13:15:18 | intent | this user input | | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:16:26:16:31 | intent | this user input | From 91d8b3da239622c4d693ce0cad7b5ce051848e52 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Wed, 6 Oct 2021 12:29:44 +0100 Subject: [PATCH 164/361] Sort Intent models --- .../code/java/frameworks/android/Intent.qll | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 50b29e77298..ba23a3516e6 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -143,17 +143,17 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint", "android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint", // currently only the Extras part of the intent is fully modelled - "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value", - "android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;value", "android.content;Intent;false;Intent;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;false;Intent;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", - "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;value", "android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getCharArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getCharSequenceArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getCharSequenceArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getCharSequenceExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getParcelableArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getParcelableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", @@ -167,6 +167,12 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.content;Intent;true;putExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putExtra;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;putExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtras;(Bundle);;Argument[-1];ReturnValue;value", + "android.content;Intent;true;putExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;true;putExtras;(Intent);;Argument[-1];ReturnValue;value", "android.content;Intent;true;putIntegerArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putIntegerArrayListExtra;;;Argument[-1];ReturnValue;value", "android.content;Intent;true;putParcelableArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", @@ -175,12 +181,6 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.content;Intent;true;putStringArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putStringArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putStringArrayListExtra;;;Argument[-1];ReturnValue;value", - "android.content;Intent;true;putExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", - "android.content;Intent;true;putExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", - "android.content;Intent;true;putExtras;(Bundle);;Argument[-1];ReturnValue;value", - "android.content;Intent;true;putExtras;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", - "android.content;Intent;true;putExtras;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", - "android.content;Intent;true;putExtras;(Intent);;Argument[-1];ReturnValue;value", "android.content;Intent;true;replaceExtras;(Bundle);;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;replaceExtras;(Bundle);;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;replaceExtras;(Bundle);;Argument[-1];ReturnValue;value", From 83cbc86f509f863b2765b2cfd29bd7a4f07784e5 Mon Sep 17 00:00:00 2001 From: Henry Mercer <henrymercer@github.com> Date: Tue, 5 Oct 2021 16:33:09 +0100 Subject: [PATCH 165/361] JS: Move `ClassifyFiles.qll` to library pack This allows us to use this library in packs that depend on the `codeql/javascript-all` library pack. --- .../ql/{src => lib/semmle/javascript}/filters/ClassifyFiles.qll | 0 javascript/ql/src/experimental/poi/PoI.qll | 2 +- javascript/ql/src/filters/ClassifyFiles.ql | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename javascript/ql/{src => lib/semmle/javascript}/filters/ClassifyFiles.qll (100%) diff --git a/javascript/ql/src/filters/ClassifyFiles.qll b/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll similarity index 100% rename from javascript/ql/src/filters/ClassifyFiles.qll rename to javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll diff --git a/javascript/ql/src/experimental/poi/PoI.qll b/javascript/ql/src/experimental/poi/PoI.qll index 20eeeee9f79..c51909c5c9e 100644 --- a/javascript/ql/src/experimental/poi/PoI.qll +++ b/javascript/ql/src/experimental/poi/PoI.qll @@ -55,7 +55,7 @@ import javascript private import DataFlow -private import filters.ClassifyFiles +private import semmle.javascript.filters.ClassifyFiles private import semmle.javascript.RestrictedLocations /** diff --git a/javascript/ql/src/filters/ClassifyFiles.ql b/javascript/ql/src/filters/ClassifyFiles.ql index fa7aad41ab4..9100485a6d6 100644 --- a/javascript/ql/src/filters/ClassifyFiles.ql +++ b/javascript/ql/src/filters/ClassifyFiles.ql @@ -8,7 +8,7 @@ */ import javascript -import ClassifyFiles +import semmle.javascript.filters.ClassifyFiles from File f, string category where classify(f, category) From 4be2347a30c2dc5ebe062d6dd6655896cfd77325 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Wed, 6 Oct 2021 16:15:18 +0100 Subject: [PATCH 166/361] Adapt to use the new shared Intent models --- .../code/java/frameworks/android/Intent.qll | 14 ++++- .../CWE/CWE-200/AndroidFileIntentSource.qll | 52 +++++-------------- .../CWE/CWE-200/SensitiveAndroidFileLeak.ql | 8 +++ .../CWE-200/SensitiveAndroidFileLeak.expected | 29 ++++++++--- 4 files changed, 55 insertions(+), 48 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index ba23a3516e6..263ff3f6b1b 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -142,18 +142,25 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.os;Bundle;true;putStringArrayList;;;Argument[1];MapValue of Argument[-1];value", "android.os;Bundle;true;readFromParcel;;;Argument[0];MapKey of Argument[-1];taint", "android.os;Bundle;true;readFromParcel;;;Argument[0];MapValue of Argument[-1];taint", - // currently only the Extras part of the intent is fully modelled + // currently only the Extras part of the intent and the data field are fully modelled "android.content;Intent;false;Intent;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;false;Intent;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", + "android.content;Intent;false;Intent;(String,Uri);;Argument[1];MapValue of SyntheticField[android.content.Intent.data] of Argument[-1];value", + "android.content;Intent;false;Intent;(String,Uri,Context,Class);;Argument[1];MapValue of SyntheticField[android.content.Intent.data] of Argument[-1];value", "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value", "android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;value", + "android.content;Intent;false;createChooser;;;Argument[0..2];MapValue of SyntheticField[android.content.Intent.extras] of ReturnValue;value", "android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getByteArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getCharArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getCharSequenceArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getCharSequenceArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getCharSequenceExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getData;;;SyntheticField[android.content.Intent.data] of Argument[-1];ReturnValue;value", + "android.content;Intent;true;getDataString;;;SyntheticField[android.content.Intent.data] of Argument[-1];ReturnValue;taint", "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;false;getIntent;();;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint", + "android.content;Intent;false;getIntentOld;();;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint", "android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getParcelableArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getParcelableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", @@ -161,6 +168,7 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.content;Intent;true;getStringArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getStringArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getStringExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", + "android.content;Intent;false;parseUri;();;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint", "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;value", @@ -192,9 +200,13 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.content;Intent;true;setClassName;;;Argument[-1];ReturnValue;value", "android.content;Intent;true;setComponent;;;Argument[-1];ReturnValue;value", "android.content;Intent;true;setData;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setData;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];value", "android.content;Intent;true;setDataAndNormalize;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setDataAndNormalize;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];value", "android.content;Intent;true;setDataAndType;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setDataAndType;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];value", "android.content;Intent;true;setDataAndTypeAndNormalize;;;Argument[-1];ReturnValue;value", + "android.content;Intent;true;setDataAndTypeAndNormalize;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];value", "android.content;Intent;true;setFlags;;;Argument[-1];ReturnValue;value", "android.content;Intent;true;setIdentifier;;;Argument[-1];ReturnValue;value", "android.content;Intent;true;setPackage;;;Argument[-1];ReturnValue;value", diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll index 8ef29014c8e..88e554e6a7c 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll @@ -28,45 +28,6 @@ class GetContentIntent extends ClassInstanceExpr { } } -/** Android intent data model in the new CSV format. */ -private class AndroidIntentDataModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;taint", - "android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;taint", - "android.content;Intent;true;createChooser;;;Argument[0];ReturnValue;taint", - "android.content;Intent;true;getData;;;Argument[-1];ReturnValue;taint", - "android.content;Intent;true;getDataString;;;Argument[-1];ReturnValue;taint", - "android.content;Intent;true;getExtras;;;Argument[-1];ReturnValue;taint", - "android.content;Intent;true;getIntent;;;Argument[-1];ReturnValue;taint", - "android.content;Intent;true;get" + - [ - "ParcelableArray", "ParcelableArrayList", "Parcelable", "Serializable", "StringArray", - "StringArrayList", "String" - ] + "Extra;;;Argument[-1..1];ReturnValue;taint", - "android.content;Intent;true;put" + - [ - "", "CharSequenceArrayList", "IntegerArrayList", "ParcelableArrayList", - "StringArrayList" - ] + "Extra;;;Argument[1];Argument[-1];taint", - "android.content;Intent;true;putExtras;;;Argument[1];Argument[-1];taint", - "android.content;Intent;true;setData;;;Argument[0];ReturnValue;taint", - "android.content;Intent;true;setDataAndType;;;Argument[-1];ReturnValue;taint", - "android.content;Intent;true;setFlags;;;Argument[-1];ReturnValue;taint", - "android.content;Intent;true;setType;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getEncodedPath;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getEncodedQuery;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getLastPathSegment;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getPath;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getPathSegments;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getQuery;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getQueryParameter;;;Argument[-1];ReturnValue;taint", - "android.net;Uri;true;getQueryParameters;;;Argument[-1];ReturnValue;taint" - ] - } -} - /** Taint configuration for getting content intent. */ class GetContentIntentConfig extends TaintTracking2::Configuration { GetContentIntentConfig() { this = "GetContentIntentConfig" } @@ -80,6 +41,19 @@ class GetContentIntentConfig extends TaintTracking2::Configuration { ma.getMethod() instanceof StartActivityForResultMethod and sink.asExpr() = ma.getArgument(0) ) } + + override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content content) { + super.allowImplicitRead(node, content) + or + // Allow the wrapped intent created by Intent.getChooser to be consumed + // by at the sink: + isSink(node) and + ( + content.(DataFlow::SyntheticFieldContent).getField() = "android.content.Intent.extras" + or + content instanceof DataFlow::MapValueContent + ) + } } /** Android `Intent` input to request file loading. */ diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql index 906d3505444..d84fe2453b6 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql @@ -14,6 +14,8 @@ import semmle.code.java.controlflow.Guards import AndroidFileIntentSink import AndroidFileIntentSource import DataFlow::PathGraph +// For readStep, to implement `isAdditionalTaintStep` +private import semmle.code.java.dataflow.internal.DataFlowPrivate private class StartsWithSanitizer extends DataFlow::BarrierGuard { StartsWithSanitizer() { this.(MethodAccess).getMethod().hasName("startsWith") } @@ -64,6 +66,7 @@ class AndroidFileLeakConfig extends TaintTracking::Configuration { ) or exists(MethodAccess csma, ServiceOnStartCommandMethod ssm, ClassInstanceExpr ce | + // An intent passed to startService will later be passed to the onStartCommand event of the corresponding service csma.getMethod() instanceof ContextStartServiceMethod and ce.getConstructedType() instanceof TypeIntent and // Intent intent = new Intent(context, FileUploader.class); ce.getArgument(1).(TypeLiteral).getReferencedType() = ssm.getDeclaringType() and @@ -71,6 +74,11 @@ class AndroidFileLeakConfig extends TaintTracking::Configuration { prev.asExpr() = csma.getArgument(0) and succ.asParameter() = ssm.getParameter(0) // public int onStartCommand(Intent intent, int flags, int startId) {...} in FileUploader ) + or + // When a whole Intent is tainted (e.g., due to this Configuration's source), treat its fields as tainted + readStep(prev, + any(DataFlow::SyntheticFieldContent c | c.getField().matches("android.content.Intent.%")), + succ) } override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected index 472a0cae215..3ad57e266c5 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -1,14 +1,20 @@ edges | FileService.java:20:31:20:43 | intent : Intent | FileService.java:21:28:21:33 | intent : Intent | | FileService.java:20:31:20:43 | intent : Intent | FileService.java:25:42:25:50 | localPath : String | -| FileService.java:21:28:21:33 | intent : Intent | FileService.java:21:28:21:64 | getStringExtra(...) : String | -| FileService.java:21:28:21:64 | getStringExtra(...) : String | FileService.java:25:42:25:50 | localPath : String | +| FileService.java:21:28:21:33 | intent : Intent | FileService.java:21:28:21:64 | getStringExtra(...) : Object | +| FileService.java:21:28:21:64 | getStringExtra(...) : Object | FileService.java:25:42:25:50 | localPath : Object | | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:40:41:40:55 | params : Object[] | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | +| FileService.java:25:42:25:50 | localPath : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | +| FileService.java:25:42:25:50 | localPath : Object | FileService.java:32:13:32:28 | sourceUri : Object | | FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | | FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | +| FileService.java:32:13:32:28 | sourceUri : Object | FileService.java:35:17:35:25 | sourceUri : Object | | FileService.java:32:13:32:28 | sourceUri : String | FileService.java:35:17:35:25 | sourceUri : String | +| FileService.java:34:20:36:13 | {...} [[]] : Object | FileService.java:34:20:36:13 | new Object[] [[]] : Object | | FileService.java:34:20:36:13 | {...} [[]] : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | +| FileService.java:35:17:35:25 | sourceUri : Object | FileService.java:34:20:36:13 | {...} [[]] : Object | | FileService.java:35:17:35:25 | sourceUri : String | FileService.java:34:20:36:13 | {...} [[]] : String | | FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | | FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | @@ -16,19 +22,25 @@ edges | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:20:31:20:43 | intent : Intent | | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | -| LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | -| LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | -| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | LeakFileActivity.java:21:58:21:82 | getPath(...) | +| LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | LeakFileActivity.java:19:31:19:53 | getData(...) : Object | +| LeakFileActivity.java:19:31:19:53 | getData(...) : Object | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Object | +| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Object | LeakFileActivity.java:21:58:21:82 | getPath(...) | nodes | FileService.java:20:31:20:43 | intent : Intent | semmle.label | intent : Intent | | FileService.java:21:28:21:33 | intent : Intent | semmle.label | intent : Intent | -| FileService.java:21:28:21:64 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | +| FileService.java:21:28:21:64 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | semmle.label | makeParamsToExecute(...) [[]] : Object | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | semmle.label | makeParamsToExecute(...) [[]] : String | +| FileService.java:25:42:25:50 | localPath : Object | semmle.label | localPath : Object | | FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String | +| FileService.java:32:13:32:28 | sourceUri : Object | semmle.label | sourceUri : Object | | FileService.java:32:13:32:28 | sourceUri : String | semmle.label | sourceUri : String | +| FileService.java:34:20:36:13 | new Object[] [[]] : Object | semmle.label | new Object[] [[]] : Object | | FileService.java:34:20:36:13 | new Object[] [[]] : String | semmle.label | new Object[] [[]] : String | +| FileService.java:34:20:36:13 | {...} [[]] : Object | semmle.label | {...} [[]] : Object | | FileService.java:34:20:36:13 | {...} [[]] : String | semmle.label | {...} [[]] : String | +| FileService.java:35:17:35:25 | sourceUri : Object | semmle.label | sourceUri : Object | | FileService.java:35:17:35:25 | sourceUri : String | semmle.label | sourceUri : String | | FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] | | FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | @@ -38,10 +50,11 @@ nodes | LeakFileActivity.java:14:35:14:38 | data : Intent | semmle.label | data : Intent | | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | semmle.label | contentIntent : Intent | | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | semmle.label | contentIntent : Intent | -| LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | semmle.label | getData(...) : Uri | -| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | semmle.label | streamsToUpload : Uri | +| LeakFileActivity.java:19:31:19:53 | getData(...) : Object | semmle.label | getData(...) : Object | +| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Object | semmle.label | streamsToUpload : Object | | LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) | subpaths +| FileService.java:25:42:25:50 | localPath : Object | FileService.java:32:13:32:28 | sourceUri : Object | FileService.java:34:20:36:13 | new Object[] [[]] : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | | FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | #select | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:15:13:15:18 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:15:13:15:18 | intent | this user input | From b33daa3d3a8260cf69682c7d8eb4664ce61c19cd Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Wed, 6 Oct 2021 17:09:47 +0100 Subject: [PATCH 167/361] Update Intent model tests, and fix models where required --- .../code/java/frameworks/android/Intent.qll | 10 +- .../frameworks/android/intent/Test.java | 102 ++++++++++++++++++ 2 files changed, 107 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 263ff3f6b1b..796a52f3696 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -145,8 +145,8 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { // currently only the Extras part of the intent and the data field are fully modelled "android.content;Intent;false;Intent;(Intent);;MapKey of SyntheticField[android.content.Intent.extras] of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;false;Intent;(Intent);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", - "android.content;Intent;false;Intent;(String,Uri);;Argument[1];MapValue of SyntheticField[android.content.Intent.data] of Argument[-1];value", - "android.content;Intent;false;Intent;(String,Uri,Context,Class);;Argument[1];MapValue of SyntheticField[android.content.Intent.data] of Argument[-1];value", + "android.content;Intent;false;Intent;(String,Uri);;Argument[1];SyntheticField[android.content.Intent.data] of Argument[-1];value", + "android.content;Intent;false;Intent;(String,Uri,Context,Class);;Argument[1];SyntheticField[android.content.Intent.data] of Argument[-1];value", "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value", "android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;value", "android.content;Intent;false;createChooser;;;Argument[0..2];MapValue of SyntheticField[android.content.Intent.extras] of ReturnValue;value", @@ -159,8 +159,8 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.content;Intent;true;getData;;;SyntheticField[android.content.Intent.data] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getDataString;;;SyntheticField[android.content.Intent.data] of Argument[-1];ReturnValue;taint", "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", - "android.content;Intent;false;getIntent;();;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint", - "android.content;Intent;false;getIntentOld;();;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint", + "android.content;Intent;false;getIntent;;;Argument[0];SyntheticField[android.content.Intent.data] of ReturnValue;taint", + "android.content;Intent;false;getIntentOld;;;Argument[0];SyntheticField[android.content.Intent.data] of ReturnValue;taint", "android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getParcelableArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getParcelableExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", @@ -168,7 +168,7 @@ private class IntentBundleFlowSteps extends SummaryModelCsv { "android.content;Intent;true;getStringArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getStringArrayListExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", "android.content;Intent;true;getStringExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value", - "android.content;Intent;false;parseUri;();;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint", + "android.content;Intent;false;parseUri;;;Argument[0];SyntheticField[android.content.Intent.data] of ReturnValue;taint", "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[1];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value", "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;value", diff --git a/java/ql/test/library-tests/frameworks/android/intent/Test.java b/java/ql/test/library-tests/frameworks/android/intent/Test.java index cdee36af212..9172c4c19ad 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/Test.java +++ b/java/ql/test/library-tests/frameworks/android/intent/Test.java @@ -2,6 +2,8 @@ package generatedtest; import android.content.Context; import android.content.Intent; +import android.content.IntentSender; +import android.net.Uri; import android.os.BaseBundle; import android.os.Bundle; import android.os.IBinder; @@ -21,10 +23,12 @@ public class Test { String getMapKey(BaseBundle b) { return b.keySet().iterator().next(); } Object getMapValue(BaseBundle b) { return null; } Intent newWithIntent_extras(Bundle b) { return null; } + Intent newWithIntent_data(Uri data) { return new Intent("title", data); } Bundle newBundleWithMapKey(String k) { Bundle b = new Bundle(); b.putInt(k, 0); return b; } PersistableBundle newPersistableBundleWithMapKey(String k) { PersistableBundle b = new PersistableBundle(); b.putInt(k, 0); return b; } Bundle newBundleWithMapValue(Object element) { return null; } PersistableBundle newPersistableBundleWithMapValue(Object element) { return null; } + Uri getData(Intent intent) { return intent.getData(); } <T> T source() { return null; } void sink(Object o) { } @@ -44,6 +48,20 @@ public class Test { out = new Intent(in); sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow } + { + // "android.content;Intent;false;Intent;(String,Uri);;Argument[1];SyntheticField[android.content.Intent.data] of Argument[-1];value" + Intent out = null; + Uri in = (Uri)source(); + out = new Intent(null, in); + sink(getData(out)); // $ hasValueFlow + } + { + // "android.content;Intent;false;Intent;(String,Uri,Context,Class);;Argument[1];SyntheticField[android.content.Intent.data] of Argument[-1];value" + Intent out = null; + Uri in = (Uri)source(); + out = new Intent(null, in, null, null); + sink(getData(out)); // $ hasValueFlow + } { // "android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;value" Intent out = null; @@ -58,6 +76,27 @@ public class Test { out = in.addFlags(0); sink(out); // $ hasValueFlow } + { + // "android.content;Intent;false;createChooser;;;Argument[0..2];MapValue of SyntheticField[android.content.Intent.extras] of ReturnValue;value" + Intent out = null; + CharSequence in = (CharSequence)source(); + out = Intent.createChooser(null, in, null); + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow + } + { + // "android.content;Intent;false;createChooser;;;Argument[0..2];MapValue of SyntheticField[android.content.Intent.extras] of ReturnValue;value" + Intent out = null; + IntentSender in = (IntentSender)source(); + out = Intent.createChooser(null, null, in); + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow + } + { + // "android.content;Intent;false;createChooser;;;Argument[0..2];MapValue of SyntheticField[android.content.Intent.extras] of ReturnValue;value" + Intent out = null; + Intent in = (Intent)source(); + out = Intent.createChooser(in, null, null); + sink(getMapValue(getIntent_extras(out))); // $ hasValueFlow + } { // "android.content;Intent;true;getBundleExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Bundle out = null; @@ -100,6 +139,20 @@ public class Test { out = in.getCharSequenceExtra(null); sink(out); // $ hasValueFlow } + { + // "android.content;Intent;true;getData;;;SyntheticField[android.content.Intent.data] of Argument[-1];ReturnValue;value" + Uri out = null; + Intent in = (Intent)newWithIntent_data(source()); + out = in.getData(); + sink(out); // $ hasValueFlow + } + { + // "android.content;Intent;true;getDataString;;;SyntheticField[android.content.Intent.data] of Argument[-1];ReturnValue;taint" + String out = null; + Intent in = (Intent)newWithIntent_data(source()); + out = in.getDataString(); + sink(out); // $ hasTaintFlow + } { // "android.content;Intent;true;getExtras;();;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Bundle out = null; @@ -107,6 +160,20 @@ public class Test { out = in.getExtras(); sink(out); // $ hasValueFlow } + { + // "android.content;Intent;false;getIntent;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint" + Intent out = null; + String in = (String)source(); + out = Intent.getIntent(in); + sink(out.getData()); // $ hasTaintFlow + } + { + // "android.content;Intent;false;getIntentOld;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint" + Intent out = null; + String in = (String)source(); + out = Intent.getIntentOld(in); + sink(out.getData()); // $ hasTaintFlow + } { // "android.content;Intent;true;getParcelableArrayExtra;(String);;MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value" Parcelable[] out = null; @@ -156,6 +223,13 @@ public class Test { out = in.getStringExtra(null); sink(out); // $ hasValueFlow } + { + // "android.content;Intent;false;parseUri;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];taint" + Intent out = null; + String in = (String)source(); + out = Intent.parseUri(in, 0); + sink(out.getData()); // $ hasTaintFlow + } { // "android.content;Intent;true;putCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;value" Intent out = null; @@ -863,6 +937,34 @@ public class Test { out = in.setData(null); sink(out); // $ hasValueFlow } + { + // "android.content;Intent;true;setData;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];value", + Uri in = (Uri)source(); + Intent instance = new Intent(); + instance.setData(in); + sink(instance.getData()); // $ hasValueFlow + } + { + // "android.content;Intent;true;setDataAndNormalize;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];value", + Uri in = (Uri)source(); + Intent instance = new Intent(); + instance.setDataAndNormalize(in); + sink(instance.getData()); // $ hasValueFlow + } + { + // "android.content;Intent;true;setDataAndType;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];value", + Uri in = (Uri)source(); + Intent instance = new Intent(); + instance.setDataAndType(in, null); + sink(instance.getData()); // $ hasValueFlow + } + { + // "android.content;Intent;true;setDataAndTypeAndNormalize;;;Argument[0];SyntheticField[android.content.Intent.data] of Argument[-1];value", + Uri in = (Uri)source(); + Intent instance = new Intent(); + instance.setDataAndTypeAndNormalize(in, null); + sink(instance.getData()); // $ hasValueFlow + } { // "android.content;Intent;true;setDataAndNormalize;;;Argument[-1];ReturnValue;value" Intent out = null; From f88c8a64a1d3c49244bb8668dc16a703192842e6 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Wed, 6 Oct 2021 17:37:21 +0100 Subject: [PATCH 168/361] Copyedit --- .../CWE/CWE-200/AndroidFileIntentSink.qll | 8 +++---- .../CWE/CWE-200/AndroidFileIntentSource.qll | 22 +++++-------------- .../CWE-200/SensitiveAndroidFileLeak.qhelp | 12 +++++----- .../CWE/CWE-200/SensitiveAndroidFileLeak.ql | 17 +++++++------- 4 files changed, 24 insertions(+), 35 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll index c3f5eebccc4..597590dbaa1 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSink.qll @@ -19,7 +19,7 @@ class AsyncTask extends RefType { AsyncTask() { this.hasQualifiedName("android.os", "AsyncTask") } } -/** The `execute` or `executeOnExecutor` method of Android `AsyncTask`. */ +/** The `execute` or `executeOnExecutor` method of Android's `AsyncTask` class. */ class ExecuteAsyncTaskMethod extends Method { int paramIndex; @@ -35,7 +35,7 @@ class ExecuteAsyncTaskMethod extends Method { int getParamIndex() { result = paramIndex } } -/** The `doInBackground` method of Android `AsyncTask`. */ +/** The `doInBackground` method of Android's `AsyncTask` class. */ class AsyncTaskRunInBackgroundMethod extends Method { AsyncTaskRunInBackgroundMethod() { this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and @@ -43,7 +43,7 @@ class AsyncTaskRunInBackgroundMethod extends Method { } } -/** The service start method of Android context. */ +/** The service start method of Android's `Context` class. */ class ContextStartServiceMethod extends Method { ContextStartServiceMethod() { this.getName() = ["startService", "startForegroundService"] and @@ -51,7 +51,7 @@ class ContextStartServiceMethod extends Method { } } -/** The `onStartCommand` method of Android service. */ +/** The `onStartCommand` method of Android's `Service` class. */ class ServiceOnStartCommandMethod extends Method { ServiceOnStartCommandMethod() { this.hasName("onStartCommand") and diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll index 88e554e6a7c..22935997afe 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll @@ -5,7 +5,7 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.TaintTracking2 import semmle.code.java.frameworks.android.Android -/** The `startActivityForResult` method of Android `Activity`. */ +/** The `startActivityForResult` method of Android's `Activity` class. */ class StartActivityForResultMethod extends Method { StartActivityForResultMethod() { this.getDeclaringType().getASupertype*() instanceof AndroidActivity and @@ -13,7 +13,7 @@ class StartActivityForResultMethod extends Method { } } -/** Android class instance of `GET_CONTENT` intent. */ +/** An instance of `android.content.Intent` constructed passing `GET_CONTENT` to the constructor. */ class GetContentIntent extends ClassInstanceExpr { GetContentIntent() { this.getConstructedType() instanceof TypeIntent and @@ -28,7 +28,7 @@ class GetContentIntent extends ClassInstanceExpr { } } -/** Taint configuration for getting content intent. */ +/** Taint configuration that identifies `GET_CONTENT` `Intent` instances passed to `startActivityForResult`. */ class GetContentIntentConfig extends TaintTracking2::Configuration { GetContentIntentConfig() { this = "GetContentIntentConfig" } @@ -56,8 +56,8 @@ class GetContentIntentConfig extends TaintTracking2::Configuration { } } -/** Android `Intent` input to request file loading. */ -class AndroidFileIntentInput extends LocalUserInput { +/** A `GET_CONTENT` `Intent` instances that is passed to `startActivityForResult`. */ +class AndroidFileIntentInput extends DataFlow::Node { MethodAccess ma; AndroidFileIntentInput() { @@ -68,7 +68,7 @@ class AndroidFileIntentInput extends LocalUserInput { ) } - /** The request code identifying a specific intent, which is to be matched in `onActivityResult()`. */ + /** The request code passed to `startActivityForResult`, which is to be matched in `onActivityResult()`. */ int getRequestCode() { result = ma.getArgument(1).(CompileTimeConstantExpr).getIntValue() } } @@ -79,13 +79,3 @@ class OnActivityForResultMethod extends Method { this.getName() = "onActivityResult" } } - -/** Input of Android activity result from the same application or another application. */ -class AndroidActivityResultInput extends DataFlow::Node { - OnActivityForResultMethod m; - - AndroidActivityResultInput() { this.asExpr() = m.getParameter(2).getAnAccess() } - - /** The request code matching a specific intent request. */ - VarAccess getRequestCodeVar() { result = m.getParameter(0).getAnAccess() } -} diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.qhelp b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.qhelp index 7b6e60d7ca0..ca4a7e668ea 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.qhelp @@ -5,22 +5,22 @@ <overview> <p>The Android API allows to start an activity in another mobile application and receive a result back. When starting an activity to retrieve a file from another application, missing input validation can -lead to leaking of sensitive configuration file or user data because the intent is from the application -itself that is allowed to access its protected data therefore bypassing the access control. +lead to leaking of sensitive configuration file or user data because the intent could refer to paths +which are accessible to the receiver application, but are intended to be application-private. </p> </overview> <recommendation> <p> -When loading file data from an activity of another application, validate that the file path is not its own +When loading file data from an activity of another application, validate that the file path is not the receiver's protected directory, which is a subdirectory of the Android application directory <code>/data/data/</code>. </p> </recommendation> <example> <p> -The following examples show the bad situation and the good situation respectively. In bad situation, a -file is loaded without path validation. In good situation, a file is loaded with path validation. +The following examples show a bad situation and a good situation respectively. In the bad situation, a +file is loaded without path validation. In the good situation, a file is loaded with path validation. </p> <sample src="LoadFileFromAppActivity.java" /> </example> @@ -33,6 +33,6 @@ Google: <li> CVE: <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-32695">CVE-2021-32695: File Sharing Flow Initiated by a Victim Leaks Sensitive Data to a Malicious App</a>. -</li> +</li> </references> </qhelp> \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql index d84fe2453b6..e392446c188 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql @@ -1,6 +1,6 @@ /** * @name Leaking sensitive Android file - * @description Getting file intent from user input without path validation could leak arbitrary + * @description Using a path specified in an Android Intent without validation could leak arbitrary * Android configuration file and sensitive user data. * @kind path-problem * @id java/sensitive-android-file-leak @@ -35,18 +35,17 @@ class AndroidFileLeakConfig extends TaintTracking::Configuration { /** * Holds if `src` is a read of some Intent-typed variable guarded by a check like - * `requestCode == REQUEST_CODE__SELECT_CONTENT_FROM_APPS`, where `requestCode` is the first - * argument to `Activity.onActivityResult` and `REQUEST_CODE__SELECT_CONTENT_FROM_APPS` is - * any request code in a call to `startActivityForResult(intent, code)`. + * `requestCode == someCode`, where `requestCode` is the first + * argument to `Activity.onActivityResult` and `someCode` is + * any request code used in a call to `startActivityForResult(intent, someCode)`. */ override predicate isSource(DataFlow::Node src) { exists( - AndroidActivityResultInput ai, AndroidFileIntentInput fi, ConditionBlock cb, EQExpr ee, - CompileTimeConstantExpr cc, VarAccess intentVar + OnActivityForResultMethod oafr, ConditionBlock cb, CompileTimeConstantExpr cc, + VarAccess intentVar | - cb.getCondition() = ee and - ee.hasOperands(ai.getRequestCodeVar(), cc) and - cc.getIntValue() = fi.getRequestCode() and + cb.getCondition().(EQExpr).hasOperands(oafr.getParameter(0).getAnAccess(), cc) and + cc.getIntValue() = any(AndroidFileIntentInput fi).getRequestCode() and intentVar.getType() instanceof TypeIntent and cb.controls(intentVar.getBasicBlock(), true) and src.asExpr() = intentVar From e2b1f6ac50c40971829fbc719be41e8114119221 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg <aeisenberg@github.com> Date: Wed, 6 Oct 2021 14:29:55 -0700 Subject: [PATCH 169/361] Packaging: Add library flag to upgrades packs This flag was missing. It should be there. Otherwise, this pack cannot be built. --- cpp/upgrades/qlpack.yml | 1 + csharp/upgrades/qlpack.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/cpp/upgrades/qlpack.yml b/cpp/upgrades/qlpack.yml index acc305bb6a2..7f18cb54c8e 100644 --- a/cpp/upgrades/qlpack.yml +++ b/cpp/upgrades/qlpack.yml @@ -1,3 +1,4 @@ name: codeql/cpp-upgrades upgrades: . version: 0.0.2 +library: true diff --git a/csharp/upgrades/qlpack.yml b/csharp/upgrades/qlpack.yml index 9c3e8f6520a..1fb67a8785a 100644 --- a/csharp/upgrades/qlpack.yml +++ b/csharp/upgrades/qlpack.yml @@ -1,3 +1,4 @@ name: codeql/csharp-upgrades upgrades: . version: 0.0.2 +library: true From f651bc3668e8cbc28b473f52d94daec21c725051 Mon Sep 17 00:00:00 2001 From: Sebastian Bauersfeld <sebastian@semmle.com> Date: Thu, 7 Oct 2021 12:45:21 +0700 Subject: [PATCH 170/361] Adjust locations of results in JSP files. This is necessary due to known limitations in VSCode which cause locations with zero character indices to be mapped to invalid ranges. This is hopefully a temporary workaround until this problem has been properly addressed. --- java/ql/lib/semmle/code/SMAP.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/SMAP.qll b/java/ql/lib/semmle/code/SMAP.qll index 006f5ad5e38..575d54f92de 100644 --- a/java/ql/lib/semmle/code/SMAP.qll +++ b/java/ql/lib/semmle/code/SMAP.qll @@ -52,6 +52,6 @@ predicate hasSmapLocationInfo( smap(inputFile, isl, outputFile, osl) and smap(inputFile, iel - 1, outputFile, oel) and isc = 1 and - iec = 0 + iec = 1 ) } From b7448d55ed65634e28786f44ee1a514687083b82 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Thu, 7 Oct 2021 11:20:19 +0100 Subject: [PATCH 171/361] Introduce TaintInheritingContent instead of using parts of DataFlowPrivate --- .../lib/semmle/code/java/dataflow/FlowSteps.qll | 16 ++++++++++++++++ .../java/dataflow/internal/TaintTrackingUtil.qll | 6 +++++- .../code/java/frameworks/android/Intent.qll | 9 +++++++++ .../CWE/CWE-200/SensitiveAndroidFileLeak.ql | 7 ------- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll index 0017582c0d9..ae9c88fb118 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll @@ -103,3 +103,19 @@ private class NumberTaintPreservingCallable extends TaintPreservingCallable { override predicate returnsTaintFrom(int arg) { arg = argument } } + +/** + * A `Content` that should be implicitly regarded as tainted whenever an object with such `Content` + * is itself tainted. + * + * For example, if we had a type `class Container { Contained field; }`, then by default a tainted + * `Container` and a `Container` with a tainted `Contained` stored in its `field` are distinct. + * + * If `any(DataFlow::FieldContent fc | fc.getField().hasQualifiedName("Container", "field"))` was + * included in this type however, then a tainted `Container` would imply that its `field` is also + * tainted (but not vice versa). + * + * Note that `TaintTracking::Configuration` applies this behaviour by default to array, collection, + * map-key and map-value content, so that e.g. a tainted `Map` is assumed to have tainted keys and values. + */ +abstract class TaintInheritingContent extends DataFlow::Content { } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index 58ecc4c0a01..569c7cef3c5 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -83,7 +83,11 @@ private module Cached { not sink.getTypeBound() instanceof PrimitiveType and not sink.getTypeBound() instanceof BoxedType and not sink.getTypeBound() instanceof NumberType and - containerContent(f) + ( + containerContent(f) + or + f instanceof TaintInheritingContent + ) ) or FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 796a52f3696..f3a981cebc5 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -1,4 +1,5 @@ import java +private import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.FlowSteps import semmle.code.java.dataflow.ExternalFlow @@ -54,6 +55,14 @@ class BundleGetterMethod extends Method, TaintPreservingCallable { override predicate returnsTaintFrom(int arg) { arg = -1 } } +/** + * Specifies that if an `Intent` is tainted, then so are its synthetic fields. + */ +private class IntentFieldsInheritTaint extends DataFlow::SyntheticFieldContent, + TaintInheritingContent { + IntentFieldsInheritTaint() { this.getField().matches("android.content.Intent.%") } +} + private class IntentBundleFlowSteps extends SummaryModelCsv { override predicate row(string row) { row = diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql index e392446c188..6cc6c09be87 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql @@ -14,8 +14,6 @@ import semmle.code.java.controlflow.Guards import AndroidFileIntentSink import AndroidFileIntentSource import DataFlow::PathGraph -// For readStep, to implement `isAdditionalTaintStep` -private import semmle.code.java.dataflow.internal.DataFlowPrivate private class StartsWithSanitizer extends DataFlow::BarrierGuard { StartsWithSanitizer() { this.(MethodAccess).getMethod().hasName("startsWith") } @@ -73,11 +71,6 @@ class AndroidFileLeakConfig extends TaintTracking::Configuration { prev.asExpr() = csma.getArgument(0) and succ.asParameter() = ssm.getParameter(0) // public int onStartCommand(Intent intent, int flags, int startId) {...} in FileUploader ) - or - // When a whole Intent is tainted (e.g., due to this Configuration's source), treat its fields as tainted - readStep(prev, - any(DataFlow::SyntheticFieldContent c | c.getField().matches("android.content.Intent.%")), - succ) } override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { From fc69acee46c1ce18d1545115e3e6ab2b8d20b591 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Wed, 6 Oct 2021 13:34:46 +0200 Subject: [PATCH 172/361] Java: Add test. --- .../FlowTestCaseSupportMethods.qll | 30 ++ java/ql/test/TestUtilities/InlineFlowTest.qll | 21 +- .../library-tests/frameworks/stream/Test.java | 475 ++++++++++++++++++ .../frameworks/stream/test.expected | 0 .../library-tests/frameworks/stream/test.ql | 12 + 5 files changed, 530 insertions(+), 8 deletions(-) create mode 100644 java/ql/test/library-tests/frameworks/stream/Test.java create mode 100644 java/ql/test/library-tests/frameworks/stream/test.expected create mode 100644 java/ql/test/library-tests/frameworks/stream/test.ql diff --git a/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseSupportMethods.qll index 1e6c1bcc063..89cf470b4a5 100644 --- a/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseSupportMethods.qll @@ -217,6 +217,22 @@ private class EnumerationGetMethod extends GetMethod { override string getCall(string arg) { result = "getElement(" + arg + ")" } } +private class StreamGetMethod extends GetMethod { + StreamGetMethod() { this = "streamgetmethod" } + + override predicate appliesTo(Type t, Content c) { + t.(RefType).getASourceSupertype*().hasQualifiedName("java.util.stream", "BaseStream") and + c instanceof CollectionContent + } + + override string getDefinition() { + result = "<T> T getElement(BaseStream<T,?> s) { return s.iterator().next(); }" + } + + bindingset[arg] + override string getCall(string arg) { result = "getElement(" + arg + ")" } +} + private class OptionalGetMethod extends GetMethod { OptionalGetMethod() { this = "optionalgetmethod" } @@ -392,6 +408,20 @@ private class IteratorGenMethod extends GenMethod { override string getCall(string arg) { result = "List.of(" + arg + ").iterator()" } } +private class StreamGenMethod extends GenMethod { + StreamGenMethod() { this = "streamgenmethod" } + + override predicate appliesTo(Type t, Content c) { + exists(GenericType op | op.hasQualifiedName("java.util.stream", ["BaseStream", "Stream"]) | + op.getAParameterizedType().getASupertype*() = t + ) and + c instanceof CollectionContent + } + + bindingset[arg] + override string getCall(string arg) { result = "Stream.of(" + arg + ")" } +} + private class OptionalGenMethod extends GenMethod { OptionalGenMethod() { this = "optionalgenmethod" } diff --git a/java/ql/test/TestUtilities/InlineFlowTest.qll b/java/ql/test/TestUtilities/InlineFlowTest.qll index 1ed61182260..e6a0a551d15 100644 --- a/java/ql/test/TestUtilities/InlineFlowTest.qll +++ b/java/ql/test/TestUtilities/InlineFlowTest.qll @@ -43,12 +43,14 @@ import semmle.code.java.dataflow.ExternalFlow import semmle.code.java.dataflow.TaintTracking import TestUtilities.InlineExpectationsTest +private predicate defaultSource(DataFlow::Node src) { + src.asExpr().(MethodAccess).getMethod().getName() = ["source", "taint"] +} + class DefaultValueFlowConf extends DataFlow::Configuration { DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" } - override predicate isSource(DataFlow::Node n) { - n.asExpr().(MethodAccess).getMethod().getName() = ["source", "taint"] - } + override predicate isSource(DataFlow::Node n) { defaultSource(n) } override predicate isSink(DataFlow::Node n) { exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument()) @@ -60,9 +62,7 @@ class DefaultValueFlowConf extends DataFlow::Configuration { class DefaultTaintFlowConf extends TaintTracking::Configuration { DefaultTaintFlowConf() { this = "qltest:defaultTaintFlowConf" } - override predicate isSource(DataFlow::Node n) { - n.asExpr().(MethodAccess).getMethod().getName() = ["source", "taint"] - } + override predicate isSource(DataFlow::Node n) { defaultSource(n) } override predicate isSink(DataFlow::Node n) { exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument()) @@ -71,6 +71,11 @@ class DefaultTaintFlowConf extends TaintTracking::Configuration { override int fieldFlowBranchLimit() { result = 1000 } } +private string getSourceArgString(DataFlow::Node src) { + defaultSource(src) and + src.asExpr().(MethodAccess).getAnArgument().(StringLiteral).getValue() = result +} + class InlineFlowTest extends InlineExpectationsTest { InlineFlowTest() { this = "HasFlowTest" } @@ -81,7 +86,7 @@ class InlineFlowTest extends InlineExpectationsTest { exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) | sink.getLocation() = location and element = sink.toString() and - value = "" + if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" ) or tag = "hasTaintFlow" and @@ -90,7 +95,7 @@ class InlineFlowTest extends InlineExpectationsTest { | sink.getLocation() = location and element = sink.toString() and - value = "" + if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" ) } diff --git a/java/ql/test/library-tests/frameworks/stream/Test.java b/java/ql/test/library-tests/frameworks/stream/Test.java new file mode 100644 index 00000000000..040fce0158e --- /dev/null +++ b/java/ql/test/library-tests/frameworks/stream/Test.java @@ -0,0 +1,475 @@ +package generatedtest; + +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.stream.BaseStream; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; + +public class Test { + + <T> T getArrayElement(T[] array) { return array[0]; } + <T> T getElement(BaseStream<T,?> s) { return s.iterator().next(); } + <T> T getElement(Iterable<T> it) { return it.iterator().next(); } + <T> T getElement(Iterator<T> it) { return it.next(); } + <T> T getElement(Optional<T> o) { return o.get(); } + <T> T getElementSpliterator(Spliterator<T> o) { return null; } + Object source(String tag) { return null; } + void sink(Object o) { } + + public void test() throws Exception { + + // *** Generated *** + { + // "java.util.stream;BaseStream;true;iterator;();;Element of Argument[-1];Element of ReturnValue;value" + Iterator out = null; + BaseStream in = (BaseStream)Stream.of(source("iterator_1")); + out = in.iterator(); + sink(getElement(out)); // $ hasValueFlow=iterator_1 + } + { + // "java.util.stream;BaseStream;true;onClose;(Runnable);;Element of Argument[-1];Element of ReturnValue;value" + BaseStream out = null; + BaseStream in = (BaseStream)Stream.of(source("onClose_1")); + out = in.onClose(null); + sink(getElement(out)); // $ hasValueFlow=onClose_1 + } + { + // "java.util.stream;BaseStream;true;parallel;();;Element of Argument[-1];Element of ReturnValue;value" + BaseStream out = null; + BaseStream in = (BaseStream)Stream.of(source("parallel_1")); + out = in.parallel(); + sink(getElement(out)); // $ hasValueFlow=parallel_1 + } + { + // "java.util.stream;BaseStream;true;sequential;();;Element of Argument[-1];Element of ReturnValue;value" + BaseStream out = null; + BaseStream in = (BaseStream)Stream.of(source("sequential_1")); + out = in.sequential(); + sink(getElement(out)); // $ hasValueFlow=sequential_1 + } + { + // "java.util.stream;BaseStream;true;spliterator;();;Element of Argument[-1];Element of ReturnValue;value" + Spliterator out = null; + BaseStream in = (BaseStream)Stream.of(source("spliterator_1")); + out = in.spliterator(); + sink(getElementSpliterator(out)); // $ hasValueFlow=spliterator_1 + } + { + // "java.util.stream;BaseStream;true;unordered;();;Element of Argument[-1];Element of ReturnValue;value" + BaseStream out = null; + BaseStream in = (BaseStream)Stream.of(source("unordered_1")); + out = in.unordered(); + sink(getElement(out)); // $ hasValueFlow=unordered_1 + } + { + // "java.util.stream;Stream;true;concat;(Stream,Stream);;Element of Argument[0..1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("concat_1")); + out = Stream.concat(in, null); + sink(getElement(out)); // $ hasValueFlow=concat_1 + } + { + // "java.util.stream;Stream;true;concat;(Stream,Stream);;Element of Argument[0..1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("concat_2")); + out = Stream.concat(null, in); + sink(getElement(out)); // $ hasValueFlow=concat_2 + } + { + // "java.util.stream;Stream;true;distinct;();;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("distinct_1")); + out = in.distinct(); + sink(getElement(out)); // $ hasValueFlow=distinct_1 + } + { + // "java.util.stream;Stream;true;dropWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("dropWhile_1")); + out = in.dropWhile(null); + sink(getElement(out)); // $ hasValueFlow=dropWhile_1 + } + { + // "java.util.stream;Stream;true;filter;(Predicate);;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("filter_1")); + out = in.filter(null); + sink(getElement(out)); // $ hasValueFlow=filter_1 + } + { + // "java.util.stream;Stream;true;findAny;();;Element of Argument[-1];Element of ReturnValue;value" + Optional out = null; + Stream in = (Stream)Stream.of(source("findAny_1")); + out = in.findAny(); + sink(getElement(out)); // $ hasValueFlow=findAny_1 + } + { + // "java.util.stream;Stream;true;findFirst;();;Element of Argument[-1];Element of ReturnValue;value" + Optional out = null; + Stream in = (Stream)Stream.of(source("findFirst_1")); + out = in.findFirst(); + sink(getElement(out)); // $ hasValueFlow=findFirst_1 + } + { + // "java.util.stream;Stream;true;limit;(long);;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("limit_1")); + out = in.limit(0L); + sink(getElement(out)); // $ hasValueFlow=limit_1 + } + { + // "java.util.stream;Stream;true;max;(Comparator);;Element of Argument[-1];Element of ReturnValue;value" + Optional out = null; + Stream in = (Stream)Stream.of(source("max_1")); + out = in.max(null); + sink(getElement(out)); // $ hasValueFlow=max_1 + } + { + // "java.util.stream;Stream;true;min;(Comparator);;Element of Argument[-1];Element of ReturnValue;value" + Optional out = null; + Stream in = (Stream)Stream.of(source("min_1")); + out = in.min(null); + sink(getElement(out)); // $ hasValueFlow=min_1 + } + { + // "java.util.stream;Stream;true;of;(Object);;Argument[0];Element of ReturnValue;value" + Stream out = null; + Object in = (Object)source("of_1"); + out = Stream.of(in); + sink(getElement(out)); // $ hasValueFlow=of_1 + } + { + // "java.util.stream;Stream;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value" + Stream out = null; + Object[] in = (Object[])new Object[]{source("of_2")}; + out = Stream.of(in); + sink(getElement(out)); // $ hasValueFlow=of_2 + } + { + // "java.util.stream;Stream;true;ofNullable;(Object);;Argument[0];Element of ReturnValue;value" + Stream out = null; + Object in = (Object)source("ofNullable_1"); + out = Stream.ofNullable(in); + sink(getElement(out)); // $ hasValueFlow=ofNullable_1 + } + { + // "java.util.stream;Stream;true;peek;(Consumer);;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("peek_1")); + out = in.peek(null); + sink(getElement(out)); // $ hasValueFlow=peek_1 + } + { + // "java.util.stream;Stream;true;skip;(long);;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("skip_1")); + out = in.skip(0L); + sink(getElement(out)); // $ hasValueFlow=skip_1 + } + { + // "java.util.stream;Stream;true;sorted;;;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("sorted_1")); + out = in.sorted(); + sink(getElement(out)); // $ hasValueFlow=sorted_1 + } + { + // "java.util.stream;Stream;true;sorted;;;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("sorted_2")); + out = in.sorted(null); + sink(getElement(out)); // $ hasValueFlow=sorted_2 + } + { + // "java.util.stream;Stream;true;takeWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value" + Stream out = null; + Stream in = (Stream)Stream.of(source("takeWhile_1")); + out = in.takeWhile(null); + sink(getElement(out)); // $ hasValueFlow=takeWhile_1 + } + { + // "java.util.stream;Stream;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value" + Object[] out = null; + Stream in = (Stream)Stream.of(source("toArray_1")); + out = in.toArray(); + sink(getArrayElement(out)); // $ hasValueFlow=toArray_1 + } + { + // "java.util.stream;Stream;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value" + Object[] out = null; + Stream in = (Stream)Stream.of(source("toArray_2")); + out = in.toArray(null); + sink(getArrayElement(out)); // $ hasValueFlow=toArray_2 + } + { + // "java.util.stream;Stream;true;toList;();;Element of Argument[-1];Element of ReturnValue;value" + List out = null; + Stream in = (Stream)Stream.of(source("toList_1")); + out = in.toList(); + sink(getElement(out)); // $ hasValueFlow=toList_1 + } + + // *** Handwritten *** + { + //java.util.stream;Stream;true;allMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("allMatch")); + in.allMatch(x -> { sink(x); return true; }); // $ hasValueFlow=allMatch + } + { + //java.util.stream;Stream;true;anyMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("anyMatch")); + in.anyMatch(x -> { sink(x); return true; }); // $ hasValueFlow=anyMatch + } + { + //java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Element of Argument[-1];Parameter[1] of Argument[1];value + Stream<Object> in = Stream.of(source("collect")); + in.collect(null, (c,x) -> sink(x), null); // $ hasValueFlow=collect + } + { + //java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0..1] of Argument[2];Parameter[0] of Argument[1];value + Stream.of(new Object()).collect( + () -> new Object[1], + (a, x) -> sink(a[0]), // $ hasValueFlow=collect_2 hasValueFlow=collect_3 SPURIOUS: hasValueFlow=collect_4 hasValueFlow=collect_5 + (a1, a2) -> { + a1[0] = source("collect_2"); + a2[0] = source("collect_3"); + }); + } + { + //java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];Parameter[0..1] of Argument[2];value + //java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];ReturnValue;value + //java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;ReturnValue of Argument[0];Parameter[0] of Argument[1];value + Object[] out = Stream.of(new Object()).collect( + () -> new Object[] { source("collect_5") }, + (a, x) -> { + sink(a[0]); // $ hasValueFlow=collect_4 hasValueFlow=collect_5 SPURIOUS: hasValueFlow=collect_2 hasValueFlow=collect_3 + a[0] = source("collect_4"); + }, + (a1, a2) -> { + sink(a1[0]); // $ hasValueFlow=collect_4 hasValueFlow=collect_5 SPURIOUS: hasValueFlow=collect_2 hasValueFlow=collect_3 + sink(a2[0]); // $ hasValueFlow=collect_4 hasValueFlow=collect_5 SPURIOUS: hasValueFlow=collect_2 hasValueFlow=collect_3 + }); + sink(out[0]); // $ hasValueFlow=collect_4 hasValueFlow=collect_5 + } + { + Stream<Object> in = Stream.of(source("collect_6")); + Object[] out = in.collect( + () -> new Object[1], + (a, x) -> { a[0] = x; }, + (a1, a2) -> { + a1[0] = a2[0]; + a2[0] = a1[0]; + }); + sink(out[0]); // $ hasValueFlow=collect_6 + } + { + //java.util.stream;Stream;true;dropWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("dropWhile")); + in.dropWhile(x -> { sink(x); return true; }); // $ hasValueFlow=dropWhile + } + { + //java.util.stream;Stream;true;filter;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("filter")); + in.filter(x -> { sink(x); return true; }); // $ hasValueFlow=filter + } + { + //java.util.stream;Stream;true;flatMap;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("flatMap")); + in.flatMap(x -> { sink(x); return Stream.empty(); }); // $ hasValueFlow=flatMap + } + { + //java.util.stream;Stream;true;flatMap;(Function);;Element of ReturnValue of Argument[0];Element of ReturnValue;value + Stream<Object> out = Stream.of(new Object()).flatMap(x -> Stream.of(source("flatMap_2"))); + sink(getElement(out)); // $ hasValueFlow=flatMap_2 + } + { + //java.util.stream;Stream;true;flatMapToDouble;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("flatMapToDouble")); + in.flatMapToDouble(x -> { sink(x); return null; }); // $ hasValueFlow=flatMapToDouble + } + { + //java.util.stream;Stream;true;flatMapToInt;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("flatMapToInt")); + in.flatMapToInt(x -> { sink(x); return null; }); // $ hasValueFlow=flatMapToInt + } + { + //java.util.stream;Stream;true;flatMapToLong;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("flatMapToLong")); + in.flatMapToLong(x -> { sink(x); return null; }); // $ hasValueFlow=flatMapToLong + } + { + //java.util.stream;Stream;true;forEach;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("forEach")); + in.forEach(x -> sink(x)); // $ hasValueFlow=forEach + } + { + //java.util.stream;Stream;true;forEachOrdered;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("forEachOrdered")); + in.forEachOrdered(x -> sink(x)); // $ hasValueFlow=forEachOrdered + } + { + //java.util.stream;Stream;true;generate;(Supplier);;ReturnValue of Argument[0];Element of ReturnValue;value + Stream<Object> out = Stream.generate(() -> source("generate")); + sink(getElement(out)); // $ hasValueFlow=generate + } + { + // "java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Element of ReturnValue;value" + //java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Parameter[0] of Argument[1..2];value + //java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Element of ReturnValue;value + //java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Parameter[0] of Argument[1..2];value + Stream<Object> out = null; + Object in = (Object)source("iterate_1"); + out = Stream.iterate(in, x -> { + sink(x); // $ hasValueFlow=iterate_1 hasValueFlow=iterate_2 + return true; + }, x -> { + sink(x); // $ hasValueFlow=iterate_1 hasValueFlow=iterate_2 + return source("iterate_2"); + }); + sink(getElement(out)); // $ hasValueFlow=iterate_1 hasValueFlow=iterate_2 + } + { + // "java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Element of ReturnValue;value" + //java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Parameter[0] of Argument[1];value + //java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Element of ReturnValue;value + //java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Parameter[0] of Argument[1];value + Stream<Object> out = null; + Object in = (Object)source("iterate_3"); + out = Stream.iterate(in, x -> { + sink(x); // $ hasValueFlow=iterate_3 hasValueFlow=iterate_4 + return source("iterate_4"); + }); + sink(getElement(out)); // $ hasValueFlow=iterate_3 hasValueFlow=iterate_4 + } + { + //java.util.stream;Stream;true;map;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value + //java.util.stream;Stream;true;map;(Function);;ReturnValue of Argument[0];Element of ReturnValue;value + Stream<Object> in = Stream.of(source("map_1")); + Stream<Object> out = in.map(x -> { sink(x); return source("map_2"); }); // $ hasValueFlow=map_1 + sink(getElement(out)); // $ hasValueFlow=map_2 + } + { + //java.util.stream;Stream;true;mapMulti;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("mapMulti")); + in.mapMulti((x, consumer) -> sink(x)); // $ hasValueFlow=mapMulti + } + { + //java.util.stream;Stream;true;mapMultiToDouble;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("mapMultiToDouble")); + in.mapMultiToDouble((x, consumer) -> sink(x)); // $ hasValueFlow=mapMultiToDouble + } + { + //java.util.stream;Stream;true;mapMultiToInt;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("mapMultiToInt")); + in.mapMultiToInt((x, consumer) -> sink(x)); // $ hasValueFlow=mapMultiToInt + } + { + //java.util.stream;Stream;true;mapMultiToLong;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("mapMultiToLong")); + in.mapMultiToLong((x, consumer) -> sink(x)); // $ hasValueFlow=mapMultiToLong + } + { + //java.util.stream;Stream;true;mapToDouble;(ToDoubleFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("mapToDouble")); + in.mapToDouble(x -> { sink(x); return 0.0; }); // $ hasValueFlow=mapToDouble + } + { + //java.util.stream;Stream;true;mapToInt;(ToIntFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("mapToInt")); + in.mapToInt(x -> { sink(x); return 0; }); // $ hasValueFlow=mapToInt + } + { + //java.util.stream;Stream;true;mapToLong;(ToLongFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("mapToLong")); + in.mapToLong(x -> { sink(x); return 0; }); // $ hasValueFlow=mapToLong + } + { + //java.util.stream;Stream;true;max;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value + Stream<Object> in = Stream.of(source("max")); + in.max((x,y) -> { sink(x); return 0; }); // $ hasValueFlow=max + in.max((x,y) -> { sink(y); return 0; }); // $ hasValueFlow=max + } + { + //java.util.stream;Stream;true;min;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value + Stream<Object> in = Stream.of(source("min")); + in.min((x,y) -> { sink(x); return 0; }); // $ hasValueFlow=min + in.min((x,y) -> { sink(y); return 0; }); // $ hasValueFlow=min + } + { + //java.util.stream;Stream;true;noneMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("noneMatch")); + in.noneMatch(x -> { sink(x); return true; }); // $ hasValueFlow=noneMatch + } + { + //java.util.stream;Stream;true;peek;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("peek")); + in.peek(x -> sink(x)); // $ hasValueFlow=peek + } + { + // "java.util.stream;Stream;true;reduce;(BinaryOperator);;Element of Argument[-1];Element of ReturnValue;value" + //java.util.stream;Stream;true;reduce;(BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value + //java.util.stream;Stream;true;reduce;(BinaryOperator);;ReturnValue of Argument[0];Element of ReturnValue;value + //java.util.stream;Stream;true;reduce;(BinaryOperator);;ReturnValue of Argument[0];Parameter[0..1] of Argument[0];value + Stream<Object> in = Stream.of(source("reduce_1")); + Optional<Object> out = in.reduce((x,y) -> { + sink(x); // $ hasValueFlow=reduce_1 hasValueFlow=reduce_2 + sink(y); // $ hasValueFlow=reduce_1 hasValueFlow=reduce_2 + return source("reduce_2"); + }); + sink(getElement(out)); // $ hasValueFlow=reduce_1 hasValueFlow=reduce_2 + } + { + // "java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];ReturnValue;value" + //java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[1];value + //java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[1];value + //java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];Parameter[0..1] of Argument[1];value + //java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];ReturnValue;value + Stream<Object> in = Stream.of(source("reduce_3")); + Object out = in.reduce(source("reduce_4"), (x,y) -> { + sink(x); // $ hasValueFlow=reduce_3 hasValueFlow=reduce_4 hasValueFlow=reduce_5 + sink(y); // $ hasValueFlow=reduce_3 hasValueFlow=reduce_4 hasValueFlow=reduce_5 + return source("reduce_5"); + }); + sink(out); // $ hasValueFlow=reduce_4 hasValueFlow=reduce_5 SPURIOUS: hasValueFlow=reduce_3 + } + { + // "java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];ReturnValue;value" + //java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[2];value + //java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0] of Argument[1];value + //java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Element of Argument[-1];Parameter[1] of Argument[1];value + //java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0..1] of Argument[2];value + //java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0] of Argument[1];value + //java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];ReturnValue;value + Stream<Object> in = Stream.of(source("reduce_6")); + Object out = in.reduce(source("reduce_7"), (x,y) -> { + sink(x); // $ hasValueFlow=reduce_7 hasValueFlow=reduce_8 hasValueFlow=reduce_9 + sink(y); // $ hasValueFlow=reduce_6 + return source("reduce_8"); + }, (x,y) -> { + sink(x); // $ hasValueFlow=reduce_7 hasValueFlow=reduce_8 hasValueFlow=reduce_9 + sink(y); // $ hasValueFlow=reduce_7 hasValueFlow=reduce_8 hasValueFlow=reduce_9 + return source("reduce_9"); + }); + sink(out); // $ hasValueFlow=reduce_7 hasValueFlow=reduce_8 hasValueFlow=reduce_9 + } + { + //java.util.stream;Stream;true;sorted;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value + Stream<Object> in = Stream.of(source("sorted")); + in.sorted((x,y) -> { sink(x); return 0; }); // $ hasValueFlow=sorted + in.sorted((x,y) -> { sink(y); return 0; }); // $ hasValueFlow=sorted + } + { + //java.util.stream;Stream;true;takeWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value + Stream<Object> in = Stream.of(source("takeWhile")); + in.takeWhile(x -> { sink(x); return true; }); // $ hasValueFlow=takeWhile + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/stream/test.expected b/java/ql/test/library-tests/frameworks/stream/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/stream/test.ql b/java/ql/test/library-tests/frameworks/stream/test.ql new file mode 100644 index 00000000000..ff94106f985 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/stream/test.ql @@ -0,0 +1,12 @@ +import java +import TestUtilities.InlineFlowTest + +class SummaryModelTest extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", + "generatedtest;Test;false;getElementSpliterator;(Spliterator);;Element of Argument[0];ReturnValue;value" + ] + } +} From 538bf7c3219a00b62f54b4e29d666fd60b519a82 Mon Sep 17 00:00:00 2001 From: haby0 <Ha_yub@163.com> Date: Thu, 7 Oct 2021 19:44:25 +0800 Subject: [PATCH 173/361] Update python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql Co-authored-by: yoff <lerchedahl@gmail.com> --- .../Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql index 9f840132fa3..af2d6f8bc16 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql @@ -38,7 +38,9 @@ class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configura } override predicate isSanitizer(DataFlow::Node node) { + // `client_supplied_ip.split(",")[n]` for `n` > 0 exists(Subscript ss | + not ss.getIndex().(IntegerLiteral).getText() = "0" and ss.getObject().(Call).getFunc().(Attribute).getName() = "split" and ss.getObject().(Call).getAnArg().(StrConst).getText() = "," and ss = node.asExpr() From 764a987b09a874c668de3d2896ca906edd8633f3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 7 Oct 2021 13:51:05 +0200 Subject: [PATCH 174/361] C#: Speedup GVN string `concat`s by pulling ranges into separate predicates --- .../ql/lib/semmle/code/csharp/Implements.qll | 15 ++++++++----- .../ql/lib/semmle/code/csharp/Unification.qll | 21 ++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/Implements.qll b/csharp/ql/lib/semmle/code/csharp/Implements.qll index c2d33d102dd..cc821b52823 100644 --- a/csharp/ql/lib/semmle/code/csharp/Implements.qll +++ b/csharp/ql/lib/semmle/code/csharp/Implements.qll @@ -398,6 +398,15 @@ private module Gvn { ) } + pragma[noinline] + private predicate toStringPart(int i, int j) { + exists(Unification::GenericType t, int children | + t = this.getConstructedGenericDeclaringTypeAt(i) and + children = t.getNumberOfArgumentsSelf() and + if children = 0 then j = 0 else j in [0 .. 2 * children] + ) + } + language[monotonicAggregates] string toString() { this.isFullyConstructed() and @@ -406,11 +415,7 @@ private module Gvn { or result = strictconcat(int i, int j | - exists(Unification::GenericType t, int children | - t = this.getConstructedGenericDeclaringTypeAt(i) and - children = t.getNumberOfArgumentsSelf() and - if children = 0 then j = 0 else j in [0 .. 2 * children] - ) + this.toStringPart(i, j) | this.toStringConstructedPart(i, j) order by i desc, j ) diff --git a/csharp/ql/lib/semmle/code/csharp/Unification.qll b/csharp/ql/lib/semmle/code/csharp/Unification.qll index 173feedb695..3a2c6745f45 100644 --- a/csharp/ql/lib/semmle/code/csharp/Unification.qll +++ b/csharp/ql/lib/semmle/code/csharp/Unification.qll @@ -277,6 +277,18 @@ module Gvn { ) } + pragma[noinline] + private predicate toStringPart(int i, int j) { + exists(int offset | + exists(GenericType t, int children | + t = this.getConstructedGenericDeclaringTypeAt(i) and + children = t.getNumberOfArgumentsSelf() and + (if this.isDeclaringTypeAt(i) then offset = 1 else offset = 0) and + if children = 0 then j in [0 .. offset] else j in [0 .. 2 * children + offset] + ) + ) + } + language[monotonicAggregates] string toString() { this.isFullyConstructed() and @@ -284,13 +296,8 @@ module Gvn { result = k.toStringBuiltin(this.getArg(0).toString()) or result = - strictconcat(int i, int j, int offset | - exists(GenericType t, int children | - t = this.getConstructedGenericDeclaringTypeAt(i) and - children = t.getNumberOfArgumentsSelf() and - (if this.isDeclaringTypeAt(i) then offset = 1 else offset = 0) and - if children = 0 then j in [0 .. offset] else j in [0 .. 2 * children + offset] - ) + strictconcat(int i, int j | + toStringPart(i, j) | this.toStringConstructedPart(i, j) order by i desc, j ) From f8857511077f5203b403e7fcaa10fc85ae7153b0 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Thu, 7 Oct 2021 14:42:19 +0200 Subject: [PATCH 175/361] Java: Add change note. --- java/change-notes/2021-10-07-java-util-stream.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java/change-notes/2021-10-07-java-util-stream.md diff --git a/java/change-notes/2021-10-07-java-util-stream.md b/java/change-notes/2021-10-07-java-util-stream.md new file mode 100644 index 00000000000..76ed485c279 --- /dev/null +++ b/java/change-notes/2021-10-07-java-util-stream.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added data flow models for `java.util.stream.Stream`. From 2b88a2aa0c250cf44aa4f73bccd9fd3d0d2dd637 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Thu, 7 Oct 2021 14:46:24 +0200 Subject: [PATCH 176/361] Dataflow: Fix qldoc: s/accesspath/access path/. --- .../semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll | 2 +- .../lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll | 2 +- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll | 2 +- .../semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 2 +- .../semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll | 2 +- .../semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll | 2 +- .../semmle/code/java/dataflow/internal/DataFlowImplCommon.qll | 2 +- .../lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll | 2 +- .../semmle/python/dataflow/new/internal/DataFlowImplCommon.qll | 2 +- .../lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 2 +- 10 files changed, 10 insertions(+), 10 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 e8ebb3f5e96..aae210452d6 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -1238,7 +1238,7 @@ class TypedContent extends MkTypedContent { string toString() { result = c.toString() } /** - * Holds if accesspaths with this `TypedContent` at their head always should + * Holds if access paths with this `TypedContent` at their head always should * be tracked at high precision. This disables adaptive accesspath precision * for such accesspaths. */ diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 338aa73ce86..4ccdd3425ab 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -241,7 +241,7 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl int accessPathLimit() { result = 5 } /** - * Holds if accesspaths with `c` at their head always should be tracked at high + * Holds if access paths with `c` at their head always should be tracked at high * precision. This disables adaptive accesspath precision for such accesspaths. */ predicate forceHighPrecision(Content c) { none() } 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 e8ebb3f5e96..aae210452d6 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 @@ -1238,7 +1238,7 @@ class TypedContent extends MkTypedContent { string toString() { result = c.toString() } /** - * Holds if accesspaths with this `TypedContent` at their head always should + * Holds if access paths with this `TypedContent` at their head always should * be tracked at high precision. This disables adaptive accesspath precision * for such accesspaths. */ 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 945ee2766fb..23714024459 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 @@ -467,7 +467,7 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl int accessPathLimit() { result = 5 } /** - * Holds if accesspaths with `c` at their head always should be tracked at high + * Holds if access paths with `c` at their head always should be tracked at high * precision. This disables adaptive accesspath precision for such accesspaths. */ predicate forceHighPrecision(Content c) { none() } 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 e8ebb3f5e96..aae210452d6 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -1238,7 +1238,7 @@ class TypedContent extends MkTypedContent { string toString() { result = c.toString() } /** - * Holds if accesspaths with this `TypedContent` at their head always should + * Holds if access paths with this `TypedContent` at their head always should * be tracked at high precision. This disables adaptive accesspath precision * for such accesspaths. */ diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index a164008e402..550bf3bb341 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1919,7 +1919,7 @@ private predicate viableConstantBooleanParamArg( int accessPathLimit() { result = 5 } /** - * Holds if accesspaths with `c` at their head always should be tracked at high + * Holds if access paths with `c` at their head always should be tracked at high * precision. This disables adaptive accesspath precision for such accesspaths. */ predicate forceHighPrecision(Content c) { c instanceof ElementContent } 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 e8ebb3f5e96..aae210452d6 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -1238,7 +1238,7 @@ class TypedContent extends MkTypedContent { string toString() { result = c.toString() } /** - * Holds if accesspaths with this `TypedContent` at their head always should + * Holds if access paths with this `TypedContent` at their head always should * be tracked at high precision. This disables adaptive accesspath precision * for such accesspaths. */ diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 0e21aaa64cd..e55a57c7817 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -309,7 +309,7 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { int accessPathLimit() { result = 5 } /** - * Holds if accesspaths with `c` at their head always should be tracked at high + * Holds if access paths with `c` at their head always should be tracked at high * precision. This disables adaptive accesspath precision for such accesspaths. */ predicate forceHighPrecision(Content c) { 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 e8ebb3f5e96..aae210452d6 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -1238,7 +1238,7 @@ class TypedContent extends MkTypedContent { string toString() { result = c.toString() } /** - * Holds if accesspaths with this `TypedContent` at their head always should + * Holds if access paths with this `TypedContent` at their head always should * be tracked at high precision. This disables adaptive accesspath precision * for such accesspaths. */ 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 7c662b6249a..ba1a230b4ee 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1621,7 +1621,7 @@ predicate isImmutableOrUnobservable(Node n) { none() } int accessPathLimit() { result = 5 } /** - * Holds if accesspaths with `c` at their head always should be tracked at high + * Holds if access paths with `c` at their head always should be tracked at high * precision. This disables adaptive accesspath precision for such accesspaths. */ predicate forceHighPrecision(Content c) { none() } From 39640efc9b575ee7144e7adbb293aa73e2cdde41 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Thu, 7 Oct 2021 14:33:39 +0100 Subject: [PATCH 177/361] Remove no-longer-needed TaintPreservingCallables and update test expectations --- .../code/java/frameworks/android/Intent.qll | 19 ------------------- .../CWE-200/SensitiveAndroidFileLeak.expected | 14 -------------- .../security/CWE-755/NFEAndroidDoS.expected | 18 +++++++++++++----- .../dataflow/taintsources/remote.expected | 11 +++++++++++ 4 files changed, 24 insertions(+), 38 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index f3a981cebc5..47f0df13365 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -36,25 +36,6 @@ class ContextStartActivityMethod extends Method { } } -class IntentGetExtraMethod extends Method, TaintPreservingCallable { - IntentGetExtraMethod() { - (getName().regexpMatch("get\\w+Extra") or hasName("getExtras")) and - getDeclaringType() instanceof TypeIntent - } - - override predicate returnsTaintFrom(int arg) { arg = -1 } -} - -/** A getter on `android.os.BaseBundle` or `android.os.Bundle`. */ -class BundleGetterMethod extends Method, TaintPreservingCallable { - BundleGetterMethod() { - getDeclaringType().hasQualifiedName("android.os", ["BaseBundle", "Bundle"]) and - getName().matches("get%") - } - - override predicate returnsTaintFrom(int arg) { arg = -1 } -} - /** * Specifies that if an `Intent` is tainted, then so are its synthetic fields. */ diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected index 3ad57e266c5..b67c634ad9f 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -1,21 +1,14 @@ edges | FileService.java:20:31:20:43 | intent : Intent | FileService.java:21:28:21:33 | intent : Intent | -| FileService.java:20:31:20:43 | intent : Intent | FileService.java:25:42:25:50 | localPath : String | | FileService.java:21:28:21:33 | intent : Intent | FileService.java:21:28:21:64 | getStringExtra(...) : Object | | FileService.java:21:28:21:64 | getStringExtra(...) : Object | FileService.java:25:42:25:50 | localPath : Object | | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:40:41:40:55 | params : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | -| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | | FileService.java:25:42:25:50 | localPath : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | | FileService.java:25:42:25:50 | localPath : Object | FileService.java:32:13:32:28 | sourceUri : Object | -| FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | -| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | | FileService.java:32:13:32:28 | sourceUri : Object | FileService.java:35:17:35:25 | sourceUri : Object | -| FileService.java:32:13:32:28 | sourceUri : String | FileService.java:35:17:35:25 | sourceUri : String | | FileService.java:34:20:36:13 | {...} [[]] : Object | FileService.java:34:20:36:13 | new Object[] [[]] : Object | -| FileService.java:34:20:36:13 | {...} [[]] : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | | FileService.java:35:17:35:25 | sourceUri : Object | FileService.java:34:20:36:13 | {...} [[]] : Object | -| FileService.java:35:17:35:25 | sourceUri : String | FileService.java:34:20:36:13 | {...} [[]] : String | | FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | | FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | | LeakFileActivity2.java:15:13:15:18 | intent : Intent | LeakFileActivity2.java:16:26:16:31 | intent : Intent | @@ -31,17 +24,11 @@ nodes | FileService.java:21:28:21:64 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] | | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | semmle.label | makeParamsToExecute(...) [[]] : Object | -| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | semmle.label | makeParamsToExecute(...) [[]] : String | | FileService.java:25:42:25:50 | localPath : Object | semmle.label | localPath : Object | -| FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String | | FileService.java:32:13:32:28 | sourceUri : Object | semmle.label | sourceUri : Object | -| FileService.java:32:13:32:28 | sourceUri : String | semmle.label | sourceUri : String | | FileService.java:34:20:36:13 | new Object[] [[]] : Object | semmle.label | new Object[] [[]] : Object | -| FileService.java:34:20:36:13 | new Object[] [[]] : String | semmle.label | new Object[] [[]] : String | | FileService.java:34:20:36:13 | {...} [[]] : Object | semmle.label | {...} [[]] : Object | -| FileService.java:34:20:36:13 | {...} [[]] : String | semmle.label | {...} [[]] : String | | FileService.java:35:17:35:25 | sourceUri : Object | semmle.label | sourceUri : Object | -| FileService.java:35:17:35:25 | sourceUri : String | semmle.label | sourceUri : String | | FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] | | FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | | FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] | @@ -55,7 +42,6 @@ nodes | LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) | subpaths | FileService.java:25:42:25:50 | localPath : Object | FileService.java:32:13:32:28 | sourceUri : Object | FileService.java:34:20:36:13 | new Object[] [[]] : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | -| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | FileService.java:34:20:36:13 | new Object[] [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | #select | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:15:13:15:18 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:15:13:15:18 | intent | this user input | | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:16:26:16:31 | intent | this user input | diff --git a/java/ql/test/experimental/query-tests/security/CWE-755/NFEAndroidDoS.expected b/java/ql/test/experimental/query-tests/security/CWE-755/NFEAndroidDoS.expected index 16c97df96e8..73657a38158 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-755/NFEAndroidDoS.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-755/NFEAndroidDoS.expected @@ -1,17 +1,25 @@ edges -| NFEAndroidDoS.java:13:24:13:34 | getIntent(...) : Intent | NFEAndroidDoS.java:14:21:14:51 | parseDouble(...) | -| NFEAndroidDoS.java:22:21:22:31 | getIntent(...) : Intent | NFEAndroidDoS.java:23:15:23:40 | parseInt(...) | -| NFEAndroidDoS.java:25:22:25:32 | getIntent(...) : Intent | NFEAndroidDoS.java:26:16:26:42 | parseInt(...) | -| NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | NFEAndroidDoS.java:44:21:44:43 | new Double(...) | -| NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | NFEAndroidDoS.java:47:21:47:47 | valueOf(...) | +| NFEAndroidDoS.java:13:24:13:34 | getIntent(...) : Intent | NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : Object | +| NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:14:21:14:51 | parseDouble(...) | +| NFEAndroidDoS.java:22:21:22:31 | getIntent(...) : Intent | NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | +| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | NFEAndroidDoS.java:23:15:23:40 | parseInt(...) | +| NFEAndroidDoS.java:25:22:25:32 | getIntent(...) : Intent | NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | +| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | NFEAndroidDoS.java:26:16:26:42 | parseInt(...) | +| NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | +| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:44:21:44:43 | new Double(...) | +| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:47:21:47:47 | valueOf(...) | nodes | NFEAndroidDoS.java:13:24:13:34 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | +| NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | | NFEAndroidDoS.java:14:21:14:51 | parseDouble(...) | semmle.label | parseDouble(...) | | NFEAndroidDoS.java:22:21:22:31 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | +| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | | NFEAndroidDoS.java:23:15:23:40 | parseInt(...) | semmle.label | parseInt(...) | | NFEAndroidDoS.java:25:22:25:32 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | +| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | | NFEAndroidDoS.java:26:16:26:42 | parseInt(...) | semmle.label | parseInt(...) | | NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | +| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | | NFEAndroidDoS.java:44:21:44:43 | new Double(...) | semmle.label | new Double(...) | | NFEAndroidDoS.java:47:21:47:47 | valueOf(...) | semmle.label | valueOf(...) | subpaths diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.expected b/java/ql/test/library-tests/dataflow/taintsources/remote.expected index 55268b63bad..c6b22148e24 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.expected @@ -5,14 +5,22 @@ | A.java:41:5:41:53 | getInputStream(...) | A.java:41:5:41:53 | getInputStream(...) | | A.java:42:5:42:45 | getInputStream(...) | A.java:42:5:42:45 | getInputStream(...) | | A.java:43:5:43:47 | getHostName(...) | A.java:43:5:43:47 | getHostName(...) | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | | IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:35 | getIntent(...) | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:57 | getStringExtra(...) | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:10:29:10:35 | trouble | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | | IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:30 | getIntent(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:52 | getStringExtra(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:17:29:17:35 | trouble | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | [summary] read: android.content.Intent.extras of argument -1 in getExtras | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | [summary] to write: return (return) in getExtras | | IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | parameter this | | IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] read: <map.value> of argument -1 in getString | | IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] to write: return (return) in getString | @@ -21,6 +29,9 @@ | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:42 | getExtras(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:59 | getString(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:24:29:24:35 | trouble | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | | IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:33 | getIntent(...) | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:55 | getStringExtra(...) | From 933412eb8d073400d8b558037a45da21d9a9ba81 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Thu, 7 Oct 2021 17:45:07 +0200 Subject: [PATCH 178/361] Apply suggestions from code review Co-authored-by: Taus <tausbn@github.com> --- .../experimental/dataflow/module-initialization/localFlow.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql index 4c334607876..3bb6ec021e6 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql +++ b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql @@ -25,7 +25,7 @@ class ImportTimeLocalFlowTest extends InlineExpectationsTest { class RuntimeLocalFlowTest extends FlowTest { RuntimeLocalFlowTest() { this = "RuntimeLocalFlowTest" } - override string flowTag() { result = "runtimFlow" } + override string flowTag() { result = "runtimeFlow" } override predicate relevantFlow(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { nodeFrom.getLocation().getFile().getBaseName() = "multiphase.py" and From 2ed572095c10790e16b442d6aa706db06b2b8d36 Mon Sep 17 00:00:00 2001 From: Aditya Sharad <adityasharad@github.com> Date: Thu, 7 Oct 2021 10:51:11 -0700 Subject: [PATCH 179/361] CLI docs: Address comments on Bazel example --- docs/codeql/codeql-cli/creating-codeql-databases.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index fd9bf9a0847..52bd076e636 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -225,10 +225,8 @@ commands that you can specify for compiled languages. # Navigate to the Bazel workspace. - # Stop all running Bazel server processes. - bazel shutdown - - # Remove cached objects before building. + # Before building, remove cached objects + # and stop all running Bazel server processes. bazel clean --expunge # Build using the following Bazel flags, to help CodeQL detect the build: @@ -238,6 +236,11 @@ commands that you can specify for compiled languages. codeql database create new-database --language=<language> \ --command='bazel build --spawn_strategy=local --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results //path/to/package:target' + # After building, stop all running Bazel server processes. + # This ensures future build commands start in a clean Bazel server process + # without CodeQL attached. + bazel shutdown + - Project built using a custom build script:: codeql database create new-database --language=<language> --command='./scripts/build.sh' From a31bf75169ce47400d71d86fa98a7ebd53853567 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> Date: Thu, 7 Oct 2021 20:28:30 +0200 Subject: [PATCH 180/361] Python: Refactor `pickle.loads()` modeling --- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 539f0dcabb0..0c4c49aa504 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -447,23 +447,15 @@ private module StdlibPrivate { // --------------------------------------------------------------------------- // pickle // --------------------------------------------------------------------------- - /** Gets a reference to the `pickle` module. */ - DataFlow::Node pickle() { result = API::moduleImport(["pickle", "cPickle", "_pickle"]).getAUse() } - - /** Provides models for the `pickle` module. */ - module pickle { - /** Gets a reference to the `pickle.loads` function. */ - DataFlow::Node loads() { - result = API::moduleImport(["pickle", "cPickle", "_pickle"]).getMember("loads").getAUse() - } - } + /** Gets a reference to any of the `pickle` modules. */ + API::Node pickle() { result = API::moduleImport(["pickle", "cPickle", "_pickle"]) } /** * A call to `pickle.loads` * See https://docs.python.org/3/library/pickle.html#pickle.loads */ private class PickleLoadsCall extends Decoding::Range, DataFlow::CallCfgNode { - PickleLoadsCall() { this.getFunction() = pickle::loads() } + PickleLoadsCall() { this = pickle().getMember("loads").getACall() } override predicate mayExecuteInput() { any() } From 3592b09d56285770563693cc6071158139c482fd Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> Date: Thu, 7 Oct 2021 21:11:51 +0200 Subject: [PATCH 181/361] Python: Expand stdlib decoding tests The part about claiming there is decoding of the input to `shelve.open` is sort of an odd one, since it's not the filename, but the contents of the file that is decoded. However, trying to only handle this problem through path injection is not enough -- if a user is able to upload and access files through `shelve.open` in a path injection safe manner, that still leads to code execution. So right now the best way we have of modeling this is to treat the filename argument as being deserialized... --- .../library-tests/frameworks/stdlib/Decoding.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py index 5d157a61f6e..7455ff85856 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py +++ b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py @@ -1,10 +1,23 @@ import pickle import marshal +import shelve import base64 +pickle.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=pickle.load(..) decodeFormat=pickle decodeMayExecuteInput +pickle.load(file=file_) # $ MISSING: decodeInput=file_ decodeOutput=pickle.load(..) decodeFormat=pickle decodeMayExecuteInput pickle.loads(payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput +# using this keyword argument is disallowed from Python 3.9 +pickle.loads(data=payload) # $ decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput MISSING: decodeInput=payload + +marshal.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=marshal.load(..) decodeFormat=marshal decodeMayExecuteInput marshal.loads(payload) # $ decodeInput=payload decodeOutput=marshal.loads(..) decodeFormat=marshal decodeMayExecuteInput + +# if the file opened has been controlled by an attacker, this can lead to code +# execution. (underlying file format is pickle) +shelve.open(filepath) # $ MISSING: decodeInput=filepath decodeOutput=shelve.open(..) decodeFormat=pickle decodeMayExecuteInput getAPathArgument=filepath +shelve.open(filename=filepath) # $ MISSING: decodeInput=filepath decodeOutput=shelve.open(..) decodeFormat=pickle decodeMayExecuteInput getAPathArgument=filepath + # TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py base64.b64decode(payload) # $ decodeInput=payload decodeOutput=base64.b64decode(..) decodeFormat=Base64 base64.standard_b64decode(payload) # $ decodeInput=payload decodeOutput=base64.standard_b64decode(..) decodeFormat=Base64 From 27c368a444bcfaeea023f7ddf7b1917d5223496b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> Date: Thu, 7 Oct 2021 21:24:12 +0200 Subject: [PATCH 182/361] Python: Model keyword arguments to `pickle.loads` --- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 2 +- python/ql/test/library-tests/frameworks/stdlib/Decoding.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 0c4c49aa504..b0807a52c99 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -459,7 +459,7 @@ private module StdlibPrivate { override predicate mayExecuteInput() { any() } - override DataFlow::Node getAnInput() { result = this.getArg(0) } + override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] } override DataFlow::Node getOutput() { result = this } diff --git a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py index 7455ff85856..f5f1f035e0d 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py +++ b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py @@ -7,7 +7,7 @@ pickle.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=pickle.load(..) pickle.load(file=file_) # $ MISSING: decodeInput=file_ decodeOutput=pickle.load(..) decodeFormat=pickle decodeMayExecuteInput pickle.loads(payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput # using this keyword argument is disallowed from Python 3.9 -pickle.loads(data=payload) # $ decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput MISSING: decodeInput=payload +pickle.loads(data=payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput marshal.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=marshal.load(..) decodeFormat=marshal decodeMayExecuteInput marshal.loads(payload) # $ decodeInput=payload decodeOutput=marshal.loads(..) decodeFormat=marshal decodeMayExecuteInput From 1b61296ea59f829ab6f7d376c84fcfc9c17eb254 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> Date: Thu, 7 Oct 2021 21:25:48 +0200 Subject: [PATCH 183/361] Python: Model `pickle.load` --- .../ql/lib/semmle/python/frameworks/Stdlib.qll | 16 ++++++++++++++++ .../library-tests/frameworks/stdlib/Decoding.py | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index b0807a52c99..0f74eea8618 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -450,6 +450,22 @@ private module StdlibPrivate { /** Gets a reference to any of the `pickle` modules. */ API::Node pickle() { result = API::moduleImport(["pickle", "cPickle", "_pickle"]) } + /** + * A call to `pickle.load` + * See https://docs.python.org/3/library/pickle.html#pickle.load + */ + private class PickleLoadCall extends Decoding::Range, DataFlow::CallCfgNode { + PickleLoadCall() { this = pickle().getMember("load").getACall() } + + override predicate mayExecuteInput() { any() } + + override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("file")] } + + override DataFlow::Node getOutput() { result = this } + + override string getFormat() { result = "pickle" } + } + /** * A call to `pickle.loads` * See https://docs.python.org/3/library/pickle.html#pickle.loads diff --git a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py index f5f1f035e0d..a57685f9b3c 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py +++ b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py @@ -3,8 +3,8 @@ import marshal import shelve import base64 -pickle.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=pickle.load(..) decodeFormat=pickle decodeMayExecuteInput -pickle.load(file=file_) # $ MISSING: decodeInput=file_ decodeOutput=pickle.load(..) decodeFormat=pickle decodeMayExecuteInput +pickle.load(file_) # $ decodeInput=file_ decodeOutput=pickle.load(..) decodeFormat=pickle decodeMayExecuteInput +pickle.load(file=file_) # $ decodeInput=file_ decodeOutput=pickle.load(..) decodeFormat=pickle decodeMayExecuteInput pickle.loads(payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput # using this keyword argument is disallowed from Python 3.9 pickle.loads(data=payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput From a81d359669468d17ed1a86bebab5b03a221bf439 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> Date: Thu, 7 Oct 2021 21:27:35 +0200 Subject: [PATCH 184/361] Python: Model `marshal.load` --- .../ql/lib/semmle/python/frameworks/Stdlib.qll | 16 ++++++++++++++++ .../library-tests/frameworks/stdlib/Decoding.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 0f74eea8618..c045e8fdb7f 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -428,6 +428,22 @@ private module StdlibPrivate { // --------------------------------------------------------------------------- // marshal // --------------------------------------------------------------------------- + /** + * A call to `marshal.load` + * See https://docs.python.org/3/library/marshal.html#marshal.load + */ + private class MarshalLoadCall extends Decoding::Range, DataFlow::CallCfgNode { + MarshalLoadCall() { this = API::moduleImport("marshal").getMember("load").getACall() } + + override predicate mayExecuteInput() { any() } + + override DataFlow::Node getAnInput() { result = this.getArg(0) } + + override DataFlow::Node getOutput() { result = this } + + override string getFormat() { result = "marshal" } + } + /** * A call to `marshal.loads` * See https://docs.python.org/3/library/marshal.html#marshal.loads diff --git a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py index a57685f9b3c..e468bf51c21 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py +++ b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py @@ -9,7 +9,7 @@ pickle.loads(payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) dec # using this keyword argument is disallowed from Python 3.9 pickle.loads(data=payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput -marshal.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=marshal.load(..) decodeFormat=marshal decodeMayExecuteInput +marshal.load(file_) # $ decodeInput=file_ decodeOutput=marshal.load(..) decodeFormat=marshal decodeMayExecuteInput marshal.loads(payload) # $ decodeInput=payload decodeOutput=marshal.loads(..) decodeFormat=marshal decodeMayExecuteInput From 062250741a0e6264b6521cd6c4393afaa8b35e01 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 8 Oct 2021 00:08:55 +0000 Subject: [PATCH 185/361] Add changed framework coverage reports --- java/documentation/library-coverage/coverage.csv | 2 +- java/documentation/library-coverage/coverage.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index 7d57763fefb..220a9025bff 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -1,5 +1,5 @@ package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:jexl,sink:jndi-injection,sink:ldap,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value -android.content,8,27,61,,,,,,,,,,,,,8,,,,,,27,,4,57 +android.content,8,27,73,,,,,,,,,,,,,8,,,,,,27,,8,65 android.database,59,,30,,,,,,,,,,,,,59,,,,,,,,30, android.net,,,60,,,,,,,,,,,,,,,,,,,,,45,15 android.os,,,82,,,,,,,,,,,,,,,,,,,,,2,80 diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index be2984fa4c0..46a091579c7 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -7,7 +7,7 @@ Java framework & library support :widths: auto Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :sub:`Cleartext transmission` - Android,``android.*``,45,233,70,,,3,67,,, + Android,``android.*``,45,245,70,,,3,67,,, `Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,, `Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,22,,,,,,,, `Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,423,,,,,,,, @@ -19,5 +19,5 @@ Java framework & library support Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2 `Spring <https://spring.io/>`_,``org.springframework.*``,29,469,91,,,,19,14,,29 Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,28,151,,,,14,18,, - Totals,,143,5125,408,13,6,10,107,33,1,66 + Totals,,143,5137,408,13,6,10,107,33,1,66 From 1bec58dee58045ddd5a7bd8030459008e9949b2a Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Fri, 8 Oct 2021 09:41:26 +0200 Subject: [PATCH 186/361] Dataflow: Fix more qldoc: s/accesspath/access path/. --- .../semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll | 4 ++-- .../lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll | 2 +- .../code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll | 4 ++-- .../semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 2 +- .../code/csharp/dataflow/internal/DataFlowImplCommon.qll | 4 ++-- .../semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll | 2 +- .../semmle/code/java/dataflow/internal/DataFlowImplCommon.qll | 4 ++-- .../semmle/code/java/dataflow/internal/DataFlowPrivate.qll | 2 +- .../python/dataflow/new/internal/DataFlowImplCommon.qll | 4 ++-- .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 2 +- 10 files changed, 15 insertions(+), 15 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 aae210452d6..f43a550af57 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -1239,8 +1239,8 @@ class TypedContent extends MkTypedContent { /** * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive accesspath precision - * for such accesspaths. + * be tracked at high precision. This disables adaptive access path precision + * for such access paths. */ predicate forceHighPrecision() { forceHighPrecision(c) } } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 4ccdd3425ab..986197bb0ce 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -242,7 +242,7 @@ int accessPathLimit() { result = 5 } /** * Holds if access paths with `c` at their head always should be tracked at high - * precision. This disables adaptive accesspath precision for such accesspaths. + * precision. This disables adaptive access path precision for such access paths. */ predicate forceHighPrecision(Content c) { none() } 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 aae210452d6..f43a550af57 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 @@ -1239,8 +1239,8 @@ class TypedContent extends MkTypedContent { /** * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive accesspath precision - * for such accesspaths. + * be tracked at high precision. This disables adaptive access path precision + * for such access paths. */ predicate forceHighPrecision() { forceHighPrecision(c) } } 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 23714024459..00996a6ebfc 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 @@ -468,7 +468,7 @@ int accessPathLimit() { result = 5 } /** * Holds if access paths with `c` at their head always should be tracked at high - * precision. This disables adaptive accesspath precision for such accesspaths. + * precision. This disables adaptive access path precision for such access paths. */ predicate forceHighPrecision(Content c) { none() } 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 aae210452d6..f43a550af57 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -1239,8 +1239,8 @@ class TypedContent extends MkTypedContent { /** * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive accesspath precision - * for such accesspaths. + * be tracked at high precision. This disables adaptive access path precision + * for such access paths. */ predicate forceHighPrecision() { forceHighPrecision(c) } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 550bf3bb341..d75afd20b6c 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1920,7 +1920,7 @@ int accessPathLimit() { result = 5 } /** * Holds if access paths with `c` at their head always should be tracked at high - * precision. This disables adaptive accesspath precision for such accesspaths. + * precision. This disables adaptive access path precision for such access paths. */ predicate forceHighPrecision(Content c) { c instanceof ElementContent } 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 aae210452d6..f43a550af57 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -1239,8 +1239,8 @@ class TypedContent extends MkTypedContent { /** * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive accesspath precision - * for such accesspaths. + * be tracked at high precision. This disables adaptive access path precision + * for such access paths. */ predicate forceHighPrecision() { forceHighPrecision(c) } } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index e55a57c7817..94b3cb6614e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -310,7 +310,7 @@ int accessPathLimit() { result = 5 } /** * Holds if access paths with `c` at their head always should be tracked at high - * precision. This disables adaptive accesspath precision for such accesspaths. + * precision. This disables adaptive access path precision for such access paths. */ predicate forceHighPrecision(Content c) { c instanceof ArrayContent or c instanceof CollectionContent 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 aae210452d6..f43a550af57 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -1239,8 +1239,8 @@ class TypedContent extends MkTypedContent { /** * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive accesspath precision - * for such accesspaths. + * be tracked at high precision. This disables adaptive access path precision + * for such access paths. */ predicate forceHighPrecision() { forceHighPrecision(c) } } 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 ba1a230b4ee..1fe40af0dfe 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1622,7 +1622,7 @@ int accessPathLimit() { result = 5 } /** * Holds if access paths with `c` at their head always should be tracked at high - * precision. This disables adaptive accesspath precision for such accesspaths. + * precision. This disables adaptive access path precision for such access paths. */ predicate forceHighPrecision(Content c) { none() } From d79596354e22d325ec1bfb7edc41a08fee5f405c Mon Sep 17 00:00:00 2001 From: ihsinme <ihsinme@gmail.com> Date: Fri, 8 Oct 2021 11:50:45 +0300 Subject: [PATCH 187/361] Update cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql index 5b609697b73..4b147fa3612 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql @@ -49,7 +49,7 @@ predicate conditionsOutsideWrapper(FunctionCall fcp) { not exists(ExprCall ectmp | fcp = ectmp.getAnArgument().getAChild*()) } -/** Held if the conditions for calling `fcp` inside the `fnp` wrapper function are met. */ +/** Holds if the conditions for calling `fcp` inside the `fnp` wrapper function are met. */ pragma[inline] predicate conditionsInsideWrapper(FunctionCall fcp, Function fnp) { not exists(FunctionCall fctmp2 | From 2df30dc10784e7567a05a4384d251ea67059f167 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Fri, 8 Oct 2021 11:48:35 +0200 Subject: [PATCH 188/361] Use InlineFlowTest for local and remote flow tests --- .../dataflow/taintsources/A.java | 35 +++++---- .../dataflow/taintsources/IntentSources.java | 13 +++- .../dataflow/taintsources/RmiFlowImpl.java | 7 +- .../taintsources/SpringMultiPart.java | 30 ++++---- .../taintsources/SpringSavedRequest.java | 26 ++++--- .../dataflow/taintsources/local.expected | 10 --- .../dataflow/taintsources/local.ql | 46 +++++++++--- .../dataflow/taintsources/remote.expected | 74 ------------------- .../dataflow/taintsources/remote.ql | 36 ++++++--- 9 files changed, 124 insertions(+), 153 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/taintsources/A.java b/java/ql/test/library-tests/dataflow/taintsources/A.java index a2c30176c60..25320b315ad 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/A.java +++ b/java/ql/test/library-tests/dataflow/taintsources/A.java @@ -14,36 +14,39 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class A { + + private static void sink(Object o) {} + public static void main(String[] args) { - String[] a = args; // user input - String s = args[0]; // user input + sink(args); // $hasLocalValueFlow + sink(args[0]); // $hasLocalTaintFlow } public static void userInput() throws SQLException, IOException, MalformedURLException { - System.getenv("test"); // user input + sink(System.getenv("test")); // $hasLocalValueFlow class TestServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - req.getParameter("test"); // remote user input - req.getHeader("test"); // remote user input - req.getQueryString(); // remote user input - req.getCookies()[0].getValue(); // remote user input + throws ServletException, IOException { + sink(req.getParameter("test")); // $hasRemoteValueFlow + sink(req.getHeader("test")); // $hasRemoteValueFlow + sink(req.getQueryString()); // $hasRemoteValueFlow + sink(req.getCookies()[0].getValue()); // $hasRemoteValueFlow } } - new Properties().getProperty("test"); // user input - System.getProperty("test"); // user input + sink(new Properties().getProperty("test")); // $hasLocalValueFlow + sink(System.getProperty("test")); // $hasLocalValueFlow new Object() { public void test(ResultSet rs) throws SQLException { - rs.getString(0); // user input + sink(rs.getString(0)); // $hasLocalValueFlow } }; - new URL("test").openConnection().getInputStream(); // remote user input - new Socket("test", 1234).getInputStream(); // remote user input - InetAddress.getByName("test").getHostName(); // remote user input + sink(new URL("test").openConnection().getInputStream()); // $hasRemoteValueFlow + sink(new Socket("test", 1234).getInputStream()); // $hasRemoteValueFlow + sink(InetAddress.getByName("test").getHostName()); // $hasRemoteValueFlow - System.in.read(); // user input - new FileInputStream("test").read(); // user input + sink(System.in); // $hasLocalValueFlow + sink(new FileInputStream("test")); // $hasLocalValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/IntentSources.java b/java/ql/test/library-tests/dataflow/taintsources/IntentSources.java index 6f0051f0d10..17cc6b6a199 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/IntentSources.java +++ b/java/ql/test/library-tests/dataflow/taintsources/IntentSources.java @@ -4,34 +4,39 @@ import android.app.Activity; public class IntentSources extends Activity { + private static void sink(Object o) {} + public void test() throws java.io.IOException { String trouble = this.getIntent().getStringExtra("key"); - Runtime.getRuntime().exec(trouble); + sink(trouble); // $hasRemoteTaintFlow } public void test2() throws java.io.IOException { String trouble = getIntent().getStringExtra("key"); - Runtime.getRuntime().exec(trouble); + sink(trouble); // $hasRemoteTaintFlow } public void test3() throws java.io.IOException { String trouble = getIntent().getExtras().getString("key"); - Runtime.getRuntime().exec(trouble); + sink(trouble); // $hasRemoteTaintFlow } } + class OtherClass { + private static void sink(Object o) {} + public void test(IntentSources is) throws java.io.IOException { String trouble = is.getIntent().getStringExtra("key"); - Runtime.getRuntime().exec(trouble); + sink(trouble); // $hasRemoteTaintFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java b/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java index f75c6ddf2b7..9e814bf7201 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java +++ b/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java @@ -1,15 +1,18 @@ package security.library.dataflow; public class RmiFlowImpl implements RmiFlow { + + private static void sink(Object o) {} + public String listDirectory(String path) throws java.io.IOException { String command = "ls " + path; - Runtime.getRuntime().exec(command); + sink(command); // $hasRemoteTaintFlow return "pretend there are some results here"; } public String notRemotable(String path) throws java.io.IOException { String command = "ls " + path; - Runtime.getRuntime().exec(command); + sink(command); // Safe return "pretend there are some results here"; } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java b/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java index 6702059ab70..33eeced2a4e 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java +++ b/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java @@ -4,22 +4,24 @@ import org.springframework.web.multipart.MultipartRequest; public class SpringMultiPart { MultipartFile file; + private static void sink(Object o) {} + public void test() throws Exception { - file.getBytes(); - file.isEmpty(); - file.getInputStream(); - file.getResource(); - file.getName(); - file.getContentType(); - file.getOriginalFilename(); + sink(file.getBytes()); // $hasRemoteValueFlow + sink(file.isEmpty()); // Safe + sink(file.getInputStream()); // $hasRemoteValueFlow + sink(file.getResource()); // $hasRemoteValueFlow + sink(file.getName()); // $hasRemoteValueFlow + sink(file.getContentType()); // $hasRemoteValueFlow + sink(file.getOriginalFilename()); // $hasRemoteValueFlow } - + public void test(MultipartRequest request) { - request.getFile("name"); - request.getFileMap(); - request.getFileNames(); - request.getFiles("name"); - request.getMultiFileMap(); - request.getMultipartContentType("name"); + sink(request.getFile("name"));// $hasRemoteValueFlow + sink(request.getFileMap());// $hasRemoteValueFlow + sink(request.getFileNames());// $hasRemoteValueFlow + sink(request.getFiles("name"));// $hasRemoteValueFlow + sink(request.getMultiFileMap());// $hasRemoteValueFlow + sink(request.getMultipartContentType("name")); // $hasRemoteValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/SpringSavedRequest.java b/java/ql/test/library-tests/dataflow/taintsources/SpringSavedRequest.java index a4ee8c018a2..e61e0cbb827 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/SpringSavedRequest.java +++ b/java/ql/test/library-tests/dataflow/taintsources/SpringSavedRequest.java @@ -4,23 +4,25 @@ import org.springframework.security.web.savedrequest.SimpleSavedRequest; public class SpringSavedRequest { SavedRequest sr; + private static void sink(Object o) {} + public void test() { - sr.getRedirectUrl(); - sr.getCookies(); - sr.getHeaderValues("name"); - sr.getHeaderNames(); - sr.getParameterValues("name"); - sr.getParameterMap(); + sink(sr.getRedirectUrl()); // $hasRemoteValueFlow + sink(sr.getCookies()); // $hasRemoteValueFlow + sink(sr.getHeaderValues("name")); // $hasRemoteValueFlow + sink(sr.getHeaderNames()); // $hasRemoteValueFlow + sink(sr.getParameterValues("name")); // $hasRemoteValueFlow + sink(sr.getParameterMap()); // $hasRemoteValueFlow } SimpleSavedRequest ssr; public void test2() { - ssr.getRedirectUrl(); - ssr.getCookies(); - ssr.getHeaderValues("name"); - ssr.getHeaderNames(); - ssr.getParameterValues("name"); - ssr.getParameterMap(); + sink(ssr.getRedirectUrl()); // $hasRemoteValueFlow + sink(ssr.getCookies()); // $hasRemoteValueFlow + sink(ssr.getHeaderValues("name")); // $hasRemoteValueFlow + sink(ssr.getHeaderNames()); // $hasRemoteValueFlow + sink(ssr.getParameterValues("name")); // $hasRemoteValueFlow + sink(ssr.getParameterMap()); // $hasRemoteValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/local.expected b/java/ql/test/library-tests/dataflow/taintsources/local.expected index 19e7359357a..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/local.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/local.expected @@ -1,10 +0,0 @@ -| A.java:17:27:17:39 | args | A.java:17:27:17:39 | args | -| A.java:17:27:17:39 | args | A.java:18:18:18:21 | args | -| A.java:17:27:17:39 | args | A.java:19:16:19:19 | args | -| A.java:17:27:17:39 | args | A.java:19:16:19:22 | ...[...] | -| A.java:23:5:23:25 | getenv(...) | A.java:23:5:23:25 | getenv(...) | -| A.java:34:5:34:40 | getProperty(...) | A.java:34:5:34:40 | getProperty(...) | -| A.java:35:5:35:30 | getProperty(...) | A.java:35:5:35:30 | getProperty(...) | -| A.java:38:9:38:23 | getString(...) | A.java:38:9:38:23 | getString(...) | -| A.java:45:5:45:13 | System.in | A.java:45:5:45:13 | System.in | -| A.java:46:5:46:31 | new FileInputStream(...) | A.java:46:5:46:31 | new FileInputStream(...) | diff --git a/java/ql/test/library-tests/dataflow/taintsources/local.ql b/java/ql/test/library-tests/dataflow/taintsources/local.ql index 382b0f706d6..8cf3a34915d 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/local.ql +++ b/java/ql/test/library-tests/dataflow/taintsources/local.ql @@ -1,18 +1,40 @@ import java -import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.FlowSources +import TestUtilities.InlineFlowTest -class Conf extends TaintTracking::Configuration { - Conf() { this = "remote taint conf" } - - override predicate isSource(DataFlow::Node n) { - n instanceof UserInput and - not n instanceof RemoteFlowSource +class LocalSource extends DataFlow::Node { + LocalSource() { + this instanceof UserInput and + not this instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node n) { any() } } -from DataFlow::Node src, DataFlow::Node sink, Conf conf -where conf.hasFlow(src, sink) -select src, sink +class LocalValueConf extends DefaultValueFlowConf { + override predicate isSource(DataFlow::Node n) { n instanceof LocalSource } +} + +class LocalTaintConf extends DefaultTaintFlowConf { + override predicate isSource(DataFlow::Node n) { n instanceof LocalSource } +} + +class LocalFlowTest extends InlineFlowTest { + override string getARelevantTag() { result = ["hasLocalValueFlow", "hasLocalTaintFlow"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasLocalValueFlow" and + exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + or + tag = "hasLocalTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink | + getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.expected b/java/ql/test/library-tests/dataflow/taintsources/remote.expected index c6b22148e24..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.expected @@ -1,74 +0,0 @@ -| A.java:28:9:28:32 | getParameter(...) | A.java:28:9:28:32 | getParameter(...) | -| A.java:29:9:29:29 | getHeader(...) | A.java:29:9:29:29 | getHeader(...) | -| A.java:30:9:30:28 | getQueryString(...) | A.java:30:9:30:28 | getQueryString(...) | -| A.java:31:9:31:38 | getValue(...) | A.java:31:9:31:38 | getValue(...) | -| A.java:41:5:41:53 | getInputStream(...) | A.java:41:5:41:53 | getInputStream(...) | -| A.java:42:5:42:45 | getInputStream(...) | A.java:42:5:42:45 | getInputStream(...) | -| A.java:43:5:43:47 | getHostName(...) | A.java:43:5:43:47 | getHostName(...) | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | -| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:35 | getIntent(...) | -| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:57 | getStringExtra(...) | -| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:10:29:10:35 | trouble | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | -| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:30 | getIntent(...) | -| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:52 | getStringExtra(...) | -| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:17:29:17:35 | trouble | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | [summary] read: android.content.Intent.extras of argument -1 in getExtras | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | [summary] to write: return (return) in getExtras | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | parameter this | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] read: <map.value> of argument -1 in getString | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] to write: return (return) in getString | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | parameter this | -| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:30 | getIntent(...) | -| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:42 | getExtras(...) | -| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:59 | getString(...) | -| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:24:29:24:35 | trouble | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | -| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:33 | getIntent(...) | -| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:55 | getStringExtra(...) | -| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:34:29:34:35 | trouble | -| PlayResource.java:19:37:19:46 | uri | PlayResource.java:19:37:19:46 | uri | -| PlayResource.java:20:18:20:48 | getQueryString(...) | ../../../stubs/playframework-2.6.x/play/mvc/Results.java:634:33:634:42 | url | -| PlayResource.java:20:18:20:48 | getQueryString(...) | PlayResource.java:20:18:20:48 | getQueryString(...) | -| PlayResource.java:20:18:20:48 | getQueryString(...) | PlayResource.java:21:21:21:23 | url | -| PlayResource.java:24:42:24:53 | token | ../../../stubs/playframework-2.6.x/play/mvc/Results.java:94:27:94:40 | content | -| PlayResource.java:24:42:24:53 | token | PlayResource.java:24:42:24:53 | token | -| PlayResource.java:24:42:24:53 | token | PlayResource.java:25:30:25:34 | token | -| PlayResource.java:28:56:28:65 | uri | PlayResource.java:28:56:28:65 | uri | -| RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:4:30:4:40 | path | -| RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:5:20:5:31 | ... + ... | -| RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:5:28:5:31 | path | -| RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:6:29:6:35 | command | -| SpringMultiPart.java:8:3:8:17 | getBytes(...) | SpringMultiPart.java:8:3:8:17 | getBytes(...) | -| SpringMultiPart.java:10:3:10:23 | getInputStream(...) | SpringMultiPart.java:10:3:10:23 | getInputStream(...) | -| SpringMultiPart.java:11:3:11:20 | getResource(...) | SpringMultiPart.java:11:3:11:20 | getResource(...) | -| SpringMultiPart.java:12:3:12:16 | getName(...) | SpringMultiPart.java:12:3:12:16 | getName(...) | -| SpringMultiPart.java:13:3:13:23 | getContentType(...) | SpringMultiPart.java:13:3:13:23 | getContentType(...) | -| SpringMultiPart.java:14:3:14:28 | getOriginalFilename(...) | SpringMultiPart.java:14:3:14:28 | getOriginalFilename(...) | -| SpringMultiPart.java:18:3:18:25 | getFile(...) | SpringMultiPart.java:18:3:18:25 | getFile(...) | -| SpringMultiPart.java:19:3:19:22 | getFileMap(...) | SpringMultiPart.java:19:3:19:22 | getFileMap(...) | -| SpringMultiPart.java:20:3:20:24 | getFileNames(...) | SpringMultiPart.java:20:3:20:24 | getFileNames(...) | -| SpringMultiPart.java:21:3:21:26 | getFiles(...) | SpringMultiPart.java:21:3:21:26 | getFiles(...) | -| SpringMultiPart.java:22:3:22:27 | getMultiFileMap(...) | SpringMultiPart.java:22:3:22:27 | getMultiFileMap(...) | -| SpringMultiPart.java:23:3:23:41 | getMultipartContentType(...) | SpringMultiPart.java:23:3:23:41 | getMultipartContentType(...) | -| SpringSavedRequest.java:8:3:8:21 | getRedirectUrl(...) | SpringSavedRequest.java:8:3:8:21 | getRedirectUrl(...) | -| SpringSavedRequest.java:9:3:9:17 | getCookies(...) | SpringSavedRequest.java:9:3:9:17 | getCookies(...) | -| SpringSavedRequest.java:10:3:10:28 | getHeaderValues(...) | SpringSavedRequest.java:10:3:10:28 | getHeaderValues(...) | -| SpringSavedRequest.java:11:3:11:21 | getHeaderNames(...) | SpringSavedRequest.java:11:3:11:21 | getHeaderNames(...) | -| SpringSavedRequest.java:12:3:12:31 | getParameterValues(...) | SpringSavedRequest.java:12:3:12:31 | getParameterValues(...) | -| SpringSavedRequest.java:13:3:13:22 | getParameterMap(...) | SpringSavedRequest.java:13:3:13:22 | getParameterMap(...) | -| SpringSavedRequest.java:19:3:19:22 | getRedirectUrl(...) | SpringSavedRequest.java:19:3:19:22 | getRedirectUrl(...) | -| SpringSavedRequest.java:20:3:20:18 | getCookies(...) | SpringSavedRequest.java:20:3:20:18 | getCookies(...) | -| SpringSavedRequest.java:21:3:21:29 | getHeaderValues(...) | SpringSavedRequest.java:21:3:21:29 | getHeaderValues(...) | -| SpringSavedRequest.java:22:3:22:22 | getHeaderNames(...) | SpringSavedRequest.java:22:3:22:22 | getHeaderNames(...) | -| SpringSavedRequest.java:23:3:23:32 | getParameterValues(...) | SpringSavedRequest.java:23:3:23:32 | getParameterValues(...) | -| SpringSavedRequest.java:24:3:24:23 | getParameterMap(...) | SpringSavedRequest.java:24:3:24:23 | getParameterMap(...) | diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.ql b/java/ql/test/library-tests/dataflow/taintsources/remote.ql index 9466939ab1b..afb05e91893 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.ql +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.ql @@ -1,15 +1,33 @@ import java -import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.FlowSources +import TestUtilities.InlineFlowTest -class Conf extends TaintTracking::Configuration { - Conf() { this = "remote taint conf" } - +class RemoteValueConf extends DefaultValueFlowConf { override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node n) { any() } } -from DataFlow::Node src, DataFlow::Node sink, Conf conf -where conf.hasFlow(src, sink) -select src, sink +class RemoteTaintConf extends DefaultTaintFlowConf { + override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource } +} + +class RemoteFlowTest extends InlineFlowTest { + override string getARelevantTag() { result = ["hasRemoteValueFlow", "hasRemoteTaintFlow"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasRemoteValueFlow" and + exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + or + tag = "hasRemoteTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink | + getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} From 42980a1ab4646ff8d9e380c83f0270a2c5a3f148 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> Date: Fri, 8 Oct 2021 09:07:05 +0200 Subject: [PATCH 189/361] Python: Model `shelve.open` --- .../lib/semmle/python/frameworks/Stdlib.qll | 36 +++++++++++++++++++ .../frameworks/stdlib/Decoding.py | 4 +-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index c045e8fdb7f..6e04e06aefb 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -498,6 +498,42 @@ private module StdlibPrivate { override string getFormat() { result = "pickle" } } + // --------------------------------------------------------------------------- + // shelve + // --------------------------------------------------------------------------- + /** + * A call to `shelve.open` + * See https://docs.python.org/3/library/shelve.html#shelve.open + * + * Claiming there is decoding of the input to `shelve.open` is a bit questionable, since + * it's not the filename, but the contents of the file that is decoded. + * + * However, we definitely want to be able to alert if a user is able to control what + * file is used, since that can lead to code execution (even if that file is free of + * path injection). + * + * So right now the best way we have of modeling this seems to be to treat the filename + * argument as being deserialized... + */ + private class ShelveOpenCall extends Decoding::Range, FileSystemAccess::Range, + DataFlow::CallCfgNode { + ShelveOpenCall() { this = API::moduleImport("shelve").getMember("open").getACall() } + + override predicate mayExecuteInput() { any() } + + override DataFlow::Node getAnInput() { + result in [this.getArg(0), this.getArgByName("filename")] + } + + override DataFlow::Node getAPathArgument() { + result in [this.getArg(0), this.getArgByName("filename")] + } + + override DataFlow::Node getOutput() { result = this } + + override string getFormat() { result = "pickle" } + } + // --------------------------------------------------------------------------- // popen2 // --------------------------------------------------------------------------- diff --git a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py index e468bf51c21..0044de07add 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py +++ b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py @@ -15,8 +15,8 @@ marshal.loads(payload) # $ decodeInput=payload decodeOutput=marshal.loads(..) d # if the file opened has been controlled by an attacker, this can lead to code # execution. (underlying file format is pickle) -shelve.open(filepath) # $ MISSING: decodeInput=filepath decodeOutput=shelve.open(..) decodeFormat=pickle decodeMayExecuteInput getAPathArgument=filepath -shelve.open(filename=filepath) # $ MISSING: decodeInput=filepath decodeOutput=shelve.open(..) decodeFormat=pickle decodeMayExecuteInput getAPathArgument=filepath +shelve.open(filepath) # $ decodeInput=filepath decodeOutput=shelve.open(..) decodeFormat=pickle decodeMayExecuteInput getAPathArgument=filepath +shelve.open(filename=filepath) # $ decodeInput=filepath decodeOutput=shelve.open(..) decodeFormat=pickle decodeMayExecuteInput getAPathArgument=filepath # TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py base64.b64decode(payload) # $ decodeInput=payload decodeOutput=base64.b64decode(..) decodeFormat=Base64 From f9333fc5513b87f56703064ff4e0d24732abfeea Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Oct 2021 09:32:34 +0200 Subject: [PATCH 190/361] Python: Expand `dill` tests --- python/ql/test/library-tests/frameworks/dill/Decoding.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/ql/test/library-tests/frameworks/dill/Decoding.py b/python/ql/test/library-tests/frameworks/dill/Decoding.py index 49eb551af04..3a8d4dc8da3 100644 --- a/python/ql/test/library-tests/frameworks/dill/Decoding.py +++ b/python/ql/test/library-tests/frameworks/dill/Decoding.py @@ -1,3 +1,6 @@ import dill -dill.loads(payload) # $decodeInput=payload decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput +dill.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput +dill.load(file=file_) # $ MISSING: decodeInput=file_ decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput +dill.loads(payload) # $ decodeInput=payload decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput +dill.loads(str=payload) # $ decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput MISSING: decodeInput=payload From 9180257afec24710fa2f177f20536a6d3414678c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Oct 2021 09:37:39 +0200 Subject: [PATCH 191/361] Python: Refactor `Dill.qll` So it matches the layout of all our other qll modules modeling a PyPI package. --- .../ql/lib/semmle/python/frameworks/Dill.qll | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Dill.qll b/python/ql/lib/semmle/python/frameworks/Dill.qll index 94af905756b..2ee66046e36 100644 --- a/python/ql/lib/semmle/python/frameworks/Dill.qll +++ b/python/ql/lib/semmle/python/frameworks/Dill.qll @@ -1,5 +1,5 @@ /** - * Provides classes modeling security-relevant aspects of the 'dill' package. + * Provides classes modeling security-relevant aspects of the `dill` PyPI package. * See https://pypi.org/project/dill/. */ @@ -10,18 +10,24 @@ private import semmle.python.Concepts private import semmle.python.ApiGraphs /** - * A call to `dill.loads` - * See https://pypi.org/project/dill/ (which currently refers you - * to https://docs.python.org/3/library/pickle.html#pickle.loads) + * Provides models for the `dill` PyPI package. + * See https://pypi.org/project/dill/. */ -private class DillLoadsCall extends Decoding::Range, DataFlow::CallCfgNode { - DillLoadsCall() { this = API::moduleImport("dill").getMember("loads").getACall() } +private module Dill { + /** + * A call to `dill.loads` + * See https://pypi.org/project/dill/ (which currently refers you + * to https://docs.python.org/3/library/pickle.html#pickle.loads) + */ + private class DillLoadsCall extends Decoding::Range, DataFlow::CallCfgNode { + DillLoadsCall() { this = API::moduleImport("dill").getMember("loads").getACall() } - override predicate mayExecuteInput() { any() } + override predicate mayExecuteInput() { any() } - override DataFlow::Node getAnInput() { result = this.getArg(0) } + override DataFlow::Node getAnInput() { result = this.getArg(0) } - override DataFlow::Node getOutput() { result = this } + override DataFlow::Node getOutput() { result = this } - override string getFormat() { result = "dill" } + override string getFormat() { result = "dill" } + } } From 4820be3b10729ab87b6cbe20d433ed4aafb6d1c4 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Oct 2021 09:38:34 +0200 Subject: [PATCH 192/361] Python: Model keyword arguments to `dill.loads` --- python/ql/lib/semmle/python/frameworks/Dill.qll | 2 +- python/ql/test/library-tests/frameworks/dill/Decoding.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Dill.qll b/python/ql/lib/semmle/python/frameworks/Dill.qll index 2ee66046e36..1b07da7aac9 100644 --- a/python/ql/lib/semmle/python/frameworks/Dill.qll +++ b/python/ql/lib/semmle/python/frameworks/Dill.qll @@ -24,7 +24,7 @@ private module Dill { override predicate mayExecuteInput() { any() } - override DataFlow::Node getAnInput() { result = this.getArg(0) } + override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("str")] } override DataFlow::Node getOutput() { result = this } diff --git a/python/ql/test/library-tests/frameworks/dill/Decoding.py b/python/ql/test/library-tests/frameworks/dill/Decoding.py index 3a8d4dc8da3..87ad1fa6e33 100644 --- a/python/ql/test/library-tests/frameworks/dill/Decoding.py +++ b/python/ql/test/library-tests/frameworks/dill/Decoding.py @@ -3,4 +3,4 @@ import dill dill.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput dill.load(file=file_) # $ MISSING: decodeInput=file_ decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput dill.loads(payload) # $ decodeInput=payload decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput -dill.loads(str=payload) # $ decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput MISSING: decodeInput=payload +dill.loads(str=payload) # $ decodeInput=payload decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput From 75b06d8a256bb0427982ebeb1913920d05363487 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Oct 2021 09:40:21 +0200 Subject: [PATCH 193/361] Python: Model `dill.load` --- python/ql/lib/semmle/python/frameworks/Dill.qll | 17 +++++++++++++++++ .../library-tests/frameworks/dill/Decoding.py | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Dill.qll b/python/ql/lib/semmle/python/frameworks/Dill.qll index 1b07da7aac9..168542272f9 100644 --- a/python/ql/lib/semmle/python/frameworks/Dill.qll +++ b/python/ql/lib/semmle/python/frameworks/Dill.qll @@ -14,6 +14,23 @@ private import semmle.python.ApiGraphs * See https://pypi.org/project/dill/. */ private module Dill { + /** + * A call to `dill.load` + * See https://pypi.org/project/dill/ (which currently refers you + * to https://docs.python.org/3/library/pickle.html#pickle.load) + */ + private class DillLoadCall extends Decoding::Range, DataFlow::CallCfgNode { + DillLoadCall() { this = API::moduleImport("dill").getMember("load").getACall() } + + override predicate mayExecuteInput() { any() } + + override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("file")] } + + override DataFlow::Node getOutput() { result = this } + + override string getFormat() { result = "dill" } + } + /** * A call to `dill.loads` * See https://pypi.org/project/dill/ (which currently refers you diff --git a/python/ql/test/library-tests/frameworks/dill/Decoding.py b/python/ql/test/library-tests/frameworks/dill/Decoding.py index 87ad1fa6e33..bcbd6ff4b35 100644 --- a/python/ql/test/library-tests/frameworks/dill/Decoding.py +++ b/python/ql/test/library-tests/frameworks/dill/Decoding.py @@ -1,6 +1,6 @@ import dill -dill.load(file_) # $ MISSING: decodeInput=file_ decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput -dill.load(file=file_) # $ MISSING: decodeInput=file_ decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput +dill.load(file_) # $ decodeInput=file_ decodeOutput=dill.load(..) decodeFormat=dill decodeMayExecuteInput +dill.load(file=file_) # $ decodeInput=file_ decodeOutput=dill.load(..) decodeFormat=dill decodeMayExecuteInput dill.loads(payload) # $ decodeInput=payload decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput dill.loads(str=payload) # $ decodeInput=payload decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput From 5e6f042f6eadf1c7d523d966c57aabdc9d740a1c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Oct 2021 11:51:43 +0200 Subject: [PATCH 194/361] Python: Model `pickle.Unpickler` --- .../ql/lib/semmle/python/frameworks/Stdlib.qll | 16 ++++++++++++++++ .../library-tests/frameworks/stdlib/Decoding.py | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 6e04e06aefb..f89f74f3c34 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -498,6 +498,22 @@ private module StdlibPrivate { override string getFormat() { result = "pickle" } } + /** + * A construction of a `pickle.Unpickler` + * See https://docs.python.org/3/library/pickle.html#pickle.Unpickler + */ + private class PickleUnpicklerCall extends Decoding::Range, DataFlow::CallCfgNode { + PickleUnpicklerCall() { this = pickle().getMember("Unpickler").getACall() } + + override predicate mayExecuteInput() { any() } + + override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("file")] } + + override DataFlow::Node getOutput() { result = this.getAMethodCall("load") } + + override string getFormat() { result = "pickle" } + } + // --------------------------------------------------------------------------- // shelve // --------------------------------------------------------------------------- diff --git a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py index 0044de07add..e9e811ffc97 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/Decoding.py +++ b/python/ql/test/library-tests/frameworks/stdlib/Decoding.py @@ -9,6 +9,14 @@ pickle.loads(payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) dec # using this keyword argument is disallowed from Python 3.9 pickle.loads(data=payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput +# We don't really have a good way to model a decode happening over multiple statements +# like this. Since the important bit for `py/unsafe-deserialization` is the input, that +# is the main focus. We do a best effort to model the output though (but that will only +# work in local scope). +unpickler = pickle.Unpickler(file_) # $ decodeInput=file_ decodeFormat=pickle decodeMayExecuteInput +unpickler.load() # $ decodeOutput=unpickler.load() +unpickler = pickle.Unpickler(file=file_) # $ decodeInput=file_ decodeFormat=pickle decodeMayExecuteInput + marshal.load(file_) # $ decodeInput=file_ decodeOutput=marshal.load(..) decodeFormat=marshal decodeMayExecuteInput marshal.loads(payload) # $ decodeInput=payload decodeOutput=marshal.loads(..) decodeFormat=marshal decodeMayExecuteInput From fd0c386a4cacee21e106b4d4bca5f9ed57ef0cf8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Oct 2021 12:06:18 +0200 Subject: [PATCH 195/361] Python: Add change-note --- .../2021-10-08-improve-pickle-dill-shelve-modeling.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 python/change-notes/2021-10-08-improve-pickle-dill-shelve-modeling.md diff --git a/python/change-notes/2021-10-08-improve-pickle-dill-shelve-modeling.md b/python/change-notes/2021-10-08-improve-pickle-dill-shelve-modeling.md new file mode 100644 index 00000000000..48c868ee416 --- /dev/null +++ b/python/change-notes/2021-10-08-improve-pickle-dill-shelve-modeling.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Improved modeling of decoding through pickle related functions (which can lead to code execution), resulting in additional sinks for the _Deserializing untrusted input_ query (`py/unsafe-deserialization`). Now we fully support `pickle.load`, `pickle.loads`, `pickle.Unpickler`, `marshal.load`, `marshal.loads`, `dill.load`, `dill.loads`, `shelve.open`. From 8c42545d1cf9902202ef47b180b1bf2b06b7be28 Mon Sep 17 00:00:00 2001 From: ihsinme <ihsinme@gmail.com> Date: Fri, 8 Oct 2021 13:10:36 +0300 Subject: [PATCH 196/361] Update FindWrapperFunctions.qhelp --- .../Security/CWE/CWE-1041/FindWrapperFunctions.qhelp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp index 1eb5b3e5e5c..109a806a5b8 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp @@ -14,5 +14,10 @@ </example> <references> +<li> + CERT C Coding Standard: + <a href="https://wiki.sei.cmu.edu/confluence/display/java/JNI00-J.+Define+wrappers+around+native+methods">JNI00-J. Define wrappers around native methods</a>. +</li> + </references> </qhelp> From dd95131630b3fea9b738e67b9106b2a05470caed Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 8 Oct 2021 14:28:42 +0100 Subject: [PATCH 197/361] C++: Test spacing. --- .../semmle/TOCTOUFilesystemRace.expected | 12 ++--- .../Security/CWE/CWE-367/semmle/test2.cpp | 52 +++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/TOCTOUFilesystemRace.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/TOCTOUFilesystemRace.expected index f0f7aaaefee..6de0b3a68ce 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/TOCTOUFilesystemRace.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/TOCTOUFilesystemRace.expected @@ -5,9 +5,9 @@ | test2.cpp:130:7:130:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:130:13:130:16 | path | filename | test2.cpp:128:21:128:27 | buf_ptr | checked | | test2.cpp:157:7:157:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:157:12:157:15 | path | filename | test2.cpp:155:6:155:9 | call to stat | checked | | test2.cpp:170:7:170:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:170:12:170:15 | path | filename | test2.cpp:168:6:168:10 | call to lstat | checked | -| test2.cpp:245:3:245:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:245:9:245:12 | path | filename | test2.cpp:238:6:238:10 | call to fopen | checked | -| test2.cpp:277:7:277:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:277:13:277:16 | path | filename | test2.cpp:275:6:275:11 | call to access | checked | -| test2.cpp:303:7:303:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:303:13:303:16 | path | filename | test2.cpp:301:7:301:12 | call to access | checked | -| test2.cpp:317:7:317:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:317:13:317:16 | path | filename | test2.cpp:313:6:313:11 | call to access | checked | -| test2.cpp:348:3:348:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:348:9:348:12 | path | filename | test2.cpp:341:6:341:10 | call to fopen | checked | -| test2.cpp:356:3:356:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:356:9:356:13 | path2 | filename | test2.cpp:354:7:354:12 | call to rename | checked | +| test2.cpp:297:3:297:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:297:9:297:12 | path | filename | test2.cpp:290:6:290:10 | call to fopen | checked | +| test2.cpp:329:7:329:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:329:13:329:16 | path | filename | test2.cpp:327:6:327:11 | call to access | checked | +| test2.cpp:355:7:355:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:355:13:355:16 | path | filename | test2.cpp:353:7:353:12 | call to access | checked | +| test2.cpp:369:7:369:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:369:13:369:16 | path | filename | test2.cpp:365:6:365:11 | call to access | checked | +| test2.cpp:400:3:400:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:400:9:400:12 | path | filename | test2.cpp:393:6:393:10 | call to fopen | checked | +| test2.cpp:408:3:408:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:408:9:408:13 | path2 | filename | test2.cpp:406:7:406:12 | call to rename | checked | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp index e1317e9a9ca..40b3929f81b 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp @@ -199,6 +199,58 @@ void test2_10(int dir, const char *path, int arg) // ... } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // --- open -> stat --- void test3_1(const char *path, int arg) From 1c56573194c00c3b1f44428eb7e628f073dfbc83 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 8 Oct 2021 14:30:27 +0100 Subject: [PATCH 198/361] C++: Add tests. --- .../semmle/TOCTOUFilesystemRace.expected | 4 + .../Security/CWE/CWE-367/semmle/test2.cpp | 84 +++++++++---------- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/TOCTOUFilesystemRace.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/TOCTOUFilesystemRace.expected index 6de0b3a68ce..413d3dbccf9 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/TOCTOUFilesystemRace.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/TOCTOUFilesystemRace.expected @@ -5,6 +5,10 @@ | test2.cpp:130:7:130:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:130:13:130:16 | path | filename | test2.cpp:128:21:128:27 | buf_ptr | checked | | test2.cpp:157:7:157:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:157:12:157:15 | path | filename | test2.cpp:155:6:155:9 | call to stat | checked | | test2.cpp:170:7:170:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:170:12:170:15 | path | filename | test2.cpp:168:6:168:10 | call to lstat | checked | +| test2.cpp:209:7:209:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:209:12:209:15 | path | filename | test2.cpp:207:6:207:9 | call to stat | checked | +| test2.cpp:228:8:228:11 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:228:13:228:16 | path | filename | test2.cpp:224:6:224:9 | call to stat | checked | +| test2.cpp:228:8:228:11 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:228:13:228:16 | path | filename | test2.cpp:226:7:226:9 | buf | checked | +| test2.cpp:249:6:249:10 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:249:12:249:15 | path | filename | test2.cpp:244:6:244:9 | call to stat | checked | | test2.cpp:297:3:297:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:297:9:297:12 | path | filename | test2.cpp:290:6:290:10 | call to fopen | checked | | test2.cpp:329:7:329:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:329:13:329:16 | path | filename | test2.cpp:327:6:327:11 | call to access | checked | | test2.cpp:355:7:355:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:355:13:355:16 | path | filename | test2.cpp:353:7:353:12 | call to access | checked | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp index 40b3929f81b..14875b9d367 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp @@ -199,57 +199,57 @@ void test2_10(int dir, const char *path, int arg) // ... } +void test2_11(const char *path, int arg) +{ + stat_data buf; + int f; + if (stat(path, &buf)) + { + f = open(path, arg); // GOOD (here stat is just a redundant check that the file exists / path is valid, confirmed by the return value of open) [FALSE POSITIVE] + if (f == -1) + { + // handle error + } + // ... + } +} +void test2_12(const char *path, int arg) +{ + stat_data buf; + int f; + if (stat(path, &buf)) + { + if (buf.foo == 11) // check a property of the file + { + f = open(path, arg); // BAD + if (f == -1) + { + // handle error + } + } + // ... + } +} +void test2_13(const char *path, int arg) +{ + stat_data buf; + FILE *f; + if (stat(path, &buf)) // check the file does *not* exist + { + return; + } + f = fopen(path, "wt"); // BAD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // ... +} // --- open -> stat --- From 2185a654de3954418dfa4fd2379d8b5197b8cafe Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Fri, 8 Oct 2021 15:53:14 +0200 Subject: [PATCH 199/361] Java: Fix some performance issues. --- .../Likely Bugs/Collections/IteratorRemoveMayFail.ql | 4 ++-- java/ql/src/Likely Bugs/Comparison/StringComparison.ql | 10 +++++++--- java/ql/src/Performance/InnerClassCouldBeStatic.ql | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/java/ql/src/Likely Bugs/Collections/IteratorRemoveMayFail.ql b/java/ql/src/Likely Bugs/Collections/IteratorRemoveMayFail.ql index a4d15a4e370..b350eecae7f 100644 --- a/java/ql/src/Likely Bugs/Collections/IteratorRemoveMayFail.ql +++ b/java/ql/src/Likely Bugs/Collections/IteratorRemoveMayFail.ql @@ -30,7 +30,7 @@ predicate containsSpecialCollection(Expr e, SpecialCollectionCreation origin) { e = origin or exists(Variable v | - containsSpecialCollection(v.getAnAssignedValue(), origin) and + containsSpecialCollection(pragma[only_bind_into](v.getAnAssignedValue()), origin) and e = v.getAnAccess() ) or @@ -52,7 +52,7 @@ predicate iterOfSpecialCollection(Expr e, SpecialCollectionCreation origin) { ) or exists(Variable v | - iterOfSpecialCollection(v.getAnAssignedValue(), origin) and + iterOfSpecialCollection(pragma[only_bind_into](v.getAnAssignedValue()), origin) and e = v.getAnAccess() ) or diff --git a/java/ql/src/Likely Bugs/Comparison/StringComparison.ql b/java/ql/src/Likely Bugs/Comparison/StringComparison.ql index 4681feafc00..fc6e8dce7b5 100644 --- a/java/ql/src/Likely Bugs/Comparison/StringComparison.ql +++ b/java/ql/src/Likely Bugs/Comparison/StringComparison.ql @@ -41,10 +41,8 @@ class StringValue extends Expr { } } -predicate variableValuesInterned(Variable v) { +predicate candidateVariable(Variable v) { v.fromSource() and - // All assignments to variables are interned. - forall(StringValue sv | sv = v.getAnAssignedValue() | sv.isInterned()) and // For parameters, assume they could be non-interned. not v instanceof Parameter and // If the string is modified with `+=`, then the new string is not interned @@ -52,6 +50,12 @@ predicate variableValuesInterned(Variable v) { not exists(AssignOp append | append.getDest() = v.getAnAccess()) } +predicate variableValuesInterned(Variable v) { + candidateVariable(v) and + // All assignments to variables are interned. + forall(StringValue sv | sv = v.getAnAssignedValue() | sv.isInterned()) +} + from EqualityTest e, StringValue lhs, StringValue rhs where e.getLeftOperand() = lhs and diff --git a/java/ql/src/Performance/InnerClassCouldBeStatic.ql b/java/ql/src/Performance/InnerClassCouldBeStatic.ql index 2160916c3ea..ec7dd944d7c 100644 --- a/java/ql/src/Performance/InnerClassCouldBeStatic.ql +++ b/java/ql/src/Performance/InnerClassCouldBeStatic.ql @@ -17,6 +17,7 @@ import java * since package-protected fields are not inherited by classes in different * packages, but it's enough for the purposes of this check. */ +pragma[nomagic] predicate inherits(Class c, Field f) { f = c.getAField() or From 705970cedde66acfd380057e4e95cef8f8963c7d Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Fri, 8 Oct 2021 16:57:36 +0200 Subject: [PATCH 200/361] Python: Update tests to use correct tag --- .../module-initialization/multiphase.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py index afb167d2099..a9c59cf78d1 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py +++ b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py @@ -14,21 +14,21 @@ def is_source(x): #$ importTimeFlow="ModuleVariableNode for Global Variable is_ def SINK(x): #$ importTimeFlow="ModuleVariableNode for Global Variable SINK in Module multiphase" - if is_source(x): #$ runtimFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-17 -> is_source" - print("OK") #$ runtimFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-18 -> print" + if is_source(x): #$ runtimeFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-17 -> is_source" + print("OK") #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-18 -> print" else: - print("Unexpected flow", x) #$ runtimFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-20 -> print" + print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-20 -> print" def SINK_F(x): - if is_source(x): #$ runtimFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-24 -> is_source" - print("Unexpected flow", x) #$ runtimFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-25 -> print" + if is_source(x): #$ runtimeFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-24 -> is_source" + print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-25 -> print" else: - print("OK") #$ runtimFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-27 -> print" + print("OK") #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-27 -> print" def set_foo(): #$ importTimeFlow="ModuleVariableNode for Global Variable set_foo in Module multiphase" global foo - foo = SOURCE #$ runtimFlow="ModuleVariableNode for Global Variable SOURCE in Module multiphase, l:-31 -> SOURCE" MISSING:importTimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase" + foo = SOURCE #$ runtimeFlow="ModuleVariableNode for Global Variable SOURCE in Module multiphase, l:-31 -> SOURCE" MISSING:importTimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase" foo = NONSOURCE #$ importTimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase" set_foo() @@ -36,7 +36,7 @@ set_foo() @expects(2) def test_phases(): global foo - SINK(foo) #$ runtimFlow="ModuleVariableNode for Global Variable SINK in Module multiphase, l:-39 -> SINK" runtimFlow="ModuleVariableNode for Global Variable foo in Module multiphase, l:-39 -> foo" - foo = NONSOURCE #$ runtimFlow="ModuleVariableNode for Global Variable NONSOURCE in Module multiphase, l:-40 -> NONSOURCE" - set_foo() #$ runtimFlow="ModuleVariableNode for Global Variable set_foo in Module multiphase, l:-41 -> set_foo" - SINK(foo) #$ runtimFlow="ModuleVariableNode for Global Variable SINK in Module multiphase, l:-42 -> SINK" runtimFlow="ModuleVariableNode for Global Variable foo in Module multiphase, l:-42 -> foo" + SINK(foo) #$ runtimeFlow="ModuleVariableNode for Global Variable SINK in Module multiphase, l:-39 -> SINK" runtimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase, l:-39 -> foo" + foo = NONSOURCE #$ runtimeFlow="ModuleVariableNode for Global Variable NONSOURCE in Module multiphase, l:-40 -> NONSOURCE" + set_foo() #$ runtimeFlow="ModuleVariableNode for Global Variable set_foo in Module multiphase, l:-41 -> set_foo" + SINK(foo) #$ runtimeFlow="ModuleVariableNode for Global Variable SINK in Module multiphase, l:-42 -> SINK" runtimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase, l:-42 -> foo" From 15476c2513870203c8bdf44bc7a955a20f8cfc6c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Oct 2021 18:20:14 +0200 Subject: [PATCH 201/361] Python: Add data-flow tests for BoolExp > 6.11. Boolean operations > The expression x and y first evaluates x; if x is false, its value is > returned; otherwise, y is evaluated and the resulting value is > returned. > The expression x or y first evaluates x; if x is true, its value is > returned; otherwise, y is evaluated and the resulting value is > returned. --- .../ql/test/experimental/dataflow/coverage/test.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 906ece07952..43820495276 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -422,6 +422,18 @@ def test_call_extra_keyword_flow(): SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" +# 6.11. Boolean operations + +def test_or(x = False): + # if we don't know the value of the lhs, we should always add flow + SINK(x or SOURCE) #$ MISSING: flow="SOURCE -> BoolExp" + + +def test_and(x = True): + # if we don't know the value of the lhs, we should always add flow + SINK(x and SOURCE) #$ MISSING: flow="SOURCE -> BoolExp" + + # 6.12. Assignment expressions def test_assignment_expression(): x = NONSOURCE From a50b193c406b7fd1d7d1bd58bc3f434f096ecb6d Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Oct 2021 18:30:09 +0200 Subject: [PATCH 202/361] Python: Model data-flow for `x or y` and `x and y` --- .../2021-10-08-add-dataflow-for-boolean-expressions.md | 3 +++ .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 3 +++ python/ql/test/experimental/dataflow/coverage/test.py | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 python/change-notes/2021-10-08-add-dataflow-for-boolean-expressions.md diff --git a/python/change-notes/2021-10-08-add-dataflow-for-boolean-expressions.md b/python/change-notes/2021-10-08-add-dataflow-for-boolean-expressions.md new file mode 100644 index 00000000000..ba90b6ec9f2 --- /dev/null +++ b/python/change-notes/2021-10-08-add-dataflow-for-boolean-expressions.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* Added data-flow from `x` in both `x or y` and `x and y`, as described in the + [Python Language Reference](https://docs.python.org/3/reference/expressions.html#boolean-operations). 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 44c64234b75..7c90bc1189a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -200,6 +200,9 @@ module EssaFlow { // If expressions nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand() or + // boolean inline expressions such as `x or y` or `x and y` + nodeFrom.asCfgNode() = nodeTo.asCfgNode().(BoolExprNode).getAnOperand() + or // Flow inside an unpacking assignment iterableUnpackingFlowStep(nodeFrom, nodeTo) or diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 43820495276..751adde20d8 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -426,12 +426,12 @@ def test_call_extra_keyword_flow(): def test_or(x = False): # if we don't know the value of the lhs, we should always add flow - SINK(x or SOURCE) #$ MISSING: flow="SOURCE -> BoolExp" + SINK(x or SOURCE) #$ flow="SOURCE -> BoolExpr" def test_and(x = True): # if we don't know the value of the lhs, we should always add flow - SINK(x and SOURCE) #$ MISSING: flow="SOURCE -> BoolExp" + SINK(x and SOURCE) #$ flow="SOURCE -> BoolExpr" # 6.12. Assignment expressions From 5b26d41d27983abc6a1151e90715da716cd86cf5 Mon Sep 17 00:00:00 2001 From: Henry Mercer <henrymercer@github.com> Date: Thu, 7 Oct 2021 18:40:43 +0100 Subject: [PATCH 203/361] C++: Improve SARIF severity level reporting of extractor diagnostics --- .../2021-10-07-extraction-errors.md | 3 + cpp/ql/src/Diagnostics/ExtractionErrors.ql | 16 ---- ...ctionErrors.qll => ExtractionProblems.qll} | 88 +++++++++++-------- cpp/ql/src/Diagnostics/ExtractionWarnings.ql | 18 ++++ .../Diagnostics/FailedExtractorInvocations.ql | 5 +- .../Diagnostics/SuccessfullyExtractedFiles.ql | 8 +- 6 files changed, 80 insertions(+), 58 deletions(-) create mode 100644 cpp/change-notes/2021-10-07-extraction-errors.md delete mode 100644 cpp/ql/src/Diagnostics/ExtractionErrors.ql rename cpp/ql/src/Diagnostics/{ExtractionErrors.qll => ExtractionProblems.qll} (50%) create mode 100644 cpp/ql/src/Diagnostics/ExtractionWarnings.ql diff --git a/cpp/change-notes/2021-10-07-extraction-errors.md b/cpp/change-notes/2021-10-07-extraction-errors.md new file mode 100644 index 00000000000..d4d00afb77a --- /dev/null +++ b/cpp/change-notes/2021-10-07-extraction-errors.md @@ -0,0 +1,3 @@ +codescanning +* Problems with extraction that in most cases won't break the analysis in a significant way are now reported as warnings rather than errors. +* The failed extractor invocations query now has severity `error`. diff --git a/cpp/ql/src/Diagnostics/ExtractionErrors.ql b/cpp/ql/src/Diagnostics/ExtractionErrors.ql deleted file mode 100644 index a445c3bc0c4..00000000000 --- a/cpp/ql/src/Diagnostics/ExtractionErrors.ql +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @name Extraction errors - * @description List all extraction errors for files in the source code directory. - * @kind diagnostic - * @id cpp/diagnostics/extraction-errors - */ - -import cpp -import ExtractionErrors - -from ExtractionError error -where - error instanceof ExtractionUnknownError or - exists(error.getFile().getRelativePath()) -select error, "Extraction failed in " + error.getFile() + " with error " + error.getErrorMessage(), - error.getSeverity() diff --git a/cpp/ql/src/Diagnostics/ExtractionErrors.qll b/cpp/ql/src/Diagnostics/ExtractionProblems.qll similarity index 50% rename from cpp/ql/src/Diagnostics/ExtractionErrors.qll rename to cpp/ql/src/Diagnostics/ExtractionProblems.qll index 4cf6f8145f8..c96e2e926e8 100644 --- a/cpp/ql/src/Diagnostics/ExtractionErrors.qll +++ b/cpp/ql/src/Diagnostics/ExtractionProblems.qll @@ -1,12 +1,12 @@ /** - * Provides a common hierarchy of all types of errors that can occur during extraction. + * Provides a common hierarchy of all types of problems that can occur during extraction. */ import cpp /* * A note about how the C/C++ extractor emits diagnostics: - * When the extractor frontend encounters an error, it emits a diagnostic message, + * When the extractor frontend encounters a problem, it emits a diagnostic message, * that includes a message, location and severity. * However, that process is best-effort and may fail (e.g. due to lack of memory). * Thus, if the extractor emitted at least one diagnostic of severity discretionary @@ -15,17 +15,17 @@ import cpp * In the common case, this means that a compilation during which one or more errors happened also gets * the catch-all diagnostic. * This diagnostic has the empty string as file path. - * We filter out these useless diagnostics if there is at least one error-level diagnostic + * We filter out these useless diagnostics if there is at least one warning-level diagnostic * for the affected compilation in the database. * Otherwise, we show it to indicate that something went wrong and that we * don't know what exactly happened. */ /** - * An error that, if present, leads to a file being marked as non-successfully extracted. + * A problem with a file that, if present, leads to a file being marked as non-successfully extracted. */ -class ReportableError extends Diagnostic { - ReportableError() { +class ReportableWarning extends Diagnostic { + ReportableWarning() { ( this instanceof CompilerDiscretionaryError or this instanceof CompilerError or @@ -36,39 +36,35 @@ class ReportableError extends Diagnostic { } } -private newtype TExtractionError = - TReportableError(ReportableError err) or +private newtype TExtractionProblem = + TReportableWarning(ReportableWarning err) or TCompilationFailed(Compilation c, File f) { f = c.getAFileCompiled() and not c.normalTermination() } or // Show the catch-all diagnostic (see note above) only if we haven't seen any other error-level diagnostic // for that compilation - TUnknownError(CompilerError err) { - not exists(ReportableError e | e.getCompilation() = err.getCompilation()) + TUnknownProblem(CompilerError err) { + not exists(ReportableWarning e | e.getCompilation() = err.getCompilation()) } /** - * Superclass for the extraction error hierarchy. + * Superclass for the extraction problem hierarchy. */ -class ExtractionError extends TExtractionError { - /** Gets the string representation of the error. */ +class ExtractionProblem extends TExtractionProblem { + /** Gets the string representation of the problem. */ string toString() { none() } - /** Gets the error message for this error. */ - string getErrorMessage() { none() } + /** Gets the problem message for this problem. */ + string getProblemMessage() { none() } - /** Gets the file this error occured in. */ + /** Gets the file this problem occured in. */ File getFile() { none() } - /** Gets the location this error occured in. */ + /** Gets the location this problem occured in. */ Location getLocation() { none() } - /** Gets the SARIF severity of this error. */ - int getSeverity() { - // Unfortunately, we can't distinguish between errors and fatal errors in SARIF, - // so all errors have severity 2. - result = 2 - } + /** Gets the SARIF severity of this problem. */ + int getSeverity() { none() } } /** @@ -79,7 +75,7 @@ class ExtractionError extends TExtractionError { * - stack overflow * - out of memory */ -class ExtractionUnrecoverableError extends ExtractionError, TCompilationFailed { +class ExtractionUnrecoverableError extends ExtractionProblem, TCompilationFailed { Compilation c; File f; @@ -89,49 +85,67 @@ class ExtractionUnrecoverableError extends ExtractionError, TCompilationFailed { result = "Unrecoverable extraction error while compiling " + f.toString() } - override string getErrorMessage() { result = "unrecoverable compilation failure." } + override string getProblemMessage() { result = "unrecoverable compilation failure." } override File getFile() { result = f } override Location getLocation() { result = f.getLocation() } + + override int getSeverity() { + // These extractor errors break the analysis, so we mark them in SARIF as + // [errors](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10541338). + result = 2 + } } /** - * A recoverable extraction error. + * A recoverable extraction warning. * These are compiler errors from the frontend. * Upon encountering one of these, we still continue extraction, but the * database will be incomplete for that file. */ -class ExtractionRecoverableError extends ExtractionError, TReportableError { - ReportableError err; +class ExtractionRecoverableWarning extends ExtractionProblem, TReportableWarning { + ReportableWarning err; - ExtractionRecoverableError() { this = TReportableError(err) } + ExtractionRecoverableWarning() { this = TReportableWarning(err) } override string toString() { result = "Recoverable extraction error: " + err } - override string getErrorMessage() { result = err.getFullMessage() } + override string getProblemMessage() { result = err.getFullMessage() } override File getFile() { result = err.getFile() } override Location getLocation() { result = err.getLocation() } + + override int getSeverity() { + // Recoverable extraction problems don't tend to break the analysis, so we mark them in SARIF as + // [warnings](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10541338). + result = 1 + } } /** - * An unknown error happened during extraction. - * These are only displayed if we know that we encountered an error during extraction, + * An unknown problem happened during extraction. + * These are only displayed if we know that we encountered an problem during extraction, * but, for some reason, failed to emit a proper diagnostic with location information - * and error message. + * and problem message. */ -class ExtractionUnknownError extends ExtractionError, TUnknownError { +class ExtractionUnknownProblem extends ExtractionProblem, TUnknownProblem { CompilerError err; - ExtractionUnknownError() { this = TUnknownError(err) } + ExtractionUnknownProblem() { this = TUnknownProblem(err) } - override string toString() { result = "Unknown extraction error: " + err } + override string toString() { result = "Unknown extraction problem: " + err } - override string getErrorMessage() { result = err.getFullMessage() } + override string getProblemMessage() { result = err.getFullMessage() } override File getFile() { result = err.getFile() } override Location getLocation() { result = err.getLocation() } + + override int getSeverity() { + // Unknown extraction problems don't tend to break the analysis, so we mark them in SARIF as + // [warnings](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10541338). + result = 1 + } } diff --git a/cpp/ql/src/Diagnostics/ExtractionWarnings.ql b/cpp/ql/src/Diagnostics/ExtractionWarnings.ql new file mode 100644 index 00000000000..dcfb599bbeb --- /dev/null +++ b/cpp/ql/src/Diagnostics/ExtractionWarnings.ql @@ -0,0 +1,18 @@ +/** + * @name Extraction warnings + * @description List all extraction warnings for files in the source code directory. + * @kind diagnostic + * @id cpp/diagnostics/extraction-warnings + */ + +import cpp +import ExtractionProblems + +from ExtractionProblem warning +where + warning instanceof ExtractionRecoverableWarning and exists(warning.getFile().getRelativePath()) + or + warning instanceof ExtractionUnknownProblem +select warning, + "Extraction failed in " + warning.getFile() + " with warning " + warning.getProblemMessage(), + warning.getSeverity() diff --git a/cpp/ql/src/Diagnostics/FailedExtractorInvocations.ql b/cpp/ql/src/Diagnostics/FailedExtractorInvocations.ql index 8672d674d2d..fdc02f12135 100644 --- a/cpp/ql/src/Diagnostics/FailedExtractorInvocations.ql +++ b/cpp/ql/src/Diagnostics/FailedExtractorInvocations.ql @@ -13,6 +13,9 @@ string describe(Compilation c) { else result = "extractor invocation " + concat(int i | | c.getArgument(i), " " order by i) } +/** Gets the SARIF severity level that indicates an error. */ +private int getErrorSeverity() { result = 2 } + from Compilation c where not c.normalTermination() -select "Extraction aborted for " + describe(c) +select "Extraction aborted for " + describe(c), getErrorSeverity() diff --git a/cpp/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql b/cpp/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql index a920af8e767..3e9fb12d935 100644 --- a/cpp/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql +++ b/cpp/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql @@ -1,15 +1,15 @@ /** * @name Successfully extracted files - * @description Lists all files in the source code directory that were extracted without encountering an error in the file. + * @description Lists all files in the source code directory that were extracted without encountering a problem in the file. * @kind diagnostic * @id cpp/diagnostics/successfully-extracted-files */ import cpp -import ExtractionErrors +import ExtractionProblems from File f where - not exists(ExtractionError e | e.getFile() = f) and + not exists(ExtractionProblem e | e.getFile() = f) and exists(f.getRelativePath()) -select f, "" +select f, "File successfully extracted" From 0aa632d14967be02a5bd786cfbd511f19dea4a6c Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Sun, 10 Oct 2021 15:49:33 +0200 Subject: [PATCH 204/361] Python: Move writing of module vars into runtime jump steps. --- .../dataflow/new/internal/DataFlowPrivate.qll | 16 +++++++--------- .../dataflow/fieldflow/allLocalFlow.expected | 9 --------- .../dataflow/module-initialization/multiphase.py | 12 ++++++------ 3 files changed, 13 insertions(+), 24 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 6598c1fffa8..4191b926654 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -256,15 +256,7 @@ predicate importTimeLocalFlowStep(Node nodeFrom, Node nodeTo) { // This will miss statements inside functions called from the top level. isTopLevel(nodeFrom) and isTopLevel(nodeTo) and - ( - EssaFlow::essaFlowStep(nodeFrom, nodeTo) - or - exists(SsaVariable def | - def = any(SsaVariable var).getAnUltimateDefinition() and - def.getDefinition() = nodeFrom.asCfgNode() and - def.getVariable() = nodeTo.(ModuleVariableNode).getVariable() - ) - ) + EssaFlow::essaFlowStep(nodeFrom, nodeTo) } /** Holds if there is local flow from `nodeFrom` to `nodeTo` at runtime. */ @@ -282,6 +274,12 @@ predicate runtimeJumpStep(Node nodeFrom, Node nodeTo) { or // Module variable write nodeFrom = nodeTo.(ModuleVariableNode).getAWrite() + or + exists(SsaVariable def | + def = any(SsaVariable var).getAnUltimateDefinition() and + def.getDefinition() = nodeFrom.asCfgNode() and + def.getVariable() = nodeTo.(ModuleVariableNode).getVariable() + ) } /** diff --git a/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected b/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected index 8f6d203f6af..e288b7fd157 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected @@ -2,7 +2,6 @@ | examples.py:0:0:0:0 | GSSA Variable SOURCE | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | | examples.py:0:0:0:0 | GSSA Variable object | examples.py:6:13:6:18 | ControlFlowNode for object | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:6:7:6:11 | GSSA Variable MyObj | -| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | | examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:25:9:25:13 | ControlFlowNode for MyObj | | examples.py:6:13:6:18 | ControlFlowNode for object | examples.py:11:17:11:22 | ControlFlowNode for object | | examples.py:7:5:7:28 | ControlFlowNode for FunctionExpr | examples.py:7:9:7:16 | SSA variable __init__ | @@ -68,10 +67,8 @@ | examples.py:55:5:55:5 | SSA variable a | examples.py:56:12:56:12 | ControlFlowNode for a | | examples.py:55:9:55:15 | ControlFlowNode for Attribute | examples.py:55:5:55:5 | SSA variable a | | test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | -| test.py:3:1:3:6 | ControlFlowNode for SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | | test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | -| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | | test.py:6:15:6:15 | ControlFlowNode for x | test.py:6:15:6:15 | SSA variable x | | test.py:6:15:6:15 | SSA variable x | test.py:7:12:7:12 | ControlFlowNode for x | | test.py:7:12:7:12 | ControlFlowNode for x | test.py:7:29:7:29 | ControlFlowNode for x | @@ -80,20 +77,17 @@ | test.py:7:58:7:58 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | | test.py:10:1:10:12 | GSSA Variable is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | -| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | | test.py:10:10:10:10 | ControlFlowNode for x | test.py:10:10:10:10 | SSA variable x | | test.py:10:10:10:10 | SSA variable x | test.py:11:18:11:18 | ControlFlowNode for x | | test.py:11:18:11:18 | ControlFlowNode for x | test.py:14:34:14:34 | ControlFlowNode for x | | test.py:11:18:11:18 | [post arg] ControlFlowNode for x | test.py:14:34:14:34 | ControlFlowNode for x | | test.py:17:1:17:14 | ControlFlowNode for FunctionExpr | test.py:17:5:17:10 | GSSA Variable SINK_F | | test.py:17:1:17:14 | GSSA Variable is_source | test.py:18:8:18:16 | ControlFlowNode for is_source | -| test.py:17:5:17:10 | ControlFlowNode for SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | | test.py:17:12:17:12 | ControlFlowNode for x | test.py:17:12:17:12 | SSA variable x | | test.py:17:12:17:12 | SSA variable x | test.py:18:18:18:18 | ControlFlowNode for x | | test.py:18:18:18:18 | ControlFlowNode for x | test.py:19:34:19:34 | ControlFlowNode for x | | test.py:18:18:18:18 | [post arg] ControlFlowNode for x | test.py:19:34:19:34 | ControlFlowNode for x | | test.py:25:1:25:20 | ControlFlowNode for ClassExpr | test.py:25:7:25:11 | GSSA Variable MyObj | -| test.py:25:7:25:11 | ControlFlowNode for MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | | test.py:25:13:25:18 | ControlFlowNode for object | test.py:33:17:33:22 | ControlFlowNode for object | | test.py:26:5:26:28 | ControlFlowNode for FunctionExpr | test.py:26:9:26:16 | SSA variable __init__ | | test.py:26:18:26:21 | ControlFlowNode for self | test.py:26:18:26:21 | SSA variable self | @@ -106,7 +100,6 @@ | test.py:29:22:29:24 | ControlFlowNode for foo | test.py:29:22:29:24 | SSA variable foo | | test.py:29:22:29:24 | SSA variable foo | test.py:30:20:30:22 | ControlFlowNode for foo | | test.py:33:1:33:24 | ControlFlowNode for ClassExpr | test.py:33:7:33:15 | GSSA Variable NestedObj | -| test.py:33:7:33:15 | ControlFlowNode for NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | | test.py:34:5:34:23 | ControlFlowNode for FunctionExpr | test.py:34:9:34:16 | SSA variable __init__ | | test.py:34:5:34:23 | GSSA Variable MyObj | test.py:35:20:35:24 | ControlFlowNode for MyObj | | test.py:34:18:34:21 | ControlFlowNode for self | test.py:34:18:34:21 | SSA variable self | @@ -116,7 +109,6 @@ | test.py:37:16:37:19 | SSA variable self | test.py:38:16:38:19 | ControlFlowNode for self | | test.py:41:1:41:19 | ControlFlowNode for FunctionExpr | test.py:41:5:41:10 | GSSA Variable setFoo | | test.py:41:1:41:19 | GSSA Variable SINK_F | test.py:42:5:42:10 | ControlFlowNode for SINK_F | -| test.py:41:5:41:10 | ControlFlowNode for setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | | test.py:41:12:41:14 | ControlFlowNode for obj | test.py:41:12:41:14 | SSA variable obj | | test.py:41:12:41:14 | SSA variable obj | test.py:42:12:42:14 | ControlFlowNode for obj | | test.py:41:17:41:17 | ControlFlowNode for x | test.py:41:17:41:17 | SSA variable x | @@ -174,7 +166,6 @@ | test.py:86:11:86:27 | ControlFlowNode for MyObj() | test.py:86:5:86:7 | SSA variable obj | | test.py:90:1:90:30 | ControlFlowNode for FunctionExpr | test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | | test.py:90:1:90:30 | GSSA Variable MyObj | test.py:91:11:91:15 | ControlFlowNode for MyObj | -| test.py:90:5:90:26 | ControlFlowNode for fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | | test.py:90:28:90:28 | ControlFlowNode for x | test.py:90:28:90:28 | SSA variable x | | test.py:90:28:90:28 | SSA variable x | test.py:91:17:91:17 | ControlFlowNode for x | | test.py:91:5:91:7 | SSA variable obj | test.py:92:9:92:11 | ControlFlowNode for obj | diff --git a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py index a9c59cf78d1..e499cc2f8e7 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py +++ b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py @@ -5,15 +5,15 @@ sys.path.append(os.path.dirname(os.path.dirname((__file__)))) from testlib import * # These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" #$ importTimeFlow="ModuleVariableNode for Global Variable NONSOURCE in Module multiphase" -SOURCE = "source" #$ importTimeFlow="ModuleVariableNode for Global Variable SOURCE in Module multiphase" +NONSOURCE = "not a source" +SOURCE = "source" -def is_source(x): #$ importTimeFlow="ModuleVariableNode for Global Variable is_source in Module multiphase" +def is_source(x): return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j -def SINK(x): #$ importTimeFlow="ModuleVariableNode for Global Variable SINK in Module multiphase" +def SINK(x): if is_source(x): #$ runtimeFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-17 -> is_source" print("OK") #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-18 -> print" else: @@ -26,11 +26,11 @@ def SINK_F(x): else: print("OK") #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-27 -> print" -def set_foo(): #$ importTimeFlow="ModuleVariableNode for Global Variable set_foo in Module multiphase" +def set_foo(): global foo foo = SOURCE #$ runtimeFlow="ModuleVariableNode for Global Variable SOURCE in Module multiphase, l:-31 -> SOURCE" MISSING:importTimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase" -foo = NONSOURCE #$ importTimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase" +foo = NONSOURCE set_foo() @expects(2) From 64b1aeaecd7d401cf42149fd20810a36b82300fc Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Sun, 10 Oct 2021 15:59:31 +0200 Subject: [PATCH 205/361] Python: Shorten toString for module vars --- .../dataflow/new/internal/DataFlowPublic.qll | 2 +- .../dataflow/fieldflow/globalStep.expected | 208 +++++++++--------- .../module-initialization/multiphase.py | 22 +- .../strange-essaflow/testFlow.expected | 2 +- .../dataflow/typetracking/moduleattr.expected | 2 +- 5 files changed, 118 insertions(+), 118 deletions(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 82be6c5ee46..ee626ed26bf 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -332,7 +332,7 @@ class ModuleVariableNode extends Node, TModuleVariableNode { override Scope getScope() { result = mod } override string toString() { - result = "ModuleVariableNode for " + var.toString() + " in " + mod.toString() + result = "ModuleVariableNode for " + mod.getName() + "." + var.getId() } /** Gets the module in which this variable appears. */ diff --git a/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected b/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected index 9634fcc303b..4a6a7b0675d 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected @@ -30,22 +30,22 @@ | examples.py:0:0:0:0 | GSSA Variable object | examples.py:6:13:6:18 | ControlFlowNode for object | | examples.py:0:0:0:0 | GSSA Variable object | examples.py:11:17:11:22 | ControlFlowNode for object | | examples.py:0:0:0:0 | GSSA Variable object | examples.py:11:17:11:22 | ControlFlowNode for object | -| examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | examples.py:13:20:13:24 | ControlFlowNode for MyObj | -| examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | examples.py:13:20:13:24 | ControlFlowNode for MyObj | -| examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | examples.py:54:11:54:15 | ControlFlowNode for MyObj | -| examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | examples.py:54:11:54:15 | ControlFlowNode for MyObj | -| examples.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module examples | examples.py:21:5:21:10 | ControlFlowNode for SINK_F | -| examples.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module examples | examples.py:21:5:21:10 | ControlFlowNode for SINK_F | +| examples.py:0:0:0:0 | ModuleVariableNode for examples.MyObj | examples.py:13:20:13:24 | ControlFlowNode for MyObj | +| examples.py:0:0:0:0 | ModuleVariableNode for examples.MyObj | examples.py:13:20:13:24 | ControlFlowNode for MyObj | +| examples.py:0:0:0:0 | ModuleVariableNode for examples.MyObj | examples.py:54:11:54:15 | ControlFlowNode for MyObj | +| examples.py:0:0:0:0 | ModuleVariableNode for examples.MyObj | examples.py:54:11:54:15 | ControlFlowNode for MyObj | +| examples.py:0:0:0:0 | ModuleVariableNode for examples.SINK_F | examples.py:21:5:21:10 | ControlFlowNode for SINK_F | +| examples.py:0:0:0:0 | ModuleVariableNode for examples.SINK_F | examples.py:21:5:21:10 | ControlFlowNode for SINK_F | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:6:7:6:11 | GSSA Variable MyObj | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:6:7:6:11 | GSSA Variable MyObj | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:25:9:25:13 | ControlFlowNode for MyObj | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:25:9:25:13 | ControlFlowNode for MyObj | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:49:7:49:11 | ControlFlowNode for MyObj | | examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:49:7:49:11 | ControlFlowNode for MyObj | -| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | -| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | -| examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | -| examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples | +| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for examples.MyObj | +| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for examples.MyObj | +| examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:0:0:0:0 | ModuleVariableNode for examples.MyObj | +| examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:0:0:0:0 | ModuleVariableNode for examples.MyObj | | examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:25:9:25:13 | ControlFlowNode for MyObj | | examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:25:9:25:13 | ControlFlowNode for MyObj | | examples.py:6:7:6:11 | GSSA Variable MyObj | examples.py:49:7:49:11 | ControlFlowNode for MyObj | @@ -472,82 +472,82 @@ | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | examples.py:53:28:53:28 | ControlFlowNode for x | | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:35:20:35:24 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:35:20:35:24 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:47:13:47:17 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:47:13:47:17 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:54:13:54:17 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:54:13:54:17 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:81:11:81:15 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:81:11:81:15 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:86:11:86:15 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:86:11:86:15 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:91:11:91:15 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | test.py:91:11:91:15 | ControlFlowNode for MyObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | test.py:63:9:63:17 | ControlFlowNode for NestedObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | test.py:63:9:63:17 | ControlFlowNode for NestedObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | test.py:73:9:73:17 | ControlFlowNode for NestedObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | test.py:73:9:73:17 | ControlFlowNode for NestedObj | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:50:5:50:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:50:5:50:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:57:5:57:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:57:5:57:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:67:5:67:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:67:5:67:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:77:5:77:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:77:5:77:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:82:5:82:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:82:5:82:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:87:5:87:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:87:5:87:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:97:5:97:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | test.py:97:5:97:8 | ControlFlowNode for SINK | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | test.py:42:5:42:10 | ControlFlowNode for SINK_F | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | test.py:42:5:42:10 | ControlFlowNode for SINK_F | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:49:19:49:24 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:49:19:49:24 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:56:18:56:23 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:56:18:56:23 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:61:9:61:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:61:9:61:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:71:9:71:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:71:9:71:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:81:17:81:22 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:81:17:81:22 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:86:21:86:26 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:86:21:86:26 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:97:33:97:38 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:97:33:97:38 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | test.py:97:10:97:31 | ControlFlowNode for fields_with_local_flow | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | test.py:97:10:97:31 | ControlFlowNode for fields_with_local_flow | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | test.py:11:8:11:16 | ControlFlowNode for is_source | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | test.py:11:8:11:16 | ControlFlowNode for is_source | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | test.py:18:8:18:16 | ControlFlowNode for is_source | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | test.py:18:8:18:16 | ControlFlowNode for is_source | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable print in Module test | test.py:12:9:12:13 | ControlFlowNode for print | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable print in Module test | test.py:12:9:12:13 | ControlFlowNode for print | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable print in Module test | test.py:14:9:14:13 | ControlFlowNode for print | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable print in Module test | test.py:14:9:14:13 | ControlFlowNode for print | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable print in Module test | test.py:19:9:19:13 | ControlFlowNode for print | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable print in Module test | test.py:19:9:19:13 | ControlFlowNode for print | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable print in Module test | test.py:21:9:21:13 | ControlFlowNode for print | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable print in Module test | test.py:21:9:21:13 | ControlFlowNode for print | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | test.py:49:5:49:10 | ControlFlowNode for setFoo | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | test.py:49:5:49:10 | ControlFlowNode for setFoo | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:35:20:35:24 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:35:20:35:24 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:47:13:47:17 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:47:13:47:17 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:54:13:54:17 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:54:13:54:17 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:81:11:81:15 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:81:11:81:15 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:86:11:86:15 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:86:11:86:15 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:91:11:91:15 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | test.py:91:11:91:15 | ControlFlowNode for MyObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.NestedObj | test.py:63:9:63:17 | ControlFlowNode for NestedObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.NestedObj | test.py:63:9:63:17 | ControlFlowNode for NestedObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.NestedObj | test.py:73:9:73:17 | ControlFlowNode for NestedObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.NestedObj | test.py:73:9:73:17 | ControlFlowNode for NestedObj | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:50:5:50:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:50:5:50:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:57:5:57:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:57:5:57:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:67:5:67:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:67:5:67:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:77:5:77:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:77:5:77:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:82:5:82:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:82:5:82:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:87:5:87:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:87:5:87:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:97:5:97:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK | test.py:97:5:97:8 | ControlFlowNode for SINK | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK_F | test.py:42:5:42:10 | ControlFlowNode for SINK_F | +| test.py:0:0:0:0 | ModuleVariableNode for test.SINK_F | test.py:42:5:42:10 | ControlFlowNode for SINK_F | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:49:19:49:24 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:49:19:49:24 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:56:18:56:23 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:56:18:56:23 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:61:9:61:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:61:9:61:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:71:9:71:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:71:9:71:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:81:17:81:22 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:81:17:81:22 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:86:21:86:26 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:86:21:86:26 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:97:33:97:38 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | test.py:97:33:97:38 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for test.fields_with_local_flow | test.py:97:10:97:31 | ControlFlowNode for fields_with_local_flow | +| test.py:0:0:0:0 | ModuleVariableNode for test.fields_with_local_flow | test.py:97:10:97:31 | ControlFlowNode for fields_with_local_flow | +| test.py:0:0:0:0 | ModuleVariableNode for test.is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | +| test.py:0:0:0:0 | ModuleVariableNode for test.is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | +| test.py:0:0:0:0 | ModuleVariableNode for test.is_source | test.py:18:8:18:16 | ControlFlowNode for is_source | +| test.py:0:0:0:0 | ModuleVariableNode for test.is_source | test.py:18:8:18:16 | ControlFlowNode for is_source | +| test.py:0:0:0:0 | ModuleVariableNode for test.print | test.py:12:9:12:13 | ControlFlowNode for print | +| test.py:0:0:0:0 | ModuleVariableNode for test.print | test.py:12:9:12:13 | ControlFlowNode for print | +| test.py:0:0:0:0 | ModuleVariableNode for test.print | test.py:14:9:14:13 | ControlFlowNode for print | +| test.py:0:0:0:0 | ModuleVariableNode for test.print | test.py:14:9:14:13 | ControlFlowNode for print | +| test.py:0:0:0:0 | ModuleVariableNode for test.print | test.py:19:9:19:13 | ControlFlowNode for print | +| test.py:0:0:0:0 | ModuleVariableNode for test.print | test.py:19:9:19:13 | ControlFlowNode for print | +| test.py:0:0:0:0 | ModuleVariableNode for test.print | test.py:21:9:21:13 | ControlFlowNode for print | +| test.py:0:0:0:0 | ModuleVariableNode for test.print | test.py:21:9:21:13 | ControlFlowNode for print | +| test.py:0:0:0:0 | ModuleVariableNode for test.setFoo | test.py:49:5:49:10 | ControlFlowNode for setFoo | +| test.py:0:0:0:0 | ModuleVariableNode for test.setFoo | test.py:49:5:49:10 | ControlFlowNode for setFoo | | test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | | test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE | -| test.py:3:1:3:6 | ControlFlowNode for SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | -| test.py:3:1:3:6 | ControlFlowNode for SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | -| test.py:3:1:3:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | -| test.py:3:1:3:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | +| test.py:3:1:3:6 | ControlFlowNode for SOURCE | test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | +| test.py:3:1:3:6 | ControlFlowNode for SOURCE | test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | +| test.py:3:1:3:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | +| test.py:3:1:3:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for test.SOURCE | | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | | test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | | test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source | -| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | -| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | -| test.py:6:5:6:13 | GSSA Variable is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | -| test.py:6:5:6:13 | GSSA Variable is_source | test.py:0:0:0:0 | ModuleVariableNode for Global Variable is_source in Module test | +| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for test.is_source | +| test.py:6:5:6:13 | ControlFlowNode for is_source | test.py:0:0:0:0 | ModuleVariableNode for test.is_source | +| test.py:6:5:6:13 | GSSA Variable is_source | test.py:0:0:0:0 | ModuleVariableNode for test.is_source | +| test.py:6:5:6:13 | GSSA Variable is_source | test.py:0:0:0:0 | ModuleVariableNode for test.is_source | | test.py:6:15:6:15 | ControlFlowNode for x | test.py:6:15:6:15 | SSA variable x | | test.py:6:15:6:15 | ControlFlowNode for x | test.py:6:15:6:15 | SSA variable x | | test.py:6:15:6:15 | ControlFlowNode for x | test.py:6:15:6:15 | SSA variable x | @@ -640,10 +640,10 @@ | test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | | test.py:10:1:10:12 | GSSA Variable is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | | test.py:10:1:10:12 | GSSA Variable is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | -| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | -| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | -| test.py:10:5:10:8 | GSSA Variable SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | -| test.py:10:5:10:8 | GSSA Variable SINK | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK in Module test | +| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for test.SINK | +| test.py:10:5:10:8 | ControlFlowNode for SINK | test.py:0:0:0:0 | ModuleVariableNode for test.SINK | +| test.py:10:5:10:8 | GSSA Variable SINK | test.py:0:0:0:0 | ModuleVariableNode for test.SINK | +| test.py:10:5:10:8 | GSSA Variable SINK | test.py:0:0:0:0 | ModuleVariableNode for test.SINK | | test.py:10:10:10:10 | ControlFlowNode for x | test.py:10:10:10:10 | SSA variable x | | test.py:10:10:10:10 | ControlFlowNode for x | test.py:10:10:10:10 | SSA variable x | | test.py:10:10:10:10 | ControlFlowNode for x | test.py:10:10:10:10 | SSA variable x | @@ -692,10 +692,10 @@ | test.py:17:1:17:14 | ControlFlowNode for FunctionExpr | test.py:17:5:17:10 | GSSA Variable SINK_F | | test.py:17:1:17:14 | GSSA Variable is_source | test.py:18:8:18:16 | ControlFlowNode for is_source | | test.py:17:1:17:14 | GSSA Variable is_source | test.py:18:8:18:16 | ControlFlowNode for is_source | -| test.py:17:5:17:10 | ControlFlowNode for SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | -| test.py:17:5:17:10 | ControlFlowNode for SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | -| test.py:17:5:17:10 | GSSA Variable SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | -| test.py:17:5:17:10 | GSSA Variable SINK_F | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SINK_F in Module test | +| test.py:17:5:17:10 | ControlFlowNode for SINK_F | test.py:0:0:0:0 | ModuleVariableNode for test.SINK_F | +| test.py:17:5:17:10 | ControlFlowNode for SINK_F | test.py:0:0:0:0 | ModuleVariableNode for test.SINK_F | +| test.py:17:5:17:10 | GSSA Variable SINK_F | test.py:0:0:0:0 | ModuleVariableNode for test.SINK_F | +| test.py:17:5:17:10 | GSSA Variable SINK_F | test.py:0:0:0:0 | ModuleVariableNode for test.SINK_F | | test.py:17:12:17:12 | ControlFlowNode for x | test.py:17:12:17:12 | SSA variable x | | test.py:17:12:17:12 | ControlFlowNode for x | test.py:17:12:17:12 | SSA variable x | | test.py:17:12:17:12 | ControlFlowNode for x | test.py:17:12:17:12 | SSA variable x | @@ -732,10 +732,10 @@ | test.py:19:34:19:34 | [post arg] ControlFlowNode for x | test.py:42:12:42:18 | [post arg] ControlFlowNode for Attribute | | test.py:25:1:25:20 | ControlFlowNode for ClassExpr | test.py:25:7:25:11 | GSSA Variable MyObj | | test.py:25:1:25:20 | ControlFlowNode for ClassExpr | test.py:25:7:25:11 | GSSA Variable MyObj | -| test.py:25:7:25:11 | ControlFlowNode for MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | -| test.py:25:7:25:11 | ControlFlowNode for MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | -| test.py:25:7:25:11 | GSSA Variable MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | -| test.py:25:7:25:11 | GSSA Variable MyObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module test | +| test.py:25:7:25:11 | ControlFlowNode for MyObj | test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | +| test.py:25:7:25:11 | ControlFlowNode for MyObj | test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | +| test.py:25:7:25:11 | GSSA Variable MyObj | test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | +| test.py:25:7:25:11 | GSSA Variable MyObj | test.py:0:0:0:0 | ModuleVariableNode for test.MyObj | | test.py:25:13:25:18 | ControlFlowNode for object | test.py:33:17:33:22 | ControlFlowNode for object | | test.py:25:13:25:18 | ControlFlowNode for object | test.py:33:17:33:22 | ControlFlowNode for object | | test.py:26:5:26:28 | ControlFlowNode for FunctionExpr | test.py:26:9:26:16 | SSA variable __init__ | @@ -817,10 +817,10 @@ | test.py:30:20:30:22 | ControlFlowNode for foo | test.py:30:9:30:12 | [post store] ControlFlowNode for self [Attribute foo] | | test.py:33:1:33:24 | ControlFlowNode for ClassExpr | test.py:33:7:33:15 | GSSA Variable NestedObj | | test.py:33:1:33:24 | ControlFlowNode for ClassExpr | test.py:33:7:33:15 | GSSA Variable NestedObj | -| test.py:33:7:33:15 | ControlFlowNode for NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | -| test.py:33:7:33:15 | ControlFlowNode for NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | -| test.py:33:7:33:15 | GSSA Variable NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | -| test.py:33:7:33:15 | GSSA Variable NestedObj | test.py:0:0:0:0 | ModuleVariableNode for Global Variable NestedObj in Module test | +| test.py:33:7:33:15 | ControlFlowNode for NestedObj | test.py:0:0:0:0 | ModuleVariableNode for test.NestedObj | +| test.py:33:7:33:15 | ControlFlowNode for NestedObj | test.py:0:0:0:0 | ModuleVariableNode for test.NestedObj | +| test.py:33:7:33:15 | GSSA Variable NestedObj | test.py:0:0:0:0 | ModuleVariableNode for test.NestedObj | +| test.py:33:7:33:15 | GSSA Variable NestedObj | test.py:0:0:0:0 | ModuleVariableNode for test.NestedObj | | test.py:34:5:34:23 | ControlFlowNode for FunctionExpr | test.py:34:9:34:16 | SSA variable __init__ | | test.py:34:5:34:23 | ControlFlowNode for FunctionExpr | test.py:34:9:34:16 | SSA variable __init__ | | test.py:34:5:34:23 | GSSA Variable MyObj | test.py:35:20:35:24 | ControlFlowNode for MyObj | @@ -879,10 +879,10 @@ | test.py:41:1:41:19 | ControlFlowNode for FunctionExpr | test.py:41:5:41:10 | GSSA Variable setFoo | | test.py:41:1:41:19 | GSSA Variable SINK_F | test.py:42:5:42:10 | ControlFlowNode for SINK_F | | test.py:41:1:41:19 | GSSA Variable SINK_F | test.py:42:5:42:10 | ControlFlowNode for SINK_F | -| test.py:41:5:41:10 | ControlFlowNode for setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | -| test.py:41:5:41:10 | ControlFlowNode for setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | -| test.py:41:5:41:10 | GSSA Variable setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | -| test.py:41:5:41:10 | GSSA Variable setFoo | test.py:0:0:0:0 | ModuleVariableNode for Global Variable setFoo in Module test | +| test.py:41:5:41:10 | ControlFlowNode for setFoo | test.py:0:0:0:0 | ModuleVariableNode for test.setFoo | +| test.py:41:5:41:10 | ControlFlowNode for setFoo | test.py:0:0:0:0 | ModuleVariableNode for test.setFoo | +| test.py:41:5:41:10 | GSSA Variable setFoo | test.py:0:0:0:0 | ModuleVariableNode for test.setFoo | +| test.py:41:5:41:10 | GSSA Variable setFoo | test.py:0:0:0:0 | ModuleVariableNode for test.setFoo | | test.py:41:12:41:14 | ControlFlowNode for obj | test.py:41:12:41:14 | SSA variable obj | | test.py:41:12:41:14 | ControlFlowNode for obj | test.py:41:12:41:14 | SSA variable obj | | test.py:41:12:41:14 | ControlFlowNode for obj | test.py:41:12:41:14 | SSA variable obj | @@ -1207,10 +1207,10 @@ | test.py:90:1:90:30 | ControlFlowNode for FunctionExpr | test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | | test.py:90:1:90:30 | GSSA Variable MyObj | test.py:91:11:91:15 | ControlFlowNode for MyObj | | test.py:90:1:90:30 | GSSA Variable MyObj | test.py:91:11:91:15 | ControlFlowNode for MyObj | -| test.py:90:5:90:26 | ControlFlowNode for fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | -| test.py:90:5:90:26 | ControlFlowNode for fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | -| test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | -| test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for Global Variable fields_with_local_flow in Module test | +| test.py:90:5:90:26 | ControlFlowNode for fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for test.fields_with_local_flow | +| test.py:90:5:90:26 | ControlFlowNode for fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for test.fields_with_local_flow | +| test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for test.fields_with_local_flow | +| test.py:90:5:90:26 | GSSA Variable fields_with_local_flow | test.py:0:0:0:0 | ModuleVariableNode for test.fields_with_local_flow | | test.py:90:28:90:28 | ControlFlowNode for x | test.py:90:28:90:28 | SSA variable x | | test.py:90:28:90:28 | ControlFlowNode for x | test.py:90:28:90:28 | SSA variable x | | test.py:90:28:90:28 | ControlFlowNode for x | test.py:90:28:90:28 | SSA variable x | diff --git a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py index e499cc2f8e7..6e6df47dcc4 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py +++ b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py @@ -14,21 +14,21 @@ def is_source(x): def SINK(x): - if is_source(x): #$ runtimeFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-17 -> is_source" - print("OK") #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-18 -> print" + if is_source(x): #$ runtimeFlow="ModuleVariableNode for multiphase.is_source, l:-17 -> is_source" + print("OK") #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-18 -> print" else: - print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-20 -> print" + print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-20 -> print" def SINK_F(x): - if is_source(x): #$ runtimeFlow="ModuleVariableNode for Global Variable is_source in Module multiphase, l:-24 -> is_source" - print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-25 -> print" + if is_source(x): #$ runtimeFlow="ModuleVariableNode for multiphase.is_source, l:-24 -> is_source" + print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-25 -> print" else: - print("OK") #$ runtimeFlow="ModuleVariableNode for Global Variable print in Module multiphase, l:-27 -> print" + print("OK") #$ Unexpected result: runtimeFlow="ModuleVariableNode for multiphase.print, l:-27 -> print" def set_foo(): global foo - foo = SOURCE #$ runtimeFlow="ModuleVariableNode for Global Variable SOURCE in Module multiphase, l:-31 -> SOURCE" MISSING:importTimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase" + foo = SOURCE #$ runtimeFlow="ModuleVariableNode for multiphase.SOURCE, l:-31 -> SOURCE" MISSING:importTimeFlow="ModuleVariableNode for multiphase.foo" foo = NONSOURCE set_foo() @@ -36,7 +36,7 @@ set_foo() @expects(2) def test_phases(): global foo - SINK(foo) #$ runtimeFlow="ModuleVariableNode for Global Variable SINK in Module multiphase, l:-39 -> SINK" runtimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase, l:-39 -> foo" - foo = NONSOURCE #$ runtimeFlow="ModuleVariableNode for Global Variable NONSOURCE in Module multiphase, l:-40 -> NONSOURCE" - set_foo() #$ runtimeFlow="ModuleVariableNode for Global Variable set_foo in Module multiphase, l:-41 -> set_foo" - SINK(foo) #$ runtimeFlow="ModuleVariableNode for Global Variable SINK in Module multiphase, l:-42 -> SINK" runtimeFlow="ModuleVariableNode for Global Variable foo in Module multiphase, l:-42 -> foo" + SINK(foo) #$ runtimeFlow="ModuleVariableNode for multiphase.SINK, l:-39 -> SINK" runtimeFlow="ModuleVariableNode for multiphase.foo, l:-39 -> foo" + foo = NONSOURCE #$ runtimeFlow="ModuleVariableNode for multiphase.NONSOURCE, l:-40 -> NONSOURCE" + set_foo() #$ runtimeFlow="ModuleVariableNode for multiphase.set_foo, l:-41 -> set_foo" + SINK(foo) #$ runtimeFlow="ModuleVariableNode for multiphase.SINK, l:-42 -> SINK" runtimeFlow="ModuleVariableNode for multiphase.foo, l:-42 -> foo" diff --git a/python/ql/test/experimental/dataflow/strange-essaflow/testFlow.expected b/python/ql/test/experimental/dataflow/strange-essaflow/testFlow.expected index 2d35c297fc0..81afa22a94d 100644 --- a/python/ql/test/experimental/dataflow/strange-essaflow/testFlow.expected +++ b/python/ql/test/experimental/dataflow/strange-essaflow/testFlow.expected @@ -2,5 +2,5 @@ os_import | test.py:2:8:2:9 | GSSA Variable os | flowstep jumpStep -| test.py:2:8:2:9 | GSSA Variable os | test.py:0:0:0:0 | ModuleVariableNode for Global Variable os in Module test | +| test.py:2:8:2:9 | GSSA Variable os | test.py:0:0:0:0 | ModuleVariableNode for test.os | essaFlowStep diff --git a/python/ql/test/experimental/dataflow/typetracking/moduleattr.expected b/python/ql/test/experimental/dataflow/typetracking/moduleattr.expected index adfc8c5a379..9720d759aa0 100644 --- a/python/ql/test/experimental/dataflow/typetracking/moduleattr.expected +++ b/python/ql/test/experimental/dataflow/typetracking/moduleattr.expected @@ -1,7 +1,7 @@ module_tracker | import_as_attr.py:1:6:1:11 | ControlFlowNode for ImportExpr | module_attr_tracker -| import_as_attr.py:0:0:0:0 | ModuleVariableNode for Global Variable attr_ref in Module import_as_attr | +| import_as_attr.py:0:0:0:0 | ModuleVariableNode for import_as_attr.attr_ref | | import_as_attr.py:1:20:1:35 | ControlFlowNode for ImportMember | | import_as_attr.py:1:28:1:35 | GSSA Variable attr_ref | | import_as_attr.py:3:1:3:1 | GSSA Variable x | From a74d423d82cba18ac188c4b82581fd6e046a714e Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 11 Oct 2021 01:03:46 +0200 Subject: [PATCH 206/361] Java: Improve AnnotationPresentCheck.ql --- java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql b/java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql index 6af39558a8c..22729eebd66 100644 --- a/java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql +++ b/java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql @@ -19,9 +19,8 @@ where m.getNumberOfParameters() = 1 and c.getArgument(0).getType() = p and p.getATypeArgument() = t and - not exists(Annotation a | + not exists(RetentionAnnotation a | t.getAnAnnotation() = a and - a.getType().hasQualifiedName("java.lang.annotation", "Retention") and a.getAValue().(VarAccess).getVariable().hasName("RUNTIME") ) select c, "Call to isAnnotationPresent where no annotation has the RUNTIME retention policy." From b00988666433a448277314aea4b61f50db2f2f40 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 11 Oct 2021 01:07:05 +0200 Subject: [PATCH 207/361] Java: Add TypeObjectInputStream --- java/ql/lib/semmle/code/java/JDK.qll | 7 +- .../dataflow/internal/TaintTrackingUtil.qll | 2 +- .../frameworks/javaee/ejb/EJBRestrictions.qll | 65 +++++-------------- .../security/UnsafeDeserializationQuery.qll | 2 +- .../Concurrency/SynchWriteObject.ql | 2 +- .../CWE/CWE-502/UnsafeDeserializationRmi.ql | 2 +- 6 files changed, 26 insertions(+), 54 deletions(-) diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll index 1e6d730943a..2e14ab7b898 100644 --- a/java/ql/lib/semmle/code/java/JDK.qll +++ b/java/ql/lib/semmle/code/java/JDK.qll @@ -156,6 +156,11 @@ class TypeObjectOutputStream extends RefType { TypeObjectOutputStream() { hasQualifiedName("java.io", "ObjectOutputStream") } } +/** The type `java.io.ObjectInputStream`. */ +class TypeObjectInputStream extends RefType { + TypeObjectInputStream() { hasQualifiedName("java.io", "ObjectInputStream") } +} + /** The class `java.nio.file.Paths`. */ class TypePaths extends Class { TypePaths() { this.hasQualifiedName("java.nio.file", "Paths") } @@ -275,7 +280,7 @@ class WriteObjectMethod extends Method { */ class ReadObjectMethod extends Method { ReadObjectMethod() { - this.getDeclaringType().hasQualifiedName("java.io", "ObjectInputStream") and + this.getDeclaringType() instanceof TypeObjectInputStream and ( this.hasName("readObject") or this.hasName("readObjectOverride") or diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index 569c7cef3c5..e92ad541a51 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -269,7 +269,7 @@ private predicate taintPreservingQualifierToMethod(Method m) { m.getName() = "toString" ) or - m.getDeclaringType().hasQualifiedName("java.io", "ObjectInputStream") and + m.getDeclaringType() instanceof TypeObjectInputStream and m.getName().matches("read%") or m instanceof GetterMethod and diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll index bb50f2c5d2f..c62b72ab9fc 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll @@ -299,10 +299,7 @@ class RuntimeExitOrHaltMethod extends Method { (this.hasName("exit") or this.hasName("halt")) and this.getNumberOfParameters() = 1 and this.getParameter(0).getType().(PrimitiveType).hasName("int") and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.lang", "Runtime") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeRuntime } } @@ -315,10 +312,7 @@ class RuntimeAddOrRemoveShutdownHookMethod extends Method { (this.hasName("addShutdownHook") or this.hasName("removeShutdownHook")) and this.getNumberOfParameters() = 1 and this.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "Thread") and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.lang", "Runtime") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeRuntime } } @@ -414,33 +408,29 @@ class ForbiddenSerializationMethod extends Method { /** * A method named `enableReplaceObject` declared in - * the class `java.io.ObjectInputStream` or a subclass thereof. + * the class `java.io.ObjectOutputStream` or a subclass thereof. */ class EnableReplaceObjectMethod extends Method { EnableReplaceObjectMethod() { this.hasName("enableReplaceObject") and this.getNumberOfParameters() = 1 and this.getParameter(0).getType().(PrimitiveType).hasName("boolean") and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.io", "ObjectOutputStream") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof + TypeObjectOutputStream } } /** * A method named `replaceObject` declared in - * the class `java.io.ObjectInputStream` or a subclass thereof. + * the class `java.io.ObjectOutputStream` or a subclass thereof. */ class ReplaceObjectMethod extends Method { ReplaceObjectMethod() { this.hasName("replaceObject") and this.getNumberOfParameters() = 1 and this.getParameter(0).getType() instanceof TypeObject and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.io", "ObjectOutputStream") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof + TypeObjectOutputStream } } @@ -453,10 +443,7 @@ class EnableResolveObjectMethod extends Method { this.hasName("enableResolveObject") and this.getNumberOfParameters() = 1 and this.getParameter(0).getType().(PrimitiveType).hasName("boolean") and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.io", "ObjectInputStream") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeObjectInputStream } } @@ -469,10 +456,7 @@ class ResolveObjectMethod extends Method { this.hasName("resolveObject") and this.getNumberOfParameters() = 1 and this.getParameter(0).getType() instanceof TypeObject and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.io", "ObjectInputStream") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeObjectInputStream } } @@ -485,10 +469,7 @@ class ResolveClassMethod extends Method { this.hasName("resolveClass") and this.getNumberOfParameters() = 1 and this.getParameter(0).getType().(RefType).hasQualifiedName("java.io", "ObjectStreamClass") and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.io", "ObjectInputStream") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeObjectInputStream } } @@ -500,16 +481,8 @@ class ResolveProxyClassMethod extends Method { ResolveProxyClassMethod() { this.hasName("resolveProxyClass") and this.getNumberOfParameters() = 1 and - this.getParameter(0) - .getType() - .(Array) - .getComponentType() - .(RefType) - .hasQualifiedName("java.lang", "String") and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.io", "ObjectInputStream") + this.getParameter(0).getType().(Array).getComponentType() instanceof TypeString and + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeObjectInputStream } } @@ -598,16 +571,13 @@ class SystemOrRuntimeLoadLibraryMethod extends Method { SystemOrRuntimeLoadLibraryMethod() { (this.hasName("load") or this.hasName("loadLibrary")) and this.getNumberOfParameters() = 1 and - this.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "String") and + this.getParameter(0).getType() instanceof TypeString and ( this.getDeclaringType() .getASupertype*() .getSourceDeclaration() .hasQualifiedName("java.lang", "System") or - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.lang", "Runtime") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeRuntime ) } } @@ -619,9 +589,6 @@ class SystemOrRuntimeLoadLibraryMethod extends Method { class RuntimeExecMethod extends Method { RuntimeExecMethod() { this.hasName("exec") and - this.getDeclaringType() - .getASupertype*() - .getSourceDeclaration() - .hasQualifiedName("java.lang", "Runtime") + this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeRuntime } } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index 5f38317acdb..f4a7e91ff2e 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -22,7 +22,7 @@ private import semmle.code.java.Reflection private class ObjectInputStreamReadObjectMethod extends Method { ObjectInputStreamReadObjectMethod() { - this.getDeclaringType().getASourceSupertype*().hasQualifiedName("java.io", "ObjectInputStream") and + this.getDeclaringType().getASourceSupertype*() instanceof TypeObjectInputStream and (this.hasName("readObject") or this.hasName("readUnshared")) } } diff --git a/java/ql/src/Likely Bugs/Concurrency/SynchWriteObject.ql b/java/ql/src/Likely Bugs/Concurrency/SynchWriteObject.ql index dc35a5db380..cb93e28d740 100644 --- a/java/ql/src/Likely Bugs/Concurrency/SynchWriteObject.ql +++ b/java/ql/src/Likely Bugs/Concurrency/SynchWriteObject.ql @@ -20,7 +20,7 @@ where m.getDeclaringType().getASupertype*() instanceof TypeSerializable and m.hasName("writeObject") and m.getNumberOfParameters() = 1 and - m.getAParamType().(Class).hasQualifiedName("java.io", "ObjectOutputStream") and + m.getAParamType() instanceof TypeObjectOutputStream and m.isSynchronized() and not exists(Method s | m.getDeclaringType().inherits(s) and diff --git a/java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.ql b/java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.ql index f870d6f423e..722c615f5b5 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.ql @@ -39,7 +39,7 @@ private predicate hasVulnerableMethod(RefType type) { | not parameterType instanceof PrimitiveType and not parameterType instanceof TypeString and - not parameterType.(RefType).hasQualifiedName("java.io", "ObjectInputStream") + not parameterType instanceof TypeObjectInputStream ) } From 12936ff5fef842cd716fa594427429800960c058 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 11 Oct 2021 01:10:08 +0200 Subject: [PATCH 208/361] Java: Fix IncorrectSerializableMethods.ql using wrong readObject signature --- .../Serialization/IncorrectSerializableMethods.ql | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql index 3990f94936b..f831c938f7c 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql @@ -16,8 +16,9 @@ import java from Method m, TypeSerializable serializable where m.getDeclaringType().hasSupertype+(serializable) and - m.getNumberOfParameters() = 1 and - m.getAParameter().getType().(RefType).hasQualifiedName("java.io", "ObjectOutputStream") and - (m.hasName("readObject") or m.hasName("writeObject")) and + ( + m.hasStringSignature("readObject(ObjectInputStream)") or + m.hasName("writeObject(ObjectOutputStream)") + ) and not m.isPrivate() select m, "readObject and writeObject should be private methods." From a7670fbcaba6cab17620067363a3234396b0e324 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 11 Oct 2021 01:44:04 +0200 Subject: [PATCH 209/361] Java: Enhance IncorrectSerializableMethods.ql --- .../IncorrectSerializableMethods.java | 11 +++++++++++ .../IncorrectSerializableMethods.qhelp | 15 ++++++++------- .../Serialization/IncorrectSerializableMethods.ql | 15 ++++++++++----- .../IncorrectSerializableMethodsSig.java | 2 ++ 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.java b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.java index 57fd8a64cc2..d12ab5dd887 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.java +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.java @@ -5,6 +5,12 @@ class WrongNetRequest implements Serializable { //... } + // BAD: Does not match the exact signature required for a custom + // deserialization protocol. Will not be called during deserialization. + void readObjectNoData() { + //... + } + // BAD: Does not match the exact signature required for a custom // serialization protocol. Will not be called during serialization. protected void writeObject(ObjectOutputStream out) { @@ -18,6 +24,11 @@ class NetRequest implements Serializable { //... } + // GOOD: Signature for a custom deserialization implementation. + private void readObjectNoData() { + //... + } + // GOOD: Signature for a custom serialization implementation. private void writeObject(ObjectOutputStream out) { //... diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.qhelp b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.qhelp index 8fe19086671..caf48b65107 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.qhelp +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.qhelp @@ -7,15 +7,16 @@ <overview> <p> A serializable object that defines its own serialization protocol using the methods -<code>readObject</code> and <code>writeObject</code> must use the signature that is expected by the -Java serialization framework. Otherwise, the default serialization mechanism is used. +<code>readObject</code>, <code>readObjectNoData</code> or <code>writeObject</code> must use +the signature that is expected by the Java serialization framework. Otherwise, the default +serialization mechanism is used. </p> </overview> <recommendation> <p> -Make sure that the signatures of <code>readObject</code> and <code>writeObject</code> on -serializable classes use these exact signatures: +Make sure that the signatures of <code>readObject</code>, <code>readObjectNoData</code> and +<code>writeObject</code> on serializable classes match these expected signatures: </p> <sample src="IncorrectSerializableMethodsSig.java" /> @@ -23,9 +24,9 @@ serializable classes use these exact signatures: </recommendation> <example> -<p>In the following example, <code>WrongNetRequest</code> defines <code>readObject</code> and -<code>writeObject</code> using the wrong signatures. However, <code>NetRequest</code> defines them -correctly.</p> +<p>In the following example, <code>WrongNetRequest</code> defines <code>readObject</code>, +<code>readObjectNoData</code> and <code>writeObject</code> using the wrong signatures. However, +<code>NetRequest</code> defines them correctly.</p> <sample src="IncorrectSerializableMethods.java" /> diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql index f831c938f7c..60c5ac30523 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql @@ -1,7 +1,7 @@ /** * @name Serialization methods do not match required signature - * @description A serialized class that implements 'readObject' or 'writeObject' but does not use - * the correct signatures causes the default serialization mechanism to be used. + * @description A serialized class that implements 'readObject', 'readObjectNoData' or 'writeObject' but + * does not use the correct signatures causes the default serialization mechanism to be used. * @kind problem * @problem.severity warning * @precision medium @@ -13,12 +13,17 @@ import java -from Method m, TypeSerializable serializable +from Method m, TypeSerializable serializable, string reason where m.getDeclaringType().hasSupertype+(serializable) and ( m.hasStringSignature("readObject(ObjectInputStream)") or + m.hasStringSignature("readObjectNoData()") or m.hasName("writeObject(ObjectOutputStream)") ) and - not m.isPrivate() -select m, "readObject and writeObject should be private methods." + ( + not m.isPrivate() and reason = "Method must be private" + or m.isStatic() and reason = "Method must not be static" + or not m.getReturnType() instanceof VoidType and reason = "Return type must be void" + ) +select m, reason diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethodsSig.java b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethodsSig.java index fca8fd6f558..c5163660ece 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethodsSig.java +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethodsSig.java @@ -1,4 +1,6 @@ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; +private void readObjectNoData() + throws ObjectStreamException; private void writeObject(java.io.ObjectOutputStream out) throws IOException; \ No newline at end of file From ea0a0522a7d8a018bdf728ae4bc64ae8174b9eb9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 11 Oct 2021 00:08:32 +0000 Subject: [PATCH 210/361] Add changed framework coverage reports --- java/documentation/library-coverage/coverage.csv | 2 +- java/documentation/library-coverage/coverage.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index 220a9025bff..2c187b90265 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -30,7 +30,7 @@ java.lang,,,50,,,,,,,,,,,,,,,,,,,,,41,9 java.net,10,3,7,,,,,,,,,,,10,,,,,,,,,3,7, java.nio,10,,4,,10,,,,,,,,,,,,,,,,,,,4, java.sql,7,,,,,,,,,,,,,,,7,,,,,,,,, -java.util,,,337,,,,,,,,,,,,,,,,,,,,,15,322 +java.util,,,417,,,,,,,,,,,,,,,,,,,,,15,402 javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,2,,7,, javax.json,,,123,,,,,,,,,,,,,,,,,,,,,100,23 javax.management.remote,2,,,,,,,,,2,,,,,,,,,,,,,,, diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index 46a091579c7..68d9a911fe4 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -15,9 +15,9 @@ Java framework & library support `Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25 `Google Guava <https://guava.dev/>`_,``com.google.common.*``,,728,6,,6,,,,, `JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,, - Java Standard Library,``java.*``,3,426,30,13,,,7,,,10 + Java Standard Library,``java.*``,3,506,30,13,,,7,,,10 Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2 `Spring <https://spring.io/>`_,``org.springframework.*``,29,469,91,,,,19,14,,29 Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,28,151,,,,14,18,, - Totals,,143,5137,408,13,6,10,107,33,1,66 + Totals,,143,5217,408,13,6,10,107,33,1,66 From b05d76a131e84676bf440fd0a5d301c31a7cdc90 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 11 Oct 2021 09:30:52 +0200 Subject: [PATCH 211/361] C#: Avoid bad magic in `interpretElement0` --- csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll index c7140238213..b689602d7bf 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll @@ -404,6 +404,7 @@ private string paramsString(InterpretedCallable c) { ) } +pragma[nomagic] private Element interpretElement0( string namespace, string type, boolean subtypes, string name, string signature ) { From 1552c108b0ab456318b9c4524b3990edb7124e6e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 11 Oct 2021 09:34:15 +0200 Subject: [PATCH 212/361] Python: Apply suggestions from code review Co-authored-by: yoff <lerchedahl@gmail.com> --- .../2021-10-08-add-dataflow-for-boolean-expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/change-notes/2021-10-08-add-dataflow-for-boolean-expressions.md b/python/change-notes/2021-10-08-add-dataflow-for-boolean-expressions.md index ba90b6ec9f2..2c6a39f481f 100644 --- a/python/change-notes/2021-10-08-add-dataflow-for-boolean-expressions.md +++ b/python/change-notes/2021-10-08-add-dataflow-for-boolean-expressions.md @@ -1,3 +1,3 @@ lgtm,codescanning -* Added data-flow from `x` in both `x or y` and `x and y`, as described in the +* Added data-flow from both `x` and `y` to `x or y` and `x and y`, as a slight over-approximation of what is described in the [Python Language Reference](https://docs.python.org/3/reference/expressions.html#boolean-operations). From 8444388ec76e2905c59849064c80761198f5b8d1 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 11 Oct 2021 09:46:47 +0200 Subject: [PATCH 213/361] Python: Update `.expected` --- .../dataflow/coverage/dataflow.expected | 1164 +++++++++-------- .../dataflow/fieldflow/allLocalFlow.expected | 5 + .../dataflow/fieldflow/globalStep.expected | 10 + 3 files changed, 601 insertions(+), 578 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 68cd9dc50ee..f89248985d7 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -148,243 +148,245 @@ edges | test.py:412:10:412:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:407:26:407:26 | ControlFlowNode for b [Dictionary element at key b] | | test.py:412:10:412:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() | | test.py:412:39:412:44 | ControlFlowNode for SOURCE | test.py:412:10:412:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:433:10:433:15 | ControlFlowNode for SOURCE | test.py:433:10:433:38 | ControlFlowNode for IfExp | -| test.py:441:34:441:39 | ControlFlowNode for SOURCE | test.py:441:10:441:39 | ControlFlowNode for IfExp | -| test.py:462:11:462:11 | ControlFlowNode for x | test.py:463:16:463:16 | ControlFlowNode for x | -| test.py:465:12:465:17 | ControlFlowNode for SOURCE | test.py:462:11:462:11 | ControlFlowNode for x | -| test.py:465:12:465:17 | ControlFlowNode for SOURCE | test.py:465:10:465:18 | ControlFlowNode for f() | -| test.py:469:19:469:19 | ControlFlowNode for b | test.py:470:16:470:16 | ControlFlowNode for b | -| test.py:472:28:472:33 | ControlFlowNode for SOURCE | test.py:469:19:469:19 | ControlFlowNode for b | -| test.py:472:28:472:33 | ControlFlowNode for SOURCE | test.py:472:10:472:34 | ControlFlowNode for second() | -| test.py:483:19:483:19 | ControlFlowNode for b | test.py:484:16:484:16 | ControlFlowNode for b | -| test.py:486:30:486:35 | ControlFlowNode for SOURCE | test.py:483:19:483:19 | ControlFlowNode for b | -| test.py:486:30:486:35 | ControlFlowNode for SOURCE | test.py:486:10:486:36 | ControlFlowNode for second() | -| test.py:497:19:497:19 | ControlFlowNode for b | test.py:498:16:498:16 | ControlFlowNode for b | -| test.py:500:10:500:43 | KwUnpacked b | test.py:497:19:497:19 | ControlFlowNode for b | -| test.py:500:10:500:43 | KwUnpacked b | test.py:500:10:500:43 | ControlFlowNode for second() | -| test.py:500:30:500:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:500:10:500:43 | KwUnpacked b | -| test.py:500:36:500:41 | ControlFlowNode for SOURCE | test.py:500:30:500:42 | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:504:30:504:30 | ControlFlowNode for b [Tuple element at index 0] | test.py:504:33:504:33 | ControlFlowNode for b [Tuple element at index 0] | -| test.py:504:33:504:33 | ControlFlowNode for b [Tuple element at index 0] | test.py:504:33:504:36 | ControlFlowNode for Subscript | -| test.py:505:10:505:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:504:30:504:30 | ControlFlowNode for b [Tuple element at index 0] | -| test.py:505:10:505:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() | -| test.py:505:33:505:38 | ControlFlowNode for SOURCE | test.py:505:10:505:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:509:35:509:35 | ControlFlowNode for b [Dictionary element at key b] | test.py:509:38:509:38 | ControlFlowNode for b [Dictionary element at key b] | -| test.py:509:38:509:38 | ControlFlowNode for b [Dictionary element at key b] | test.py:509:38:509:43 | ControlFlowNode for Subscript | -| test.py:510:10:510:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:509:35:509:35 | ControlFlowNode for b [Dictionary element at key b] | -| test.py:510:10:510:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() | -| test.py:510:39:510:44 | ControlFlowNode for SOURCE | test.py:510:10:510:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:522:9:522:14 | ControlFlowNode for SOURCE | test.py:524:10:524:10 | ControlFlowNode for a | -| test.py:522:9:522:14 | ControlFlowNode for SOURCE | test.py:529:10:529:10 | ControlFlowNode for b | -| test.py:534:10:534:15 | ControlFlowNode for SOURCE | test.py:534:10:534:26 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:534:10:534:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:535:5:535:8 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:535:5:535:5 | SSA variable a | test.py:536:10:536:10 | ControlFlowNode for a | -| test.py:535:5:535:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:535:5:535:5 | SSA variable a | -| test.py:542:10:542:15 | ControlFlowNode for SOURCE | test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:542:19:542:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:542:30:542:35 | ControlFlowNode for SOURCE | test.py:542:19:542:35 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:543:5:543:5 | SSA variable a | test.py:544:10:544:10 | ControlFlowNode for a | -| test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:543:5:543:5 | SSA variable a | -| test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:543:9:543:12 | IterableSequence [Tuple element at index 1] | -| test.py:543:9:543:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:543:12:543:12 | SSA variable c | -| test.py:543:9:543:12 | IterableSequence [Tuple element at index 1] | test.py:543:9:543:12 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:543:12:543:12 | SSA variable c | test.py:546:10:546:10 | ControlFlowNode for c | -| test.py:551:9:551:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:552:5:552:14 | IterableSequence [List element, List element, List element, List element] | -| test.py:551:10:551:21 | ControlFlowNode for List [List element, List element, List element] | test.py:551:9:551:33 | ControlFlowNode for List [List element, List element, List element, List element] | -| test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] | test.py:551:10:551:21 | ControlFlowNode for List [List element, List element, List element] | -| test.py:551:12:551:19 | ControlFlowNode for List [List element] | test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] | -| test.py:551:13:551:18 | ControlFlowNode for SOURCE | test.py:551:12:551:19 | ControlFlowNode for List [List element] | -| test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | test.py:552:6:552:10 | IterableSequence [List element, List element] | -| test.py:552:5:552:11 | IterableElement [List element, List element] | test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | -| test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | test.py:552:5:552:11 | IterableElement [List element, List element] | -| test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | -| test.py:552:5:552:14 | IterableElement [List element, List element, List element] | test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | -| test.py:552:5:552:14 | IterableSequence [List element, List element, List element, List element] | test.py:552:5:552:14 | IterableElement [List element, List element, List element] | -| test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] | test.py:552:7:552:9 | IterableSequence [List element] | -| test.py:552:6:552:10 | IterableElement [List element] | test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] | -| test.py:552:6:552:10 | IterableSequence [List element, List element] | test.py:552:6:552:10 | IterableElement [List element] | -| test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] | test.py:552:8:552:8 | SSA variable a | -| test.py:552:7:552:9 | IterableElement | test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] | -| test.py:552:7:552:9 | IterableSequence [List element] | test.py:552:7:552:9 | IterableElement | -| test.py:552:8:552:8 | SSA variable a | test.py:553:10:553:10 | ControlFlowNode for a | -| test.py:559:10:559:15 | ControlFlowNode for SOURCE | test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:560:5:560:5 | SSA variable a | test.py:561:10:561:10 | ControlFlowNode for a | -| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:560:5:560:5 | SSA variable a | -| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:560:8:560:9 | IterableElement | -| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:560:12:560:12 | SSA variable c | -| test.py:560:8:560:9 | IterableElement | test.py:560:8:560:9 | SSA variable b [List element] | -| test.py:560:8:560:9 | SSA variable b [List element] | test.py:563:10:563:10 | ControlFlowNode for b [List element] | -| test.py:560:12:560:12 | SSA variable c | test.py:564:12:564:12 | ControlFlowNode for c | -| test.py:563:10:563:10 | ControlFlowNode for b [List element] | test.py:563:10:563:13 | ControlFlowNode for Subscript | -| test.py:569:10:569:15 | ControlFlowNode for SOURCE | test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:569:18:569:23 | ControlFlowNode for SOURCE | test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:570:5:570:5 | SSA variable a | test.py:571:10:571:10 | ControlFlowNode for a | -| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:570:5:570:5 | SSA variable a | -| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:570:12:570:12 | SSA variable c | -| test.py:570:12:570:12 | SSA variable c | test.py:573:10:573:10 | ControlFlowNode for c | -| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:581:6:581:23 | IterableSequence [List element, List element] | -| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:589:5:589:24 | IterableSequence [List element, List element] | -| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:597:6:597:23 | IterableSequence [List element, List element] | -| test.py:578:11:578:37 | ControlFlowNode for List [List element] | test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | -| test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:578:11:578:37 | ControlFlowNode for List [List element] | -| test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:578:11:578:37 | ControlFlowNode for List [List element] | -| test.py:578:40:578:47 | ControlFlowNode for List [List element] | test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | -| test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:578:40:578:47 | ControlFlowNode for List [List element] | -| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:581:7:581:16 | IterableSequence [List element] | -| test.py:581:6:581:23 | IterableElement [List element] | test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:581:6:581:23 | IterableSequence [List element, List element] | test.py:581:6:581:23 | IterableElement [List element] | -| test.py:581:7:581:8 | SSA variable a1 | test.py:582:10:582:11 | ControlFlowNode for a1 | -| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:581:7:581:8 | SSA variable a1 | -| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:581:11:581:12 | SSA variable a2 | -| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:581:15:581:16 | SSA variable a3 | -| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:581:7:581:16 | IterableSequence [List element] | test.py:581:7:581:16 | IterableElement | -| test.py:581:11:581:12 | SSA variable a2 | test.py:583:12:583:13 | ControlFlowNode for a2 | -| test.py:581:15:581:16 | SSA variable a3 | test.py:584:10:584:11 | ControlFlowNode for a3 | -| test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] | test.py:589:7:589:16 | IterableSequence [List element] | -| test.py:589:5:589:24 | IterableElement [List element] | test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] | -| test.py:589:5:589:24 | IterableSequence [List element, List element] | test.py:589:5:589:24 | IterableElement [List element] | -| test.py:589:7:589:8 | SSA variable a1 | test.py:590:10:590:11 | ControlFlowNode for a1 | -| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:589:7:589:8 | SSA variable a1 | -| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:589:11:589:12 | SSA variable a2 | -| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:589:15:589:16 | SSA variable a3 | -| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:589:7:589:16 | IterableSequence [List element] | test.py:589:7:589:16 | IterableElement | -| test.py:589:11:589:12 | SSA variable a2 | test.py:591:12:591:13 | ControlFlowNode for a2 | -| test.py:589:15:589:16 | SSA variable a3 | test.py:592:10:592:11 | ControlFlowNode for a3 | -| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] | test.py:597:7:597:8 | SSA variable a1 | -| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] | test.py:597:11:597:12 | SSA variable a2 | -| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] | test.py:597:15:597:16 | SSA variable a3 | -| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] | -| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] | -| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] | -| test.py:597:6:597:17 | IterableSequence [List element] | test.py:597:6:597:17 | IterableElement | -| test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:597:6:597:17 | IterableSequence [List element] | -| test.py:597:6:597:23 | IterableElement [List element] | test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:597:6:597:23 | IterableSequence [List element, List element] | test.py:597:6:597:23 | IterableElement [List element] | -| test.py:597:7:597:8 | SSA variable a1 | test.py:598:10:598:11 | ControlFlowNode for a1 | -| test.py:597:11:597:12 | SSA variable a2 | test.py:599:12:599:13 | ControlFlowNode for a2 | -| test.py:597:15:597:16 | SSA variable a3 | test.py:600:10:600:11 | ControlFlowNode for a3 | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] | -| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] | -| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:609:7:609:8 | SSA variable a1 | -| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] | test.py:609:11:609:13 | IterableElement | -| test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] | test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] | -| test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] | test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] | +| test.py:429:15:429:20 | ControlFlowNode for SOURCE | test.py:429:10:429:20 | ControlFlowNode for BoolExpr | +| test.py:434:16:434:21 | ControlFlowNode for SOURCE | test.py:434:10:434:21 | ControlFlowNode for BoolExpr | +| test.py:445:10:445:15 | ControlFlowNode for SOURCE | test.py:445:10:445:38 | ControlFlowNode for IfExp | +| test.py:453:34:453:39 | ControlFlowNode for SOURCE | test.py:453:10:453:39 | ControlFlowNode for IfExp | +| test.py:474:11:474:11 | ControlFlowNode for x | test.py:475:16:475:16 | ControlFlowNode for x | +| test.py:477:12:477:17 | ControlFlowNode for SOURCE | test.py:474:11:474:11 | ControlFlowNode for x | +| test.py:477:12:477:17 | ControlFlowNode for SOURCE | test.py:477:10:477:18 | ControlFlowNode for f() | +| test.py:481:19:481:19 | ControlFlowNode for b | test.py:482:16:482:16 | ControlFlowNode for b | +| test.py:484:28:484:33 | ControlFlowNode for SOURCE | test.py:481:19:481:19 | ControlFlowNode for b | +| test.py:484:28:484:33 | ControlFlowNode for SOURCE | test.py:484:10:484:34 | ControlFlowNode for second() | +| test.py:495:19:495:19 | ControlFlowNode for b | test.py:496:16:496:16 | ControlFlowNode for b | +| test.py:498:30:498:35 | ControlFlowNode for SOURCE | test.py:495:19:495:19 | ControlFlowNode for b | +| test.py:498:30:498:35 | ControlFlowNode for SOURCE | test.py:498:10:498:36 | ControlFlowNode for second() | +| test.py:509:19:509:19 | ControlFlowNode for b | test.py:510:16:510:16 | ControlFlowNode for b | +| test.py:512:10:512:43 | KwUnpacked b | test.py:509:19:509:19 | ControlFlowNode for b | +| test.py:512:10:512:43 | KwUnpacked b | test.py:512:10:512:43 | ControlFlowNode for second() | +| test.py:512:30:512:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:512:10:512:43 | KwUnpacked b | +| test.py:512:36:512:41 | ControlFlowNode for SOURCE | test.py:512:30:512:42 | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:516:30:516:30 | ControlFlowNode for b [Tuple element at index 0] | test.py:516:33:516:33 | ControlFlowNode for b [Tuple element at index 0] | +| test.py:516:33:516:33 | ControlFlowNode for b [Tuple element at index 0] | test.py:516:33:516:36 | ControlFlowNode for Subscript | +| test.py:517:10:517:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:516:30:516:30 | ControlFlowNode for b [Tuple element at index 0] | +| test.py:517:10:517:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:517:10:517:39 | ControlFlowNode for f_extra_pos() | +| test.py:517:33:517:38 | ControlFlowNode for SOURCE | test.py:517:10:517:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:521:35:521:35 | ControlFlowNode for b [Dictionary element at key b] | test.py:521:38:521:38 | ControlFlowNode for b [Dictionary element at key b] | +| test.py:521:38:521:38 | ControlFlowNode for b [Dictionary element at key b] | test.py:521:38:521:43 | ControlFlowNode for Subscript | +| test.py:522:10:522:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:521:35:521:35 | ControlFlowNode for b [Dictionary element at key b] | +| test.py:522:10:522:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:522:10:522:45 | ControlFlowNode for f_extra_keyword() | +| test.py:522:39:522:44 | ControlFlowNode for SOURCE | test.py:522:10:522:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:534:9:534:14 | ControlFlowNode for SOURCE | test.py:536:10:536:10 | ControlFlowNode for a | +| test.py:534:9:534:14 | ControlFlowNode for SOURCE | test.py:541:10:541:10 | ControlFlowNode for b | +| test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:26 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:546:10:546:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:8 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | +| test.py:547:5:547:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | +| test.py:554:10:554:15 | ControlFlowNode for SOURCE | test.py:554:10:554:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:554:10:554:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:555:5:555:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:554:10:554:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:555:5:555:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:554:19:554:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:554:10:554:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:554:30:554:35 | ControlFlowNode for SOURCE | test.py:554:19:554:35 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:555:5:555:5 | SSA variable a | test.py:556:10:556:10 | ControlFlowNode for a | +| test.py:555:5:555:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:555:5:555:5 | SSA variable a | +| test.py:555:5:555:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:555:9:555:12 | IterableSequence [Tuple element at index 1] | +| test.py:555:9:555:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:555:12:555:12 | SSA variable c | +| test.py:555:9:555:12 | IterableSequence [Tuple element at index 1] | test.py:555:9:555:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:555:12:555:12 | SSA variable c | test.py:558:10:558:10 | ControlFlowNode for c | +| test.py:563:9:563:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:564:5:564:14 | IterableSequence [List element, List element, List element, List element] | +| test.py:563:10:563:21 | ControlFlowNode for List [List element, List element, List element] | test.py:563:9:563:33 | ControlFlowNode for List [List element, List element, List element, List element] | +| test.py:563:11:563:20 | ControlFlowNode for List [List element, List element] | test.py:563:10:563:21 | ControlFlowNode for List [List element, List element, List element] | +| test.py:563:12:563:19 | ControlFlowNode for List [List element] | test.py:563:11:563:20 | ControlFlowNode for List [List element, List element] | +| test.py:563:13:563:18 | ControlFlowNode for SOURCE | test.py:563:12:563:19 | ControlFlowNode for List [List element] | +| test.py:564:5:564:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | test.py:564:6:564:10 | IterableSequence [List element, List element] | +| test.py:564:5:564:11 | IterableElement [List element, List element] | test.py:564:5:564:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | +| test.py:564:5:564:11 | IterableSequence [List element, List element, List element] | test.py:564:5:564:11 | IterableElement [List element, List element] | +| test.py:564:5:564:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:564:5:564:11 | IterableSequence [List element, List element, List element] | +| test.py:564:5:564:14 | IterableElement [List element, List element, List element] | test.py:564:5:564:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:564:5:564:14 | IterableSequence [List element, List element, List element, List element] | test.py:564:5:564:14 | IterableElement [List element, List element, List element] | +| test.py:564:6:564:10 | ControlFlowNode for List [Tuple element at index 0, List element] | test.py:564:7:564:9 | IterableSequence [List element] | +| test.py:564:6:564:10 | IterableElement [List element] | test.py:564:6:564:10 | ControlFlowNode for List [Tuple element at index 0, List element] | +| test.py:564:6:564:10 | IterableSequence [List element, List element] | test.py:564:6:564:10 | IterableElement [List element] | +| test.py:564:7:564:9 | ControlFlowNode for List [Tuple element at index 0] | test.py:564:8:564:8 | SSA variable a | +| test.py:564:7:564:9 | IterableElement | test.py:564:7:564:9 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:564:7:564:9 | IterableSequence [List element] | test.py:564:7:564:9 | IterableElement | +| test.py:564:8:564:8 | SSA variable a | test.py:565:10:565:10 | ControlFlowNode for a | +| test.py:571:10:571:15 | ControlFlowNode for SOURCE | test.py:571:10:571:34 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:571:10:571:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:572:5:572:12 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:571:10:571:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:572:5:572:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:571:18:571:23 | ControlFlowNode for SOURCE | test.py:571:10:571:34 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:572:5:572:5 | SSA variable a | test.py:573:10:573:10 | ControlFlowNode for a | +| test.py:572:5:572:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:572:5:572:5 | SSA variable a | +| test.py:572:5:572:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:572:8:572:9 | IterableElement | +| test.py:572:5:572:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:572:12:572:12 | SSA variable c | +| test.py:572:8:572:9 | IterableElement | test.py:572:8:572:9 | SSA variable b [List element] | +| test.py:572:8:572:9 | SSA variable b [List element] | test.py:575:10:575:10 | ControlFlowNode for b [List element] | +| test.py:572:12:572:12 | SSA variable c | test.py:576:12:576:12 | ControlFlowNode for c | +| test.py:575:10:575:10 | ControlFlowNode for b [List element] | test.py:575:10:575:13 | ControlFlowNode for Subscript | +| test.py:581:10:581:15 | ControlFlowNode for SOURCE | test.py:581:10:581:23 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:581:10:581:23 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:582:5:582:12 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:581:10:581:23 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:582:5:582:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:581:18:581:23 | ControlFlowNode for SOURCE | test.py:581:10:581:23 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:582:5:582:5 | SSA variable a | test.py:583:10:583:10 | ControlFlowNode for a | +| test.py:582:5:582:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:582:5:582:5 | SSA variable a | +| test.py:582:5:582:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:582:12:582:12 | SSA variable c | +| test.py:582:12:582:12 | SSA variable c | test.py:585:10:585:10 | ControlFlowNode for c | +| test.py:590:10:590:61 | ControlFlowNode for List [List element, List element] | test.py:593:6:593:23 | IterableSequence [List element, List element] | +| test.py:590:10:590:61 | ControlFlowNode for List [List element, List element] | test.py:601:5:601:24 | IterableSequence [List element, List element] | +| test.py:590:10:590:61 | ControlFlowNode for List [List element, List element] | test.py:609:6:609:23 | IterableSequence [List element, List element] | +| test.py:590:11:590:37 | ControlFlowNode for List [List element] | test.py:590:10:590:61 | ControlFlowNode for List [List element, List element] | +| test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:590:11:590:37 | ControlFlowNode for List [List element] | +| test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:590:11:590:37 | ControlFlowNode for List [List element] | +| test.py:590:40:590:47 | ControlFlowNode for List [List element] | test.py:590:10:590:61 | ControlFlowNode for List [List element, List element] | +| test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:590:40:590:47 | ControlFlowNode for List [List element] | +| test.py:593:6:593:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:593:7:593:16 | IterableSequence [List element] | +| test.py:593:6:593:23 | IterableElement [List element] | test.py:593:6:593:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:593:6:593:23 | IterableSequence [List element, List element] | test.py:593:6:593:23 | IterableElement [List element] | +| test.py:593:7:593:8 | SSA variable a1 | test.py:594:10:594:11 | ControlFlowNode for a1 | +| test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:593:7:593:8 | SSA variable a1 | +| test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:593:11:593:12 | SSA variable a2 | +| test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:593:15:593:16 | SSA variable a3 | +| test.py:593:7:593:16 | IterableElement | test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:593:7:593:16 | IterableElement | test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:593:7:593:16 | IterableElement | test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:593:7:593:16 | IterableSequence [List element] | test.py:593:7:593:16 | IterableElement | +| test.py:593:11:593:12 | SSA variable a2 | test.py:595:12:595:13 | ControlFlowNode for a2 | +| test.py:593:15:593:16 | SSA variable a3 | test.py:596:10:596:11 | ControlFlowNode for a3 | +| test.py:601:5:601:24 | ControlFlowNode for List [Tuple element at index 0, List element] | test.py:601:7:601:16 | IterableSequence [List element] | +| test.py:601:5:601:24 | IterableElement [List element] | test.py:601:5:601:24 | ControlFlowNode for List [Tuple element at index 0, List element] | +| test.py:601:5:601:24 | IterableSequence [List element, List element] | test.py:601:5:601:24 | IterableElement [List element] | +| test.py:601:7:601:8 | SSA variable a1 | test.py:602:10:602:11 | ControlFlowNode for a1 | +| test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:601:7:601:8 | SSA variable a1 | +| test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:601:11:601:12 | SSA variable a2 | +| test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:601:15:601:16 | SSA variable a3 | +| test.py:601:7:601:16 | IterableElement | test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:601:7:601:16 | IterableElement | test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:601:7:601:16 | IterableElement | test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:601:7:601:16 | IterableSequence [List element] | test.py:601:7:601:16 | IterableElement | +| test.py:601:11:601:12 | SSA variable a2 | test.py:603:12:603:13 | ControlFlowNode for a2 | +| test.py:601:15:601:16 | SSA variable a3 | test.py:604:10:604:11 | ControlFlowNode for a3 | +| test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 0] | test.py:609:7:609:8 | SSA variable a1 | +| test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 1] | test.py:609:11:609:12 | SSA variable a2 | +| test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 2] | test.py:609:15:609:16 | SSA variable a3 | +| test.py:609:6:609:17 | IterableElement | test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:609:6:609:17 | IterableElement | test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 1] | +| test.py:609:6:609:17 | IterableElement | test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 2] | +| test.py:609:6:609:17 | IterableSequence [List element] | test.py:609:6:609:17 | IterableElement | +| test.py:609:6:609:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:609:6:609:17 | IterableSequence [List element] | +| test.py:609:6:609:23 | IterableElement [List element] | test.py:609:6:609:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:609:6:609:23 | IterableSequence [List element, List element] | test.py:609:6:609:23 | IterableElement [List element] | | test.py:609:7:609:8 | SSA variable a1 | test.py:610:10:610:11 | ControlFlowNode for a1 | -| test.py:609:11:609:13 | IterableElement | test.py:609:11:609:13 | SSA variable a2 [List element] | -| test.py:609:11:609:13 | SSA variable a2 [List element] | test.py:612:12:612:13 | ControlFlowNode for a2 [List element] | -| test.py:609:11:609:13 | SSA variable a2 [List element] | test.py:613:10:613:11 | ControlFlowNode for a2 [List element] | -| test.py:612:12:612:13 | ControlFlowNode for a2 [List element] | test.py:612:12:612:16 | ControlFlowNode for Subscript | -| test.py:613:10:613:11 | ControlFlowNode for a2 [List element] | test.py:613:10:613:14 | ControlFlowNode for Subscript | -| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] | -| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] | -| test.py:618:7:618:8 | SSA variable a1 | test.py:619:10:619:11 | ControlFlowNode for a1 | -| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:618:7:618:8 | SSA variable a1 | -| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:618:11:618:13 | IterableElement | -| test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:618:11:618:13 | IterableElement | test.py:618:11:618:13 | SSA variable a2 [List element] | -| test.py:618:11:618:13 | SSA variable a2 [List element] | test.py:621:12:621:13 | ControlFlowNode for a2 [List element] | -| test.py:618:11:618:13 | SSA variable a2 [List element] | test.py:622:10:622:11 | ControlFlowNode for a2 [List element] | -| test.py:621:12:621:13 | ControlFlowNode for a2 [List element] | test.py:621:12:621:16 | ControlFlowNode for Subscript | -| test.py:622:10:622:11 | ControlFlowNode for a2 [List element] | test.py:622:10:622:14 | ControlFlowNode for Subscript | -| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] | -| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] | -| test.py:627:7:627:8 | SSA variable a1 | test.py:628:10:628:11 | ControlFlowNode for a1 | -| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:627:7:627:8 | SSA variable a1 | -| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:627:11:627:13 | IterableElement | -| test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] | test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] | test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:627:11:627:13 | IterableElement | test.py:627:11:627:13 | SSA variable a2 [List element] | -| test.py:627:11:627:13 | SSA variable a2 [List element] | test.py:630:12:630:13 | ControlFlowNode for a2 [List element] | -| test.py:627:11:627:13 | SSA variable a2 [List element] | test.py:631:10:631:11 | ControlFlowNode for a2 [List element] | -| test.py:630:12:630:13 | ControlFlowNode for a2 [List element] | test.py:630:12:630:16 | ControlFlowNode for Subscript | -| test.py:631:10:631:11 | ControlFlowNode for a2 [List element] | test.py:631:10:631:14 | ControlFlowNode for Subscript | -| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:636:7:636:8 | SSA variable a1 | -| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] | test.py:636:11:636:13 | IterableElement | -| test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] | test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] | -| test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] | test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] | -| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] | -| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] | -| test.py:636:7:636:8 | SSA variable a1 | test.py:637:10:637:11 | ControlFlowNode for a1 | -| test.py:636:11:636:13 | IterableElement | test.py:636:11:636:13 | SSA variable a2 [List element] | -| test.py:636:11:636:13 | SSA variable a2 [List element] | test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | -| test.py:636:11:636:13 | SSA variable a2 [List element] | test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | -| test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | test.py:639:12:639:16 | ControlFlowNode for Subscript | -| test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | test.py:640:10:640:14 | ControlFlowNode for Subscript | -| test.py:647:19:647:24 | ControlFlowNode for SOURCE | test.py:648:10:648:10 | ControlFlowNode for a | -| test.py:655:10:655:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:656:16:656:17 | ControlFlowNode for tl [List element, Tuple element at index 0] | -| test.py:655:12:655:17 | ControlFlowNode for SOURCE | test.py:655:12:655:28 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:655:12:655:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:655:10:655:51 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:655:33:655:38 | ControlFlowNode for SOURCE | test.py:655:33:655:49 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:655:33:655:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:655:10:655:51 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:656:9:656:9 | SSA variable x | test.py:657:14:657:14 | ControlFlowNode for x | -| test.py:656:9:656:11 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:656:9:656:9 | SSA variable x | -| test.py:656:9:656:11 | IterableSequence [Tuple element at index 0] | test.py:656:9:656:11 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:656:16:656:17 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:656:9:656:11 | IterableSequence [Tuple element at index 0] | -| test.py:663:10:663:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:664:17:664:18 | ControlFlowNode for tl [List element, Tuple element at index 0] | -| test.py:663:12:663:17 | ControlFlowNode for SOURCE | test.py:663:12:663:28 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:663:12:663:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:663:10:663:51 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:663:33:663:38 | ControlFlowNode for SOURCE | test.py:663:33:663:49 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:663:33:663:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:663:10:663:51 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:664:9:664:10 | IterableElement | test.py:664:9:664:10 | SSA variable x [List element] | -| test.py:664:9:664:10 | SSA variable x [List element] | test.py:666:14:666:14 | ControlFlowNode for x [List element] | -| test.py:664:9:664:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:664:9:664:10 | IterableElement | -| test.py:664:9:664:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:664:12:664:12 | SSA variable y | -| test.py:664:9:664:12 | IterableSequence [Tuple element at index 0] | test.py:664:9:664:12 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:664:12:664:12 | SSA variable y | test.py:667:16:667:16 | ControlFlowNode for y | -| test.py:664:17:664:18 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:664:9:664:12 | IterableSequence [Tuple element at index 0] | -| test.py:666:14:666:14 | ControlFlowNode for x [List element] | test.py:666:14:666:17 | ControlFlowNode for Subscript | -| test.py:672:10:672:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:673:19:673:20 | ControlFlowNode for tl [List element, Tuple element at index 0] | -| test.py:672:12:672:17 | ControlFlowNode for SOURCE | test.py:672:12:672:28 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:672:12:672:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:672:10:672:51 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:672:33:672:38 | ControlFlowNode for SOURCE | test.py:672:33:672:49 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:672:33:672:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:672:10:672:51 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:673:9:673:9 | SSA variable x | test.py:674:14:674:14 | ControlFlowNode for x | -| test.py:673:9:673:14 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:673:9:673:9 | SSA variable x | -| test.py:673:9:673:14 | IterableSequence [Tuple element at index 0] | test.py:673:9:673:14 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:673:19:673:20 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:673:9:673:14 | IterableSequence [Tuple element at index 0] | -| test.py:678:39:678:42 | ControlFlowNode for args [Tuple element at index 0] | test.py:679:14:679:17 | ControlFlowNode for args [Tuple element at index 0] | -| test.py:678:39:678:42 | ControlFlowNode for args [Tuple element at index 1] | test.py:679:14:679:17 | ControlFlowNode for args [Tuple element at index 1] | -| test.py:679:7:679:9 | SSA variable arg | test.py:680:10:680:12 | ControlFlowNode for arg | -| test.py:679:14:679:17 | ControlFlowNode for args [Tuple element at index 0] | test.py:679:7:679:9 | SSA variable arg | -| test.py:679:14:679:17 | ControlFlowNode for args [Tuple element at index 1] | test.py:679:7:679:9 | SSA variable arg | -| test.py:685:7:685:12 | ControlFlowNode for SOURCE | test.py:686:51:686:51 | ControlFlowNode for s | -| test.py:686:3:686:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 0] | test.py:678:39:678:42 | ControlFlowNode for args [Tuple element at index 0] | -| test.py:686:3:686:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 1] | test.py:678:39:678:42 | ControlFlowNode for args [Tuple element at index 1] | -| test.py:686:43:686:48 | ControlFlowNode for SOURCE | test.py:686:3:686:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 0] | -| test.py:686:51:686:51 | ControlFlowNode for s | test.py:686:3:686:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 1] | -| test.py:757:16:757:21 | ControlFlowNode for SOURCE | test.py:760:10:760:36 | ControlFlowNode for return_from_inner_scope() | -| test.py:795:35:795:35 | ControlFlowNode for x | test.py:796:10:796:10 | ControlFlowNode for x | -| test.py:795:37:795:42 | ControlFlowNode for SOURCE | test.py:795:35:795:35 | ControlFlowNode for x | -| test.py:795:48:795:48 | ControlFlowNode for y | test.py:797:10:797:10 | ControlFlowNode for y | -| test.py:795:50:795:55 | ControlFlowNode for SOURCE | test.py:795:48:795:48 | ControlFlowNode for y | -| test.py:795:61:795:61 | ControlFlowNode for z | test.py:798:10:798:10 | ControlFlowNode for z | -| test.py:795:63:795:68 | ControlFlowNode for SOURCE | test.py:795:61:795:61 | ControlFlowNode for z | +| test.py:609:11:609:12 | SSA variable a2 | test.py:611:12:611:13 | ControlFlowNode for a2 | +| test.py:609:15:609:16 | SSA variable a3 | test.py:612:10:612:11 | ControlFlowNode for a3 | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:621:5:621:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:630:6:630:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:639:5:639:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:648:6:648:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:621:5:621:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:630:6:630:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:639:5:639:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:648:6:648:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:618:12:618:17 | ControlFlowNode for SOURCE | test.py:618:12:618:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:618:12:618:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:618:12:618:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:618:12:618:36 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:621:5:621:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:621:6:621:14 | IterableSequence [Tuple element at index 0] | +| test.py:621:5:621:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | test.py:621:6:621:14 | IterableSequence [Tuple element at index 2] | +| test.py:621:6:621:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:621:7:621:8 | SSA variable a1 | +| test.py:621:6:621:14 | ControlFlowNode for List [Tuple element at index 2] | test.py:621:11:621:13 | IterableElement | +| test.py:621:6:621:14 | IterableSequence [Tuple element at index 0] | test.py:621:6:621:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:621:6:621:14 | IterableSequence [Tuple element at index 2] | test.py:621:6:621:14 | ControlFlowNode for List [Tuple element at index 2] | +| test.py:621:7:621:8 | SSA variable a1 | test.py:622:10:622:11 | ControlFlowNode for a1 | +| test.py:621:11:621:13 | IterableElement | test.py:621:11:621:13 | SSA variable a2 [List element] | +| test.py:621:11:621:13 | SSA variable a2 [List element] | test.py:624:12:624:13 | ControlFlowNode for a2 [List element] | +| test.py:621:11:621:13 | SSA variable a2 [List element] | test.py:625:10:625:11 | ControlFlowNode for a2 [List element] | +| test.py:624:12:624:13 | ControlFlowNode for a2 [List element] | test.py:624:12:624:16 | ControlFlowNode for Subscript | +| test.py:625:10:625:11 | ControlFlowNode for a2 [List element] | test.py:625:10:625:14 | ControlFlowNode for Subscript | +| test.py:630:6:630:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:630:7:630:13 | IterableSequence [Tuple element at index 0] | +| test.py:630:6:630:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:630:7:630:13 | IterableSequence [Tuple element at index 2] | +| test.py:630:7:630:8 | SSA variable a1 | test.py:631:10:631:11 | ControlFlowNode for a1 | +| test.py:630:7:630:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:630:7:630:8 | SSA variable a1 | +| test.py:630:7:630:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:630:11:630:13 | IterableElement | +| test.py:630:7:630:13 | IterableSequence [Tuple element at index 0] | test.py:630:7:630:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:630:7:630:13 | IterableSequence [Tuple element at index 2] | test.py:630:7:630:13 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:630:11:630:13 | IterableElement | test.py:630:11:630:13 | SSA variable a2 [List element] | +| test.py:630:11:630:13 | SSA variable a2 [List element] | test.py:633:12:633:13 | ControlFlowNode for a2 [List element] | +| test.py:630:11:630:13 | SSA variable a2 [List element] | test.py:634:10:634:11 | ControlFlowNode for a2 [List element] | +| test.py:633:12:633:13 | ControlFlowNode for a2 [List element] | test.py:633:12:633:16 | ControlFlowNode for Subscript | +| test.py:634:10:634:11 | ControlFlowNode for a2 [List element] | test.py:634:10:634:14 | ControlFlowNode for Subscript | +| test.py:639:5:639:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:639:7:639:13 | IterableSequence [Tuple element at index 0] | +| test.py:639:5:639:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | test.py:639:7:639:13 | IterableSequence [Tuple element at index 2] | +| test.py:639:7:639:8 | SSA variable a1 | test.py:640:10:640:11 | ControlFlowNode for a1 | +| test.py:639:7:639:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:639:7:639:8 | SSA variable a1 | +| test.py:639:7:639:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:639:11:639:13 | IterableElement | +| test.py:639:7:639:13 | IterableSequence [Tuple element at index 0] | test.py:639:7:639:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:639:7:639:13 | IterableSequence [Tuple element at index 2] | test.py:639:7:639:13 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:639:11:639:13 | IterableElement | test.py:639:11:639:13 | SSA variable a2 [List element] | +| test.py:639:11:639:13 | SSA variable a2 [List element] | test.py:642:12:642:13 | ControlFlowNode for a2 [List element] | +| test.py:639:11:639:13 | SSA variable a2 [List element] | test.py:643:10:643:11 | ControlFlowNode for a2 [List element] | +| test.py:642:12:642:13 | ControlFlowNode for a2 [List element] | test.py:642:12:642:16 | ControlFlowNode for Subscript | +| test.py:643:10:643:11 | ControlFlowNode for a2 [List element] | test.py:643:10:643:14 | ControlFlowNode for Subscript | +| test.py:648:6:648:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:648:7:648:8 | SSA variable a1 | +| test.py:648:6:648:14 | ControlFlowNode for List [Tuple element at index 2] | test.py:648:11:648:13 | IterableElement | +| test.py:648:6:648:14 | IterableSequence [Tuple element at index 0] | test.py:648:6:648:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:648:6:648:14 | IterableSequence [Tuple element at index 2] | test.py:648:6:648:14 | ControlFlowNode for List [Tuple element at index 2] | +| test.py:648:6:648:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:648:6:648:14 | IterableSequence [Tuple element at index 0] | +| test.py:648:6:648:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:648:6:648:14 | IterableSequence [Tuple element at index 2] | +| test.py:648:7:648:8 | SSA variable a1 | test.py:649:10:649:11 | ControlFlowNode for a1 | +| test.py:648:11:648:13 | IterableElement | test.py:648:11:648:13 | SSA variable a2 [List element] | +| test.py:648:11:648:13 | SSA variable a2 [List element] | test.py:651:12:651:13 | ControlFlowNode for a2 [List element] | +| test.py:648:11:648:13 | SSA variable a2 [List element] | test.py:652:10:652:11 | ControlFlowNode for a2 [List element] | +| test.py:651:12:651:13 | ControlFlowNode for a2 [List element] | test.py:651:12:651:16 | ControlFlowNode for Subscript | +| test.py:652:10:652:11 | ControlFlowNode for a2 [List element] | test.py:652:10:652:14 | ControlFlowNode for Subscript | +| test.py:659:19:659:24 | ControlFlowNode for SOURCE | test.py:660:10:660:10 | ControlFlowNode for a | +| test.py:667:10:667:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:668:16:668:17 | ControlFlowNode for tl [List element, Tuple element at index 0] | +| test.py:667:12:667:17 | ControlFlowNode for SOURCE | test.py:667:12:667:28 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:667:12:667:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:667:10:667:51 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:667:33:667:38 | ControlFlowNode for SOURCE | test.py:667:33:667:49 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:667:33:667:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:667:10:667:51 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:668:9:668:9 | SSA variable x | test.py:669:14:669:14 | ControlFlowNode for x | +| test.py:668:9:668:11 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:668:9:668:9 | SSA variable x | +| test.py:668:9:668:11 | IterableSequence [Tuple element at index 0] | test.py:668:9:668:11 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:668:16:668:17 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:668:9:668:11 | IterableSequence [Tuple element at index 0] | +| test.py:675:10:675:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:676:17:676:18 | ControlFlowNode for tl [List element, Tuple element at index 0] | +| test.py:675:12:675:17 | ControlFlowNode for SOURCE | test.py:675:12:675:28 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:675:12:675:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:675:10:675:51 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:675:33:675:38 | ControlFlowNode for SOURCE | test.py:675:33:675:49 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:675:33:675:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:675:10:675:51 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:676:9:676:10 | IterableElement | test.py:676:9:676:10 | SSA variable x [List element] | +| test.py:676:9:676:10 | SSA variable x [List element] | test.py:678:14:678:14 | ControlFlowNode for x [List element] | +| test.py:676:9:676:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:676:9:676:10 | IterableElement | +| test.py:676:9:676:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:676:12:676:12 | SSA variable y | +| test.py:676:9:676:12 | IterableSequence [Tuple element at index 0] | test.py:676:9:676:12 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:676:12:676:12 | SSA variable y | test.py:679:16:679:16 | ControlFlowNode for y | +| test.py:676:17:676:18 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:676:9:676:12 | IterableSequence [Tuple element at index 0] | +| test.py:678:14:678:14 | ControlFlowNode for x [List element] | test.py:678:14:678:17 | ControlFlowNode for Subscript | +| test.py:684:10:684:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:685:19:685:20 | ControlFlowNode for tl [List element, Tuple element at index 0] | +| test.py:684:12:684:17 | ControlFlowNode for SOURCE | test.py:684:12:684:28 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:684:12:684:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:684:10:684:51 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:684:33:684:38 | ControlFlowNode for SOURCE | test.py:684:33:684:49 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:684:33:684:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:684:10:684:51 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:685:9:685:9 | SSA variable x | test.py:686:14:686:14 | ControlFlowNode for x | +| test.py:685:9:685:14 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:685:9:685:9 | SSA variable x | +| test.py:685:9:685:14 | IterableSequence [Tuple element at index 0] | test.py:685:9:685:14 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:685:19:685:20 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:685:9:685:14 | IterableSequence [Tuple element at index 0] | +| test.py:690:39:690:42 | ControlFlowNode for args [Tuple element at index 0] | test.py:691:14:691:17 | ControlFlowNode for args [Tuple element at index 0] | +| test.py:690:39:690:42 | ControlFlowNode for args [Tuple element at index 1] | test.py:691:14:691:17 | ControlFlowNode for args [Tuple element at index 1] | +| test.py:691:7:691:9 | SSA variable arg | test.py:692:10:692:12 | ControlFlowNode for arg | +| test.py:691:14:691:17 | ControlFlowNode for args [Tuple element at index 0] | test.py:691:7:691:9 | SSA variable arg | +| test.py:691:14:691:17 | ControlFlowNode for args [Tuple element at index 1] | test.py:691:7:691:9 | SSA variable arg | +| test.py:697:7:697:12 | ControlFlowNode for SOURCE | test.py:698:51:698:51 | ControlFlowNode for s | +| test.py:698:3:698:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 0] | test.py:690:39:690:42 | ControlFlowNode for args [Tuple element at index 0] | +| test.py:698:3:698:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 1] | test.py:690:39:690:42 | ControlFlowNode for args [Tuple element at index 1] | +| test.py:698:43:698:48 | ControlFlowNode for SOURCE | test.py:698:3:698:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 0] | +| test.py:698:51:698:51 | ControlFlowNode for s | test.py:698:3:698:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 1] | +| test.py:769:16:769:21 | ControlFlowNode for SOURCE | test.py:772:10:772:36 | ControlFlowNode for return_from_inner_scope() | +| test.py:807:35:807:35 | ControlFlowNode for x | test.py:808:10:808:10 | ControlFlowNode for x | +| test.py:807:37:807:42 | ControlFlowNode for SOURCE | test.py:807:35:807:35 | ControlFlowNode for x | +| test.py:807:48:807:48 | ControlFlowNode for y | test.py:809:10:809:10 | ControlFlowNode for y | +| test.py:807:50:807:55 | ControlFlowNode for SOURCE | test.py:807:48:807:48 | ControlFlowNode for y | +| test.py:807:61:807:61 | ControlFlowNode for z | test.py:810:10:810:10 | ControlFlowNode for z | +| test.py:807:63:807:68 | ControlFlowNode for SOURCE | test.py:807:61:807:61 | ControlFlowNode for z | nodes | datamodel.py:35:7:35:7 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | datamodel.py:36:10:36:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | @@ -567,272 +569,276 @@ nodes | test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | | test.py:412:10:412:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | | test.py:412:39:412:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:433:10:433:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:433:10:433:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | -| test.py:441:10:441:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | -| test.py:441:34:441:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:462:11:462:11 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:463:16:463:16 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:465:10:465:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| test.py:465:12:465:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:469:19:469:19 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:470:16:470:16 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:472:10:472:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:472:28:472:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:483:19:483:19 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:484:16:484:16 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:486:10:486:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:486:30:486:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:497:19:497:19 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:498:16:498:16 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:500:10:500:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:500:10:500:43 | KwUnpacked b | semmle.label | KwUnpacked b | -| test.py:500:30:500:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:500:36:500:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:504:30:504:30 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | -| test.py:504:33:504:33 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | -| test.py:504:33:504:36 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | -| test.py:505:10:505:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:505:33:505:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:509:35:509:35 | ControlFlowNode for b [Dictionary element at key b] | semmle.label | ControlFlowNode for b [Dictionary element at key b] | -| test.py:509:38:509:38 | ControlFlowNode for b [Dictionary element at key b] | semmle.label | ControlFlowNode for b [Dictionary element at key b] | -| test.py:509:38:509:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | -| test.py:510:10:510:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:510:39:510:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:522:9:522:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:524:10:524:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:529:10:529:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:534:10:534:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:534:10:534:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:535:5:535:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:535:5:535:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:429:10:429:20 | ControlFlowNode for BoolExpr | semmle.label | ControlFlowNode for BoolExpr | +| test.py:429:15:429:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:434:10:434:21 | ControlFlowNode for BoolExpr | semmle.label | ControlFlowNode for BoolExpr | +| test.py:434:16:434:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:445:10:445:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:445:10:445:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:453:10:453:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:453:34:453:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:474:11:474:11 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:475:16:475:16 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:477:10:477:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| test.py:477:12:477:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:481:19:481:19 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:482:16:482:16 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:484:10:484:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:484:28:484:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:495:19:495:19 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:496:16:496:16 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:498:10:498:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:498:30:498:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:509:19:509:19 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:510:16:510:16 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:512:10:512:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:512:10:512:43 | KwUnpacked b | semmle.label | KwUnpacked b | +| test.py:512:30:512:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:512:36:512:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:516:30:516:30 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | +| test.py:516:33:516:33 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | +| test.py:516:33:516:36 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:517:10:517:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | +| test.py:517:10:517:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:517:33:517:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:521:35:521:35 | ControlFlowNode for b [Dictionary element at key b] | semmle.label | ControlFlowNode for b [Dictionary element at key b] | +| test.py:521:38:521:38 | ControlFlowNode for b [Dictionary element at key b] | semmle.label | ControlFlowNode for b [Dictionary element at key b] | +| test.py:521:38:521:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:522:10:522:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | +| test.py:522:10:522:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:522:39:522:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:534:9:534:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:536:10:536:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:542:10:542:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:542:19:542:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:542:30:542:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:543:5:543:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:543:9:543:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:543:9:543:12 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | -| test.py:543:12:543:12 | SSA variable c | semmle.label | SSA variable c | -| test.py:544:10:544:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:546:10:546:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | -| test.py:551:9:551:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] | -| test.py:551:10:551:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | -| test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:551:12:551:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:551:13:551:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element, List element] | -| test.py:552:5:552:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] | -| test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] | -| test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | -| test.py:552:5:552:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] | -| test.py:552:5:552:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] | -| test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element] | -| test.py:552:6:552:10 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:552:6:552:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | -| test.py:552:7:552:9 | IterableElement | semmle.label | IterableElement | -| test.py:552:7:552:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:552:8:552:8 | SSA variable a | semmle.label | SSA variable a | -| test.py:553:10:553:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:559:10:559:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:559:18:559:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:560:5:560:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:560:8:560:9 | IterableElement | semmle.label | IterableElement | -| test.py:560:8:560:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | -| test.py:560:12:560:12 | SSA variable c | semmle.label | SSA variable c | -| test.py:561:10:561:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:563:10:563:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | -| test.py:563:10:563:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:564:12:564:12 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | -| test.py:569:10:569:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:569:18:569:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:570:5:570:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:570:12:570:12 | SSA variable c | semmle.label | SSA variable c | -| test.py:571:10:571:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:573:10:573:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | -| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:578:11:578:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:578:12:578:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:578:31:578:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:578:40:578:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:578:41:578:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:581:6:581:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:581:6:581:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:581:7:581:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:581:7:581:16 | IterableElement | semmle.label | IterableElement | -| test.py:581:7:581:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:581:11:581:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:581:15:581:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:582:10:582:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:583:12:583:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:584:10:584:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element] | -| test.py:589:5:589:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:589:5:589:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:589:7:589:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:589:7:589:16 | IterableElement | semmle.label | IterableElement | -| test.py:589:7:589:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:589:11:589:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:589:15:589:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:590:10:590:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:591:12:591:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:592:10:592:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | -| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] | semmle.label | ControlFlowNode for List [Tuple element at index 1] | -| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | -| test.py:597:6:597:17 | IterableElement | semmle.label | IterableElement | -| test.py:597:6:597:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:597:6:597:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:597:6:597:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:597:7:597:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:597:11:597:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:597:15:597:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:598:10:598:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:599:12:599:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:600:10:600:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:606:12:606:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:606:31:606:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | -| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | -| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | -| test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:541:10:541:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:546:10:546:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:546:10:546:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:547:5:547:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:554:10:554:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:554:10:554:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:554:10:554:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:554:19:554:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:554:30:554:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:555:5:555:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:555:5:555:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:555:5:555:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:555:9:555:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:555:9:555:12 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | +| test.py:555:12:555:12 | SSA variable c | semmle.label | SSA variable c | +| test.py:556:10:556:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:558:10:558:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | +| test.py:563:9:563:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] | +| test.py:563:10:563:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:563:11:563:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:563:12:563:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:563:13:563:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:564:5:564:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element, List element] | +| test.py:564:5:564:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] | +| test.py:564:5:564:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] | +| test.py:564:5:564:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:564:5:564:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] | +| test.py:564:5:564:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] | +| test.py:564:6:564:10 | ControlFlowNode for List [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element] | +| test.py:564:6:564:10 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:564:6:564:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:564:7:564:9 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:564:7:564:9 | IterableElement | semmle.label | IterableElement | +| test.py:564:7:564:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:564:8:564:8 | SSA variable a | semmle.label | SSA variable a | +| test.py:565:10:565:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:571:10:571:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:571:10:571:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:571:10:571:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:571:18:571:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:572:5:572:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:572:5:572:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:572:5:572:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:572:8:572:9 | IterableElement | semmle.label | IterableElement | +| test.py:572:8:572:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | +| test.py:572:12:572:12 | SSA variable c | semmle.label | SSA variable c | +| test.py:573:10:573:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:575:10:575:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | +| test.py:575:10:575:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:576:12:576:12 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | +| test.py:581:10:581:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:581:10:581:23 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:581:10:581:23 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:581:18:581:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:582:5:582:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:582:5:582:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:582:5:582:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:582:12:582:12 | SSA variable c | semmle.label | SSA variable c | +| test.py:583:10:583:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:585:10:585:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | +| test.py:590:10:590:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:590:11:590:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:590:12:590:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:590:31:590:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:590:40:590:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:590:41:590:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:593:6:593:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:593:6:593:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:593:6:593:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:593:7:593:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:593:7:593:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:593:7:593:16 | IterableElement | semmle.label | IterableElement | +| test.py:593:7:593:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:593:11:593:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:593:15:593:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:594:10:594:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:595:12:595:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:596:10:596:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:601:5:601:24 | ControlFlowNode for List [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element] | +| test.py:601:5:601:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:601:5:601:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:601:7:601:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:601:7:601:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:601:7:601:16 | IterableElement | semmle.label | IterableElement | +| test.py:601:7:601:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:601:11:601:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:601:15:601:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:602:10:602:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:603:12:603:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:604:10:604:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 1] | semmle.label | ControlFlowNode for List [Tuple element at index 1] | +| test.py:609:6:609:17 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | +| test.py:609:6:609:17 | IterableElement | semmle.label | IterableElement | +| test.py:609:6:609:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:609:6:609:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:609:6:609:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:609:6:609:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | | test.py:609:7:609:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:609:11:609:13 | IterableElement | semmle.label | IterableElement | -| test.py:609:11:609:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:609:11:609:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:609:15:609:16 | SSA variable a3 | semmle.label | SSA variable a3 | | test.py:610:10:610:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:612:12:612:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:612:12:612:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:613:10:613:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:613:10:613:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:618:7:618:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:618:11:618:13 | IterableElement | semmle.label | IterableElement | -| test.py:618:11:618:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:619:10:619:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:621:12:621:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:621:12:621:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:622:10:622:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:622:10:622:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | -| test.py:627:7:627:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:627:11:627:13 | IterableElement | semmle.label | IterableElement | -| test.py:627:11:627:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:628:10:628:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:630:12:630:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:630:12:630:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:631:10:631:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:631:10:631:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | -| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | -| test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:636:7:636:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:636:11:636:13 | IterableElement | semmle.label | IterableElement | -| test.py:636:11:636:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:637:10:637:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:639:12:639:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:640:10:640:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:647:19:647:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:648:10:648:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:655:10:655:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:655:12:655:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:655:12:655:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:655:33:655:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:655:33:655:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:656:9:656:9 | SSA variable x | semmle.label | SSA variable x | -| test.py:656:9:656:11 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:656:9:656:11 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:656:16:656:17 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] | -| test.py:657:14:657:14 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:663:10:663:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:663:12:663:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:663:12:663:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:663:33:663:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:663:33:663:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:664:9:664:10 | IterableElement | semmle.label | IterableElement | -| test.py:664:9:664:10 | SSA variable x [List element] | semmle.label | SSA variable x [List element] | -| test.py:664:9:664:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:664:9:664:12 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:664:12:664:12 | SSA variable y | semmle.label | SSA variable y | -| test.py:664:17:664:18 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] | -| test.py:666:14:666:14 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | -| test.py:666:14:666:17 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:667:16:667:16 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:672:10:672:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:672:12:672:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:672:12:672:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:672:33:672:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:672:33:672:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:673:9:673:9 | SSA variable x | semmle.label | SSA variable x | -| test.py:673:9:673:14 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:673:9:673:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:673:19:673:20 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] | -| test.py:674:14:674:14 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:678:39:678:42 | ControlFlowNode for args [Tuple element at index 0] | semmle.label | ControlFlowNode for args [Tuple element at index 0] | -| test.py:678:39:678:42 | ControlFlowNode for args [Tuple element at index 1] | semmle.label | ControlFlowNode for args [Tuple element at index 1] | -| test.py:679:7:679:9 | SSA variable arg | semmle.label | SSA variable arg | -| test.py:679:14:679:17 | ControlFlowNode for args [Tuple element at index 0] | semmle.label | ControlFlowNode for args [Tuple element at index 0] | -| test.py:679:14:679:17 | ControlFlowNode for args [Tuple element at index 1] | semmle.label | ControlFlowNode for args [Tuple element at index 1] | -| test.py:680:10:680:12 | ControlFlowNode for arg | semmle.label | ControlFlowNode for arg | -| test.py:685:7:685:12 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:686:3:686:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 0] | semmle.label | PosOverflowNode for iterate_star_args() [Tuple element at index 0] | -| test.py:686:3:686:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 1] | semmle.label | PosOverflowNode for iterate_star_args() [Tuple element at index 1] | -| test.py:686:43:686:48 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:686:51:686:51 | ControlFlowNode for s | semmle.label | ControlFlowNode for s | -| test.py:757:16:757:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:760:10:760:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | -| test.py:795:35:795:35 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:795:37:795:42 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:795:48:795:48 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:795:50:795:55 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:795:61:795:61 | ControlFlowNode for z | semmle.label | ControlFlowNode for z | -| test.py:795:63:795:68 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:796:10:796:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:797:10:797:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:798:10:798:10 | ControlFlowNode for z | semmle.label | ControlFlowNode for z | +| test.py:611:12:611:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:612:10:612:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:618:11:618:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:618:12:618:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:618:12:618:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:618:12:618:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:618:31:618:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:621:5:621:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:621:5:621:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | +| test.py:621:6:621:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:621:6:621:14 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | +| test.py:621:6:621:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:621:6:621:14 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:621:7:621:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:621:11:621:13 | IterableElement | semmle.label | IterableElement | +| test.py:621:11:621:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:622:10:622:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:624:12:624:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:624:12:624:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:625:10:625:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:625:10:625:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:630:6:630:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:630:6:630:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:630:7:630:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:630:7:630:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:630:7:630:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:630:7:630:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:630:7:630:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:630:11:630:13 | IterableElement | semmle.label | IterableElement | +| test.py:630:11:630:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:631:10:631:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:633:12:633:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:633:12:633:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:634:10:634:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:634:10:634:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:639:5:639:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:639:5:639:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | +| test.py:639:7:639:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:639:7:639:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:639:7:639:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:639:7:639:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:639:7:639:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:639:11:639:13 | IterableElement | semmle.label | IterableElement | +| test.py:639:11:639:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:640:10:640:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:642:12:642:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:642:12:642:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:643:10:643:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:643:10:643:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:648:6:648:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:648:6:648:14 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | +| test.py:648:6:648:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:648:6:648:14 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:648:6:648:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:648:6:648:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:648:7:648:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:648:11:648:13 | IterableElement | semmle.label | IterableElement | +| test.py:648:11:648:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:649:10:649:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:651:12:651:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:651:12:651:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:652:10:652:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:652:10:652:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:659:19:659:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:660:10:660:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:667:10:667:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:667:12:667:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:667:12:667:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:667:33:667:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:667:33:667:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:668:9:668:9 | SSA variable x | semmle.label | SSA variable x | +| test.py:668:9:668:11 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:668:9:668:11 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:668:16:668:17 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] | +| test.py:669:14:669:14 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:675:10:675:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:675:12:675:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:675:12:675:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:675:33:675:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:675:33:675:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:676:9:676:10 | IterableElement | semmle.label | IterableElement | +| test.py:676:9:676:10 | SSA variable x [List element] | semmle.label | SSA variable x [List element] | +| test.py:676:9:676:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:676:9:676:12 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:676:12:676:12 | SSA variable y | semmle.label | SSA variable y | +| test.py:676:17:676:18 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] | +| test.py:678:14:678:14 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:678:14:678:17 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:679:16:679:16 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:684:10:684:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:684:12:684:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:684:12:684:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:684:33:684:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:684:33:684:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:685:9:685:9 | SSA variable x | semmle.label | SSA variable x | +| test.py:685:9:685:14 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:685:9:685:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:685:19:685:20 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] | +| test.py:686:14:686:14 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:690:39:690:42 | ControlFlowNode for args [Tuple element at index 0] | semmle.label | ControlFlowNode for args [Tuple element at index 0] | +| test.py:690:39:690:42 | ControlFlowNode for args [Tuple element at index 1] | semmle.label | ControlFlowNode for args [Tuple element at index 1] | +| test.py:691:7:691:9 | SSA variable arg | semmle.label | SSA variable arg | +| test.py:691:14:691:17 | ControlFlowNode for args [Tuple element at index 0] | semmle.label | ControlFlowNode for args [Tuple element at index 0] | +| test.py:691:14:691:17 | ControlFlowNode for args [Tuple element at index 1] | semmle.label | ControlFlowNode for args [Tuple element at index 1] | +| test.py:692:10:692:12 | ControlFlowNode for arg | semmle.label | ControlFlowNode for arg | +| test.py:697:7:697:12 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:698:3:698:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 0] | semmle.label | PosOverflowNode for iterate_star_args() [Tuple element at index 0] | +| test.py:698:3:698:52 | PosOverflowNode for iterate_star_args() [Tuple element at index 1] | semmle.label | PosOverflowNode for iterate_star_args() [Tuple element at index 1] | +| test.py:698:43:698:48 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:698:51:698:51 | ControlFlowNode for s | semmle.label | ControlFlowNode for s | +| test.py:769:16:769:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:772:10:772:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | +| test.py:807:35:807:35 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:807:37:807:42 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:807:48:807:48 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:807:50:807:55 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:807:61:807:61 | ControlFlowNode for z | semmle.label | ControlFlowNode for z | +| test.py:807:63:807:68 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:808:10:808:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:809:10:809:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:810:10:810:10 | ControlFlowNode for z | semmle.label | ControlFlowNode for z | subpaths | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:35:7:35:7 | ControlFlowNode for a | datamodel.py:36:10:36:10 | ControlFlowNode for a | datamodel.py:38:6:38:17 | ControlFlowNode for f() | | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:44:22:44:22 | ControlFlowNode for x | datamodel.py:46:16:46:16 | ControlFlowNode for x | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | @@ -844,12 +850,12 @@ subpaths | test.py:396:10:396:43 | KwUnpacked b | test.py:375:15:375:15 | ControlFlowNode for b | test.py:376:12:376:12 | ControlFlowNode for b | test.py:396:10:396:43 | ControlFlowNode for second() | | test.py:404:10:404:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:399:21:399:21 | ControlFlowNode for b [Tuple element at index 0] | test.py:400:12:400:15 | ControlFlowNode for Subscript | test.py:404:10:404:39 | ControlFlowNode for f_extra_pos() | | test.py:412:10:412:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:407:26:407:26 | ControlFlowNode for b [Dictionary element at key b] | test.py:408:12:408:17 | ControlFlowNode for Subscript | test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() | -| test.py:465:12:465:17 | ControlFlowNode for SOURCE | test.py:462:11:462:11 | ControlFlowNode for x | test.py:463:16:463:16 | ControlFlowNode for x | test.py:465:10:465:18 | ControlFlowNode for f() | -| test.py:472:28:472:33 | ControlFlowNode for SOURCE | test.py:469:19:469:19 | ControlFlowNode for b | test.py:470:16:470:16 | ControlFlowNode for b | test.py:472:10:472:34 | ControlFlowNode for second() | -| test.py:486:30:486:35 | ControlFlowNode for SOURCE | test.py:483:19:483:19 | ControlFlowNode for b | test.py:484:16:484:16 | ControlFlowNode for b | test.py:486:10:486:36 | ControlFlowNode for second() | -| test.py:500:10:500:43 | KwUnpacked b | test.py:497:19:497:19 | ControlFlowNode for b | test.py:498:16:498:16 | ControlFlowNode for b | test.py:500:10:500:43 | ControlFlowNode for second() | -| test.py:505:10:505:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:504:30:504:30 | ControlFlowNode for b [Tuple element at index 0] | test.py:504:33:504:36 | ControlFlowNode for Subscript | test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() | -| test.py:510:10:510:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:509:35:509:35 | ControlFlowNode for b [Dictionary element at key b] | test.py:509:38:509:43 | ControlFlowNode for Subscript | test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() | +| test.py:477:12:477:17 | ControlFlowNode for SOURCE | test.py:474:11:474:11 | ControlFlowNode for x | test.py:475:16:475:16 | ControlFlowNode for x | test.py:477:10:477:18 | ControlFlowNode for f() | +| test.py:484:28:484:33 | ControlFlowNode for SOURCE | test.py:481:19:481:19 | ControlFlowNode for b | test.py:482:16:482:16 | ControlFlowNode for b | test.py:484:10:484:34 | ControlFlowNode for second() | +| test.py:498:30:498:35 | ControlFlowNode for SOURCE | test.py:495:19:495:19 | ControlFlowNode for b | test.py:496:16:496:16 | ControlFlowNode for b | test.py:498:10:498:36 | ControlFlowNode for second() | +| test.py:512:10:512:43 | KwUnpacked b | test.py:509:19:509:19 | ControlFlowNode for b | test.py:510:16:510:16 | ControlFlowNode for b | test.py:512:10:512:43 | ControlFlowNode for second() | +| test.py:517:10:517:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:516:30:516:30 | ControlFlowNode for b [Tuple element at index 0] | test.py:516:33:516:36 | ControlFlowNode for Subscript | test.py:517:10:517:39 | ControlFlowNode for f_extra_pos() | +| test.py:522:10:522:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:521:35:521:35 | ControlFlowNode for b [Dictionary element at key b] | test.py:521:38:521:43 | ControlFlowNode for Subscript | test.py:522:10:522:45 | ControlFlowNode for f_extra_keyword() | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | Flow found | @@ -887,76 +893,78 @@ subpaths | test.py:396:10:396:43 | ControlFlowNode for second() | test.py:396:36:396:41 | ControlFlowNode for SOURCE | test.py:396:10:396:43 | ControlFlowNode for second() | Flow found | | test.py:404:10:404:39 | ControlFlowNode for f_extra_pos() | test.py:404:33:404:38 | ControlFlowNode for SOURCE | test.py:404:10:404:39 | ControlFlowNode for f_extra_pos() | Flow found | | test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() | test.py:412:39:412:44 | ControlFlowNode for SOURCE | test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:433:10:433:38 | ControlFlowNode for IfExp | test.py:433:10:433:15 | ControlFlowNode for SOURCE | test.py:433:10:433:38 | ControlFlowNode for IfExp | Flow found | -| test.py:441:10:441:39 | ControlFlowNode for IfExp | test.py:441:34:441:39 | ControlFlowNode for SOURCE | test.py:441:10:441:39 | ControlFlowNode for IfExp | Flow found | -| test.py:465:10:465:18 | ControlFlowNode for f() | test.py:465:12:465:17 | ControlFlowNode for SOURCE | test.py:465:10:465:18 | ControlFlowNode for f() | Flow found | -| test.py:472:10:472:34 | ControlFlowNode for second() | test.py:472:28:472:33 | ControlFlowNode for SOURCE | test.py:472:10:472:34 | ControlFlowNode for second() | Flow found | -| test.py:486:10:486:36 | ControlFlowNode for second() | test.py:486:30:486:35 | ControlFlowNode for SOURCE | test.py:486:10:486:36 | ControlFlowNode for second() | Flow found | -| test.py:500:10:500:43 | ControlFlowNode for second() | test.py:500:36:500:41 | ControlFlowNode for SOURCE | test.py:500:10:500:43 | ControlFlowNode for second() | Flow found | -| test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() | test.py:505:33:505:38 | ControlFlowNode for SOURCE | test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() | test.py:510:39:510:44 | ControlFlowNode for SOURCE | test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:524:10:524:10 | ControlFlowNode for a | test.py:522:9:522:14 | ControlFlowNode for SOURCE | test.py:524:10:524:10 | ControlFlowNode for a | Flow found | -| test.py:529:10:529:10 | ControlFlowNode for b | test.py:522:9:522:14 | ControlFlowNode for SOURCE | test.py:529:10:529:10 | ControlFlowNode for b | Flow found | -| test.py:536:10:536:10 | ControlFlowNode for a | test.py:534:10:534:15 | ControlFlowNode for SOURCE | test.py:536:10:536:10 | ControlFlowNode for a | Flow found | -| test.py:544:10:544:10 | ControlFlowNode for a | test.py:542:10:542:15 | ControlFlowNode for SOURCE | test.py:544:10:544:10 | ControlFlowNode for a | Flow found | -| test.py:546:10:546:10 | ControlFlowNode for c | test.py:542:30:542:35 | ControlFlowNode for SOURCE | test.py:546:10:546:10 | ControlFlowNode for c | Flow found | -| test.py:553:10:553:10 | ControlFlowNode for a | test.py:551:13:551:18 | ControlFlowNode for SOURCE | test.py:553:10:553:10 | ControlFlowNode for a | Flow found | -| test.py:561:10:561:10 | ControlFlowNode for a | test.py:559:10:559:15 | ControlFlowNode for SOURCE | test.py:561:10:561:10 | ControlFlowNode for a | Flow found | -| test.py:563:10:563:13 | ControlFlowNode for Subscript | test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:563:10:563:13 | ControlFlowNode for Subscript | Flow found | -| test.py:564:12:564:12 | ControlFlowNode for c | test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:564:12:564:12 | ControlFlowNode for c | Flow found | -| test.py:571:10:571:10 | ControlFlowNode for a | test.py:569:10:569:15 | ControlFlowNode for SOURCE | test.py:571:10:571:10 | ControlFlowNode for a | Flow found | -| test.py:573:10:573:10 | ControlFlowNode for c | test.py:569:18:569:23 | ControlFlowNode for SOURCE | test.py:573:10:573:10 | ControlFlowNode for c | Flow found | -| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | -| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | -| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | -| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | -| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | -| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | -| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | -| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | -| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | -| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found | -| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found | -| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found | -| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found | -| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found | -| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found | -| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found | -| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found | -| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found | -| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found | -| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found | -| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found | -| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found | -| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found | -| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found | -| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found | -| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found | -| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found | -| test.py:610:10:610:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:610:10:610:11 | ControlFlowNode for a1 | Flow found | -| test.py:612:12:612:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:612:12:612:16 | ControlFlowNode for Subscript | Flow found | -| test.py:613:10:613:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:613:10:613:14 | ControlFlowNode for Subscript | Flow found | -| test.py:619:10:619:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:619:10:619:11 | ControlFlowNode for a1 | Flow found | -| test.py:621:12:621:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:621:12:621:16 | ControlFlowNode for Subscript | Flow found | -| test.py:622:10:622:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:622:10:622:14 | ControlFlowNode for Subscript | Flow found | -| test.py:628:10:628:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:628:10:628:11 | ControlFlowNode for a1 | Flow found | -| test.py:630:12:630:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:630:12:630:16 | ControlFlowNode for Subscript | Flow found | -| test.py:631:10:631:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:631:10:631:14 | ControlFlowNode for Subscript | Flow found | -| test.py:637:10:637:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:637:10:637:11 | ControlFlowNode for a1 | Flow found | -| test.py:639:12:639:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:639:12:639:16 | ControlFlowNode for Subscript | Flow found | -| test.py:640:10:640:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:640:10:640:14 | ControlFlowNode for Subscript | Flow found | -| test.py:648:10:648:10 | ControlFlowNode for a | test.py:647:19:647:24 | ControlFlowNode for SOURCE | test.py:648:10:648:10 | ControlFlowNode for a | Flow found | -| test.py:657:14:657:14 | ControlFlowNode for x | test.py:655:12:655:17 | ControlFlowNode for SOURCE | test.py:657:14:657:14 | ControlFlowNode for x | Flow found | -| test.py:657:14:657:14 | ControlFlowNode for x | test.py:655:33:655:38 | ControlFlowNode for SOURCE | test.py:657:14:657:14 | ControlFlowNode for x | Flow found | -| test.py:666:14:666:17 | ControlFlowNode for Subscript | test.py:663:12:663:17 | ControlFlowNode for SOURCE | test.py:666:14:666:17 | ControlFlowNode for Subscript | Flow found | -| test.py:666:14:666:17 | ControlFlowNode for Subscript | test.py:663:33:663:38 | ControlFlowNode for SOURCE | test.py:666:14:666:17 | ControlFlowNode for Subscript | Flow found | -| test.py:667:16:667:16 | ControlFlowNode for y | test.py:663:12:663:17 | ControlFlowNode for SOURCE | test.py:667:16:667:16 | ControlFlowNode for y | Flow found | -| test.py:667:16:667:16 | ControlFlowNode for y | test.py:663:33:663:38 | ControlFlowNode for SOURCE | test.py:667:16:667:16 | ControlFlowNode for y | Flow found | -| test.py:674:14:674:14 | ControlFlowNode for x | test.py:672:12:672:17 | ControlFlowNode for SOURCE | test.py:674:14:674:14 | ControlFlowNode for x | Flow found | -| test.py:674:14:674:14 | ControlFlowNode for x | test.py:672:33:672:38 | ControlFlowNode for SOURCE | test.py:674:14:674:14 | ControlFlowNode for x | Flow found | -| test.py:680:10:680:12 | ControlFlowNode for arg | test.py:685:7:685:12 | ControlFlowNode for SOURCE | test.py:680:10:680:12 | ControlFlowNode for arg | Flow found | -| test.py:680:10:680:12 | ControlFlowNode for arg | test.py:686:43:686:48 | ControlFlowNode for SOURCE | test.py:680:10:680:12 | ControlFlowNode for arg | Flow found | -| test.py:760:10:760:36 | ControlFlowNode for return_from_inner_scope() | test.py:757:16:757:21 | ControlFlowNode for SOURCE | test.py:760:10:760:36 | ControlFlowNode for return_from_inner_scope() | Flow found | -| test.py:796:10:796:10 | ControlFlowNode for x | test.py:795:37:795:42 | ControlFlowNode for SOURCE | test.py:796:10:796:10 | ControlFlowNode for x | Flow found | -| test.py:797:10:797:10 | ControlFlowNode for y | test.py:795:50:795:55 | ControlFlowNode for SOURCE | test.py:797:10:797:10 | ControlFlowNode for y | Flow found | -| test.py:798:10:798:10 | ControlFlowNode for z | test.py:795:63:795:68 | ControlFlowNode for SOURCE | test.py:798:10:798:10 | ControlFlowNode for z | Flow found | +| test.py:429:10:429:20 | ControlFlowNode for BoolExpr | test.py:429:15:429:20 | ControlFlowNode for SOURCE | test.py:429:10:429:20 | ControlFlowNode for BoolExpr | Flow found | +| test.py:434:10:434:21 | ControlFlowNode for BoolExpr | test.py:434:16:434:21 | ControlFlowNode for SOURCE | test.py:434:10:434:21 | ControlFlowNode for BoolExpr | Flow found | +| test.py:445:10:445:38 | ControlFlowNode for IfExp | test.py:445:10:445:15 | ControlFlowNode for SOURCE | test.py:445:10:445:38 | ControlFlowNode for IfExp | Flow found | +| test.py:453:10:453:39 | ControlFlowNode for IfExp | test.py:453:34:453:39 | ControlFlowNode for SOURCE | test.py:453:10:453:39 | ControlFlowNode for IfExp | Flow found | +| test.py:477:10:477:18 | ControlFlowNode for f() | test.py:477:12:477:17 | ControlFlowNode for SOURCE | test.py:477:10:477:18 | ControlFlowNode for f() | Flow found | +| test.py:484:10:484:34 | ControlFlowNode for second() | test.py:484:28:484:33 | ControlFlowNode for SOURCE | test.py:484:10:484:34 | ControlFlowNode for second() | Flow found | +| test.py:498:10:498:36 | ControlFlowNode for second() | test.py:498:30:498:35 | ControlFlowNode for SOURCE | test.py:498:10:498:36 | ControlFlowNode for second() | Flow found | +| test.py:512:10:512:43 | ControlFlowNode for second() | test.py:512:36:512:41 | ControlFlowNode for SOURCE | test.py:512:10:512:43 | ControlFlowNode for second() | Flow found | +| test.py:517:10:517:39 | ControlFlowNode for f_extra_pos() | test.py:517:33:517:38 | ControlFlowNode for SOURCE | test.py:517:10:517:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:522:10:522:45 | ControlFlowNode for f_extra_keyword() | test.py:522:39:522:44 | ControlFlowNode for SOURCE | test.py:522:10:522:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:536:10:536:10 | ControlFlowNode for a | test.py:534:9:534:14 | ControlFlowNode for SOURCE | test.py:536:10:536:10 | ControlFlowNode for a | Flow found | +| test.py:541:10:541:10 | ControlFlowNode for b | test.py:534:9:534:14 | ControlFlowNode for SOURCE | test.py:541:10:541:10 | ControlFlowNode for b | Flow found | +| test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | +| test.py:556:10:556:10 | ControlFlowNode for a | test.py:554:10:554:15 | ControlFlowNode for SOURCE | test.py:556:10:556:10 | ControlFlowNode for a | Flow found | +| test.py:558:10:558:10 | ControlFlowNode for c | test.py:554:30:554:35 | ControlFlowNode for SOURCE | test.py:558:10:558:10 | ControlFlowNode for c | Flow found | +| test.py:565:10:565:10 | ControlFlowNode for a | test.py:563:13:563:18 | ControlFlowNode for SOURCE | test.py:565:10:565:10 | ControlFlowNode for a | Flow found | +| test.py:573:10:573:10 | ControlFlowNode for a | test.py:571:10:571:15 | ControlFlowNode for SOURCE | test.py:573:10:573:10 | ControlFlowNode for a | Flow found | +| test.py:575:10:575:13 | ControlFlowNode for Subscript | test.py:571:18:571:23 | ControlFlowNode for SOURCE | test.py:575:10:575:13 | ControlFlowNode for Subscript | Flow found | +| test.py:576:12:576:12 | ControlFlowNode for c | test.py:571:18:571:23 | ControlFlowNode for SOURCE | test.py:576:12:576:12 | ControlFlowNode for c | Flow found | +| test.py:583:10:583:10 | ControlFlowNode for a | test.py:581:10:581:15 | ControlFlowNode for SOURCE | test.py:583:10:583:10 | ControlFlowNode for a | Flow found | +| test.py:585:10:585:10 | ControlFlowNode for c | test.py:581:18:581:23 | ControlFlowNode for SOURCE | test.py:585:10:585:10 | ControlFlowNode for c | Flow found | +| test.py:594:10:594:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:594:10:594:11 | ControlFlowNode for a1 | Flow found | +| test.py:594:10:594:11 | ControlFlowNode for a1 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:594:10:594:11 | ControlFlowNode for a1 | Flow found | +| test.py:594:10:594:11 | ControlFlowNode for a1 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:594:10:594:11 | ControlFlowNode for a1 | Flow found | +| test.py:595:12:595:13 | ControlFlowNode for a2 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:595:12:595:13 | ControlFlowNode for a2 | Flow found | +| test.py:595:12:595:13 | ControlFlowNode for a2 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:595:12:595:13 | ControlFlowNode for a2 | Flow found | +| test.py:595:12:595:13 | ControlFlowNode for a2 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:595:12:595:13 | ControlFlowNode for a2 | Flow found | +| test.py:596:10:596:11 | ControlFlowNode for a3 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:596:10:596:11 | ControlFlowNode for a3 | Flow found | +| test.py:596:10:596:11 | ControlFlowNode for a3 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:596:10:596:11 | ControlFlowNode for a3 | Flow found | +| test.py:596:10:596:11 | ControlFlowNode for a3 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:596:10:596:11 | ControlFlowNode for a3 | Flow found | +| test.py:602:10:602:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:602:10:602:11 | ControlFlowNode for a1 | Flow found | +| test.py:602:10:602:11 | ControlFlowNode for a1 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:602:10:602:11 | ControlFlowNode for a1 | Flow found | +| test.py:602:10:602:11 | ControlFlowNode for a1 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:602:10:602:11 | ControlFlowNode for a1 | Flow found | +| test.py:603:12:603:13 | ControlFlowNode for a2 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:603:12:603:13 | ControlFlowNode for a2 | Flow found | +| test.py:603:12:603:13 | ControlFlowNode for a2 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:603:12:603:13 | ControlFlowNode for a2 | Flow found | +| test.py:603:12:603:13 | ControlFlowNode for a2 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:603:12:603:13 | ControlFlowNode for a2 | Flow found | +| test.py:604:10:604:11 | ControlFlowNode for a3 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:604:10:604:11 | ControlFlowNode for a3 | Flow found | +| test.py:604:10:604:11 | ControlFlowNode for a3 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:604:10:604:11 | ControlFlowNode for a3 | Flow found | +| test.py:604:10:604:11 | ControlFlowNode for a3 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:604:10:604:11 | ControlFlowNode for a3 | Flow found | +| test.py:610:10:610:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:610:10:610:11 | ControlFlowNode for a1 | Flow found | +| test.py:610:10:610:11 | ControlFlowNode for a1 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:610:10:610:11 | ControlFlowNode for a1 | Flow found | +| test.py:610:10:610:11 | ControlFlowNode for a1 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:610:10:610:11 | ControlFlowNode for a1 | Flow found | +| test.py:611:12:611:13 | ControlFlowNode for a2 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:611:12:611:13 | ControlFlowNode for a2 | Flow found | +| test.py:611:12:611:13 | ControlFlowNode for a2 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:611:12:611:13 | ControlFlowNode for a2 | Flow found | +| test.py:611:12:611:13 | ControlFlowNode for a2 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:611:12:611:13 | ControlFlowNode for a2 | Flow found | +| test.py:612:10:612:11 | ControlFlowNode for a3 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:612:10:612:11 | ControlFlowNode for a3 | Flow found | +| test.py:612:10:612:11 | ControlFlowNode for a3 | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:612:10:612:11 | ControlFlowNode for a3 | Flow found | +| test.py:612:10:612:11 | ControlFlowNode for a3 | test.py:590:41:590:46 | ControlFlowNode for SOURCE | test.py:612:10:612:11 | ControlFlowNode for a3 | Flow found | +| test.py:622:10:622:11 | ControlFlowNode for a1 | test.py:618:12:618:17 | ControlFlowNode for SOURCE | test.py:622:10:622:11 | ControlFlowNode for a1 | Flow found | +| test.py:624:12:624:16 | ControlFlowNode for Subscript | test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:624:12:624:16 | ControlFlowNode for Subscript | Flow found | +| test.py:625:10:625:14 | ControlFlowNode for Subscript | test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:625:10:625:14 | ControlFlowNode for Subscript | Flow found | +| test.py:631:10:631:11 | ControlFlowNode for a1 | test.py:618:12:618:17 | ControlFlowNode for SOURCE | test.py:631:10:631:11 | ControlFlowNode for a1 | Flow found | +| test.py:633:12:633:16 | ControlFlowNode for Subscript | test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:633:12:633:16 | ControlFlowNode for Subscript | Flow found | +| test.py:634:10:634:14 | ControlFlowNode for Subscript | test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:634:10:634:14 | ControlFlowNode for Subscript | Flow found | +| test.py:640:10:640:11 | ControlFlowNode for a1 | test.py:618:12:618:17 | ControlFlowNode for SOURCE | test.py:640:10:640:11 | ControlFlowNode for a1 | Flow found | +| test.py:642:12:642:16 | ControlFlowNode for Subscript | test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:642:12:642:16 | ControlFlowNode for Subscript | Flow found | +| test.py:643:10:643:14 | ControlFlowNode for Subscript | test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:643:10:643:14 | ControlFlowNode for Subscript | Flow found | +| test.py:649:10:649:11 | ControlFlowNode for a1 | test.py:618:12:618:17 | ControlFlowNode for SOURCE | test.py:649:10:649:11 | ControlFlowNode for a1 | Flow found | +| test.py:651:12:651:16 | ControlFlowNode for Subscript | test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:651:12:651:16 | ControlFlowNode for Subscript | Flow found | +| test.py:652:10:652:14 | ControlFlowNode for Subscript | test.py:618:31:618:36 | ControlFlowNode for SOURCE | test.py:652:10:652:14 | ControlFlowNode for Subscript | Flow found | +| test.py:660:10:660:10 | ControlFlowNode for a | test.py:659:19:659:24 | ControlFlowNode for SOURCE | test.py:660:10:660:10 | ControlFlowNode for a | Flow found | +| test.py:669:14:669:14 | ControlFlowNode for x | test.py:667:12:667:17 | ControlFlowNode for SOURCE | test.py:669:14:669:14 | ControlFlowNode for x | Flow found | +| test.py:669:14:669:14 | ControlFlowNode for x | test.py:667:33:667:38 | ControlFlowNode for SOURCE | test.py:669:14:669:14 | ControlFlowNode for x | Flow found | +| test.py:678:14:678:17 | ControlFlowNode for Subscript | test.py:675:12:675:17 | ControlFlowNode for SOURCE | test.py:678:14:678:17 | ControlFlowNode for Subscript | Flow found | +| test.py:678:14:678:17 | ControlFlowNode for Subscript | test.py:675:33:675:38 | ControlFlowNode for SOURCE | test.py:678:14:678:17 | ControlFlowNode for Subscript | Flow found | +| test.py:679:16:679:16 | ControlFlowNode for y | test.py:675:12:675:17 | ControlFlowNode for SOURCE | test.py:679:16:679:16 | ControlFlowNode for y | Flow found | +| test.py:679:16:679:16 | ControlFlowNode for y | test.py:675:33:675:38 | ControlFlowNode for SOURCE | test.py:679:16:679:16 | ControlFlowNode for y | Flow found | +| test.py:686:14:686:14 | ControlFlowNode for x | test.py:684:12:684:17 | ControlFlowNode for SOURCE | test.py:686:14:686:14 | ControlFlowNode for x | Flow found | +| test.py:686:14:686:14 | ControlFlowNode for x | test.py:684:33:684:38 | ControlFlowNode for SOURCE | test.py:686:14:686:14 | ControlFlowNode for x | Flow found | +| test.py:692:10:692:12 | ControlFlowNode for arg | test.py:697:7:697:12 | ControlFlowNode for SOURCE | test.py:692:10:692:12 | ControlFlowNode for arg | Flow found | +| test.py:692:10:692:12 | ControlFlowNode for arg | test.py:698:43:698:48 | ControlFlowNode for SOURCE | test.py:692:10:692:12 | ControlFlowNode for arg | Flow found | +| test.py:772:10:772:36 | ControlFlowNode for return_from_inner_scope() | test.py:769:16:769:21 | ControlFlowNode for SOURCE | test.py:772:10:772:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:808:10:808:10 | ControlFlowNode for x | test.py:807:37:807:42 | ControlFlowNode for SOURCE | test.py:808:10:808:10 | ControlFlowNode for x | Flow found | +| test.py:809:10:809:10 | ControlFlowNode for y | test.py:807:50:807:55 | ControlFlowNode for SOURCE | test.py:809:10:809:10 | ControlFlowNode for y | Flow found | +| test.py:810:10:810:10 | ControlFlowNode for z | test.py:807:63:807:68 | ControlFlowNode for SOURCE | test.py:810:10:810:10 | ControlFlowNode for z | Flow found | diff --git a/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected b/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected index e288b7fd157..5968fdc596b 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/allLocalFlow.expected @@ -72,9 +72,14 @@ | test.py:6:15:6:15 | ControlFlowNode for x | test.py:6:15:6:15 | SSA variable x | | test.py:6:15:6:15 | SSA variable x | test.py:7:12:7:12 | ControlFlowNode for x | | test.py:7:12:7:12 | ControlFlowNode for x | test.py:7:29:7:29 | ControlFlowNode for x | +| test.py:7:12:7:24 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | | test.py:7:29:7:29 | ControlFlowNode for x | test.py:7:47:7:47 | ControlFlowNode for x | +| test.py:7:29:7:42 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | | test.py:7:47:7:47 | ControlFlowNode for x | test.py:7:58:7:58 | ControlFlowNode for x | +| test.py:7:47:7:53 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | | test.py:7:58:7:58 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | +| test.py:7:58:7:66 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | +| test.py:7:71:7:78 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | | test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | | test.py:10:1:10:12 | GSSA Variable is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | | test.py:10:10:10:10 | ControlFlowNode for x | test.py:10:10:10:10 | SSA variable x | diff --git a/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected b/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected index 1dde97a8d04..f8e4167e49a 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/globalStep.expected @@ -602,6 +602,8 @@ | test.py:7:12:7:12 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:12:7:12 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:12:7:12 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | +| test.py:7:12:7:24 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | +| test.py:7:12:7:24 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | test.py:11:8:11:19 | ControlFlowNode for is_source() | | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | test.py:11:8:11:19 | ControlFlowNode for is_source() | | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | test.py:18:8:18:19 | ControlFlowNode for is_source() | @@ -618,6 +620,8 @@ | test.py:7:29:7:29 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:29:7:29 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:29:7:29 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | +| test.py:7:29:7:42 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | +| test.py:7:29:7:42 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | | test.py:7:47:7:47 | ControlFlowNode for x | test.py:7:58:7:58 | ControlFlowNode for x | | test.py:7:47:7:47 | ControlFlowNode for x | test.py:7:58:7:58 | ControlFlowNode for x | | test.py:7:47:7:47 | ControlFlowNode for x | test.py:7:58:7:58 | ControlFlowNode for x | @@ -626,10 +630,16 @@ | test.py:7:47:7:47 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:47:7:47 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:47:7:47 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | +| test.py:7:47:7:53 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | +| test.py:7:47:7:53 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | | test.py:7:58:7:58 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:58:7:58 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:58:7:58 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | | test.py:7:58:7:58 | ControlFlowNode for x | test.py:7:71:7:71 | ControlFlowNode for x | +| test.py:7:58:7:66 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | +| test.py:7:58:7:66 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | +| test.py:7:71:7:78 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | +| test.py:7:71:7:78 | ControlFlowNode for Compare | test.py:7:12:7:78 | ControlFlowNode for BoolExpr | | test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | | test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK | | test.py:10:1:10:12 | GSSA Variable is_source | test.py:11:8:11:16 | ControlFlowNode for is_source | From 29ddc76e2fda9706ff8e92e31d27a12d29995e8a Mon Sep 17 00:00:00 2001 From: haby0 <Ha_yub@163.com> Date: Mon, 11 Oct 2021 16:43:30 +0800 Subject: [PATCH 214/361] Update python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected Co-authored-by: yoff <lerchedahl@gmail.com> --- .../query-tests/Security/CWE-117/LogInjection.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected index 14774193ce5..e27b369e640 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected @@ -20,6 +20,7 @@ nodes | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | LogInjectionBad.py:35:12:35:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +subpaths #select | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | $@ flows to log entry. | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | User-provided value | | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | $@ flows to log entry. | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | User-provided value | From c2d0fcfbe6f6e4a9e69ebdf78f768cdf4939ea61 Mon Sep 17 00:00:00 2001 From: haby0 <Ha_yub@163.com> Date: Mon, 11 Oct 2021 16:46:02 +0800 Subject: [PATCH 215/361] Update python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected Co-authored-by: yoff <lerchedahl@gmail.com> --- .../CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected index 38536f2b7a2..a432cf5053f 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected @@ -9,6 +9,7 @@ nodes | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip | +subpaths #select | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | this user input | | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | this user input | From 61973c399efa670bf0cbb1816d24c49f467c83a0 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 8 Oct 2021 13:21:21 +0200 Subject: [PATCH 216/361] C#: Make `GetCSharpArgsLogs` robust against log directory not existing --- .../Extractor/Extractor.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs index d01a3f37ac8..3140815d323 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs @@ -492,8 +492,18 @@ namespace Semmle.Extraction.CSharp /// <summary> /// Gets a list of all `csharp.{hash}.txt` files currently written to the log directory. /// </summary> - public static IEnumerable<string> GetCSharpArgsLogs() => - Directory.EnumerateFiles(GetCSharpLogDirectory(), "csharp.*.txt"); + public static IEnumerable<string> GetCSharpArgsLogs() + { + try + { + return Directory.EnumerateFiles(GetCSharpLogDirectory(), "csharp.*.txt"); + } + catch (DirectoryNotFoundException) + { + // If the directory does not exist, there are no log files + return Enumerable.Empty<string>(); + } + } private static string GetCSharpLogDirectory() { From 30bf2aade4f10fc5e852856a9d67c93a11f414af Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 8 Oct 2021 16:04:02 +0200 Subject: [PATCH 217/361] C#: Add test for missing summary flow --- .../dataflow/external-models/ExternalFlow.cs | 16 +++++++++++++++ .../external-models/ExternalFlow.expected | 20 +++++++++---------- .../dataflow/external-models/ExternalFlow.ql | 2 ++ 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs index 3b8a9ba7c7f..6fd40ec90b6 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs @@ -92,6 +92,19 @@ namespace My.Qltest Sink(i); } + void M15() + { + var d1 = new D(); + d1.Field = new object(); + var d2 = new D(); + Apply2(d => + { + Sink(d); // MISSING FLOW + }, d1, d2); + Sink(d1.Field); // MISSING FLOW + Sink(d2.Field2); + } + object StepArgRes(object x) { return null; } void StepArgArg(object @in, object @out) { } @@ -103,6 +116,7 @@ namespace My.Qltest void StepQualArg(object @out) { } object Field; + object Field2; object StepFieldGetter() => throw null; @@ -122,6 +136,8 @@ namespace My.Qltest static S[] Map<S, T>(S[] elements, Func<S, T> f) => throw null; + static void Apply2<S>(Action<S> f, S s1, S s2) => throw null; + static void Parse(string s, out int i) => throw null; static void Sink(object o) { } diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected index ecc6b95c817..10cd840a286 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected @@ -24,12 +24,12 @@ edges | ExternalFlow.cs:54:36:54:47 | object creation of type Object : Object | ExternalFlow.cs:54:13:54:16 | [post] this access [element] : Object | | ExternalFlow.cs:55:18:55:21 | this access [element] : Object | ExternalFlow.cs:55:18:55:41 | call to method StepElementGetter | | ExternalFlow.cs:60:35:60:35 | o : Object | ExternalFlow.cs:60:47:60:47 | access to parameter o | -| ExternalFlow.cs:60:64:60:75 | object creation of type Object : Object | ExternalFlow.cs:121:46:121:46 | s : Object | +| ExternalFlow.cs:60:64:60:75 | object creation of type Object : Object | ExternalFlow.cs:135:46:135:46 | s : Object | | ExternalFlow.cs:65:21:65:60 | call to method Apply<Int32,Object> : Object | ExternalFlow.cs:66:18:66:18 | access to local variable o | | ExternalFlow.cs:65:45:65:56 | object creation of type Object : Object | ExternalFlow.cs:65:21:65:60 | call to method Apply<Int32,Object> : Object | | ExternalFlow.cs:71:30:71:45 | { ..., ... } [element] : Object | ExternalFlow.cs:72:17:72:20 | access to local variable objs [element] : Object | | ExternalFlow.cs:71:32:71:43 | object creation of type Object : Object | ExternalFlow.cs:71:30:71:45 | { ..., ... } [element] : Object | -| ExternalFlow.cs:72:17:72:20 | access to local variable objs [element] : Object | ExternalFlow.cs:123:34:123:41 | elements [element] : Object | +| ExternalFlow.cs:72:17:72:20 | access to local variable objs [element] : Object | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | | ExternalFlow.cs:72:23:72:23 | o : Object | ExternalFlow.cs:72:35:72:35 | access to parameter o | | ExternalFlow.cs:77:24:77:58 | call to method Map<Int32,Object> [element] : Object | ExternalFlow.cs:78:18:78:21 | access to local variable objs [element] : Object | | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | ExternalFlow.cs:77:24:77:58 | call to method Map<Int32,Object> [element] : Object | @@ -43,11 +43,11 @@ edges | ExternalFlow.cs:90:21:90:34 | object creation of type String : String | ExternalFlow.cs:91:19:91:19 | access to local variable s : String | | ExternalFlow.cs:91:19:91:19 | access to local variable s : String | ExternalFlow.cs:91:30:91:30 | SSA def(i) : Int32 | | ExternalFlow.cs:91:30:91:30 | SSA def(i) : Int32 | ExternalFlow.cs:92:18:92:18 | (...) ... | -| ExternalFlow.cs:121:46:121:46 | s : Object | ExternalFlow.cs:60:35:60:35 | o : Object | -| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | ExternalFlow.cs:72:23:72:23 | o : Object | -| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | ExternalFlow.cs:72:23:72:23 | o : Object | -| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | ExternalFlow.cs:123:34:123:41 | elements [element] : Object | -| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | ExternalFlow.cs:123:34:123:41 | elements [element] : Object | +| ExternalFlow.cs:135:46:135:46 | s : Object | ExternalFlow.cs:60:35:60:35 | o : Object | +| ExternalFlow.cs:137:34:137:41 | elements [element] : Object | ExternalFlow.cs:72:23:72:23 | o : Object | +| ExternalFlow.cs:137:34:137:41 | elements [element] : Object | ExternalFlow.cs:72:23:72:23 | o : Object | +| ExternalFlow.cs:137:34:137:41 | elements [element] : Object | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | +| ExternalFlow.cs:137:34:137:41 | elements [element] : Object | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | nodes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | semmle.label | call to method StepArgRes | @@ -107,9 +107,9 @@ nodes | ExternalFlow.cs:91:19:91:19 | access to local variable s : String | semmle.label | access to local variable s : String | | ExternalFlow.cs:91:30:91:30 | SSA def(i) : Int32 | semmle.label | SSA def(i) : Int32 | | ExternalFlow.cs:92:18:92:18 | (...) ... | semmle.label | (...) ... | -| ExternalFlow.cs:121:46:121:46 | s : Object | semmle.label | s : Object | -| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | semmle.label | elements [element] : Object | -| ExternalFlow.cs:123:34:123:41 | elements [element] : Object | semmle.label | elements [element] : Object | +| ExternalFlow.cs:135:46:135:46 | s : Object | semmle.label | s : Object | +| ExternalFlow.cs:137:34:137:41 | elements [element] : Object | semmle.label | elements [element] : Object | +| ExternalFlow.cs:137:34:137:41 | elements [element] : Object | semmle.label | elements [element] : Object | subpaths invalidModelRow #select diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ql b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ql index d22956a1b0e..f164967c770 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ql +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ql @@ -23,6 +23,8 @@ class SummaryModelTest extends SummaryModelCsv { "My.Qltest;D;false;StepElementSetter;(System.Object);;Argument[0];Element of Argument[-1];value", "My.Qltest;D;false;Apply<,>;(System.Func<S,T>,S);;Argument[1];Parameter[0] of Argument[0];value", "My.Qltest;D;false;Apply<,>;(System.Func<S,T>,S);;ReturnValue of Argument[0];ReturnValue;value", + "My.Qltest;D;false;Apply2<>;(System.Action<S>,S,S);;Field[My.Qltest.D.Field] of Argument[1];Parameter[0] of Argument[0];value", + "My.Qltest;D;false;Apply2<>;(System.Action<S>,S,S);;Field[My.Qltest.D.Field2] of Argument[2];Parameter[0] of Argument[0];value", "My.Qltest;D;false;Map<,>;(S[],System.Func<S,T>);;Element of Argument[0];Parameter[0] of Argument[1];value", "My.Qltest;D;false;Map<,>;(S[],System.Func<S,T>);;ReturnValue of Argument[1];Element of ReturnValue;value", "My.Qltest;D;false;Parse;(System.String,System.Int32);;Argument[0];Argument[1];taint" From d5955f1ae1ee2d47bc9a93ae7ee34a6ae4448eb4 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 8 Oct 2021 16:05:06 +0200 Subject: [PATCH 218/361] Java: Add test for missing summary flow --- .../dataflow/callback-dispatch/A.java | 21 +++++++++++++++++++ .../dataflow/callback-dispatch/test.ql | 2 ++ 2 files changed, 23 insertions(+) diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java index 6224a2e3d95..d9d5ddc9d67 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java @@ -169,4 +169,25 @@ public class A { sink(res2); // $ flow=19 } + static void applyConsumer1Field1Field2(A a1, A a2, Consumer1 con) { + // summary: + // con.eat(a1.field1); + // con.eat(a2.field2); + } + + static void wrapSinkToAvoidFieldSsa(A a) { sink(a.field1); } + + void foo3() { + A a1 = new A(); + a1.field1 = source(1); + A a2 = new A(); + applyConsumer1Field1Field2(a1, a2, p -> { + sink(p); // MISSING FLOW + }); + wrapSinkToAvoidFieldSsa(a1); // MISSING FLOW + sink(a2.field2); + } + + public Object field1; + public Object field2; } diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/test.ql b/java/ql/test/library-tests/dataflow/callback-dispatch/test.ql index 63eeee53823..ba9512cf38d 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/test.ql +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/test.ql @@ -8,6 +8,8 @@ class SummaryModelTest extends SummaryModelCsv { row = [ "my.callback.qltest;A;false;applyConsumer1;(Object,Consumer1);;Argument[0];Parameter[0] of Argument[1];value", + "my.callback.qltest;A;false;applyConsumer1Field1Field2;(A,A,Consumer1);;Field[my.callback.qltest.A.field1] of Argument[0];Parameter[0] of Argument[2];value", + "my.callback.qltest;A;false;applyConsumer1Field1Field2;(A,A,Consumer1);;Field[my.callback.qltest.A.field2] of Argument[1];Parameter[0] of Argument[2];value", "my.callback.qltest;A;false;applyConsumer2;(Object,Consumer2);;Argument[0];Parameter[0] of Argument[1];value", "my.callback.qltest;A;false;applyConsumer3;(Object,Consumer3);;Argument[0];Parameter[0] of Argument[1];value", "my.callback.qltest;A;false;applyConsumer3_ret_postup;(Consumer3);;Parameter[0] of Argument[0];ReturnValue;value", From 68ea3e7b49217219f6d35000fcbd5a3f1549e3c2 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 8 Oct 2021 16:07:35 +0200 Subject: [PATCH 219/361] Data flow: Add debugging predicates for rendering data flow graphs for summarized callables --- .../dataflow/internal/DataFlowDispatch.qll | 13 +++ .../dataflow/internal/FlowSummaryImpl.qll | 92 +++++++++++++++++++ .../dataflow/internal/DataFlowPrivate.qll | 13 +++ .../dataflow/internal/FlowSummaryImpl.qll | 92 +++++++++++++++++++ 4 files changed, 210 insertions(+) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll index d38975f24bb..0182040fd11 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll @@ -262,6 +262,19 @@ abstract class DataFlowCall extends TDataFlowCall { /** Gets the location of this call. */ abstract Location getLocation(); + + /** + * 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 + ) { + this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** A non-delegate C# call relevant for data flow. */ diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 8bca0699e04..5c65570c5a6 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -870,4 +870,96 @@ module Private { ) } } + + /** + * Provides query predicates for rendering the generated data flow graph for + * a summarized callable. + * + * Import this module into a `.ql` file of `@kind graph` to render the graph. + * The graph is restricted to callables from `RelevantSummarizedCallable`. + */ + module RenderSummarizedCallable { + /** A summarized callable to include in the graph. */ + abstract class RelevantSummarizedCallable extends SummarizedCallable { } + + private newtype TNodeOrCall = + MkNode(Node n) { + exists(RelevantSummarizedCallable c | + n = summaryNode(c, _) + or + n.(ParamNode).isParameterOf(c, _) + ) + } or + MkCall(DataFlowCall call) { + call = summaryDataFlowCall(_) and + call.getEnclosingCallable() instanceof RelevantSummarizedCallable + } + + private class NodeOrCall extends TNodeOrCall { + Node asNode() { this = MkNode(result) } + + DataFlowCall asCall() { this = MkCall(result) } + + string toString() { + result = this.asNode().toString() + or + result = this.asCall().toString() + } + + /** + * 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/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + or + this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + query predicate nodes(NodeOrCall n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + private predicate edgesComponent(NodeOrCall a, NodeOrCall b, string value) { + exists(boolean preservesValue | + Private::Steps::summaryLocalStep(a.asNode(), b.asNode(), preservesValue) and + if preservesValue = true then value = "value" else value = "taint" + ) + or + exists(Content c | + Private::Steps::summaryReadStep(a.asNode(), c, b.asNode()) and + value = "read (" + c + ")" + or + Private::Steps::summaryStoreStep(a.asNode(), c, b.asNode()) and + value = "store (" + c + ")" + or + Private::Steps::summaryClearsContent(a.asNode(), c) and + b = a and + value = "clear (" + c + ")" + ) + or + summaryPostUpdateNode(b.asNode(), a.asNode()) and + value = "post-update" + or + b.asCall() = summaryDataFlowCall(a.asNode()) and + value = "receiver" + or + exists(int i | + summaryArgumentNode(b.asCall(), a.asNode(), i) and + value = "argument (" + i + ")" + ) + } + + query predicate edges(NodeOrCall a, NodeOrCall b, string key, string value) { + key = "semmle.label" and + edgesComponent(a, b, _) and + value = strictconcat(string s | edgesComponent(a, b, s) | s, " / ") + } + } } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 94b3cb6614e..d35610ecf4a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -234,6 +234,19 @@ class DataFlowCall extends TDataFlowCall { /** Gets the location of this call. */ abstract Location getLocation(); + + /** + * 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 + ) { + this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** A source call, that is, a `Call`. */ diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 8bca0699e04..5c65570c5a6 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -870,4 +870,96 @@ module Private { ) } } + + /** + * Provides query predicates for rendering the generated data flow graph for + * a summarized callable. + * + * Import this module into a `.ql` file of `@kind graph` to render the graph. + * The graph is restricted to callables from `RelevantSummarizedCallable`. + */ + module RenderSummarizedCallable { + /** A summarized callable to include in the graph. */ + abstract class RelevantSummarizedCallable extends SummarizedCallable { } + + private newtype TNodeOrCall = + MkNode(Node n) { + exists(RelevantSummarizedCallable c | + n = summaryNode(c, _) + or + n.(ParamNode).isParameterOf(c, _) + ) + } or + MkCall(DataFlowCall call) { + call = summaryDataFlowCall(_) and + call.getEnclosingCallable() instanceof RelevantSummarizedCallable + } + + private class NodeOrCall extends TNodeOrCall { + Node asNode() { this = MkNode(result) } + + DataFlowCall asCall() { this = MkCall(result) } + + string toString() { + result = this.asNode().toString() + or + result = this.asCall().toString() + } + + /** + * 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/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + or + this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + query predicate nodes(NodeOrCall n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + private predicate edgesComponent(NodeOrCall a, NodeOrCall b, string value) { + exists(boolean preservesValue | + Private::Steps::summaryLocalStep(a.asNode(), b.asNode(), preservesValue) and + if preservesValue = true then value = "value" else value = "taint" + ) + or + exists(Content c | + Private::Steps::summaryReadStep(a.asNode(), c, b.asNode()) and + value = "read (" + c + ")" + or + Private::Steps::summaryStoreStep(a.asNode(), c, b.asNode()) and + value = "store (" + c + ")" + or + Private::Steps::summaryClearsContent(a.asNode(), c) and + b = a and + value = "clear (" + c + ")" + ) + or + summaryPostUpdateNode(b.asNode(), a.asNode()) and + value = "post-update" + or + b.asCall() = summaryDataFlowCall(a.asNode()) and + value = "receiver" + or + exists(int i | + summaryArgumentNode(b.asCall(), a.asNode(), i) and + value = "argument (" + i + ")" + ) + } + + query predicate edges(NodeOrCall a, NodeOrCall b, string key, string value) { + key = "semmle.label" and + edgesComponent(a, b, _) and + value = strictconcat(string s | edgesComponent(a, b, s) | s, " / ") + } + } } From 5aee7159317fcf09be8b3f52b827eccae26dfef0 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Mon, 11 Oct 2021 13:00:21 +0200 Subject: [PATCH 220/361] Apply suggestions from code review Co-authored-by: Taus <tausbn@github.com> --- .../lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 1 + .../experimental/dataflow/module-initialization/multiphase.py | 2 +- 2 files changed, 2 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 4191b926654..eef2f30085e 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -275,6 +275,7 @@ predicate runtimeJumpStep(Node nodeFrom, Node nodeTo) { // Module variable write nodeFrom = nodeTo.(ModuleVariableNode).getAWrite() or + // Setting the possible values of the variable at the end of import time exists(SsaVariable def | def = any(SsaVariable var).getAnUltimateDefinition() and def.getDefinition() = nodeFrom.asCfgNode() and diff --git a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py index 6e6df47dcc4..f2106de4006 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py +++ b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py @@ -24,7 +24,7 @@ def SINK_F(x): if is_source(x): #$ runtimeFlow="ModuleVariableNode for multiphase.is_source, l:-24 -> is_source" print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-25 -> print" else: - print("OK") #$ Unexpected result: runtimeFlow="ModuleVariableNode for multiphase.print, l:-27 -> print" + print("OK") #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-27 -> print" def set_foo(): global foo From 19f6cc00c8f6f70f4cf478db8be1ffb04bd73b73 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Mon, 11 Oct 2021 14:28:25 +0200 Subject: [PATCH 221/361] Python: rewrite import time test --- .../module-initialization/localFlow.ql | 20 +++++++---------- .../module-initialization/multiphase.py | 22 +++++++++---------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql index 3bb6ec021e6..635902e7045 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql +++ b/python/ql/test/experimental/dataflow/module-initialization/localFlow.ql @@ -4,21 +4,17 @@ import experimental.dataflow.TestUtil.FlowTest private import semmle.python.dataflow.new.internal.PrintNode private import semmle.python.dataflow.new.internal.DataFlowPrivate as DP -class ImportTimeLocalFlowTest extends InlineExpectationsTest { +class ImportTimeLocalFlowTest extends FlowTest { ImportTimeLocalFlowTest() { this = "ImportTimeLocalFlowTest" } - override string getARelevantTag() { result = "importTimeFlow" } + override string flowTag() { result = "importTimeFlow" } - override predicate hasActualResult(Location location, string element, string tag, string value) { - exists(DataFlow::Node nodeFrom, DataFlow::ModuleVariableNode nodeTo | - DP::importTimeLocalFlowStep(nodeFrom, nodeTo) - | - nodeFrom.getLocation().getFile().getBaseName() = "multiphase.py" and - location = nodeFrom.getLocation() and - tag = "importTimeFlow" and - value = "\"" + prettyNode(nodeTo).replaceAll("\"", "'") + "\"" and - element = nodeTo.toString() - ) + override predicate relevantFlow(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + nodeFrom.getLocation().getFile().getBaseName() = "multiphase.py" and + // results are displayed next to `nodeTo`, so we need a line to write on + nodeTo.getLocation().getStartLine() > 0 and + nodeTo.asVar() instanceof GlobalSsaVariable and + DP::importTimeLocalFlowStep(nodeFrom, nodeTo) } } diff --git a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py index f2106de4006..1be7a55ff6b 100644 --- a/python/ql/test/experimental/dataflow/module-initialization/multiphase.py +++ b/python/ql/test/experimental/dataflow/module-initialization/multiphase.py @@ -1,40 +1,40 @@ -import sys -import os +import sys #$ importTimeFlow="ImportExpr -> GSSA Variable sys" +import os #$ importTimeFlow="ImportExpr -> GSSA Variable os" sys.path.append(os.path.dirname(os.path.dirname((__file__)))) from testlib import * # These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" +NONSOURCE = "not a source" #$ importTimeFlow="'not a source' -> GSSA Variable NONSOURCE" +SOURCE = "source" #$ importTimeFlow="'source' -> GSSA Variable SOURCE" -def is_source(x): +def is_source(x): #$ importTimeFlow="FunctionExpr -> GSSA Variable is_source" return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j -def SINK(x): +def SINK(x): #$ importTimeFlow="FunctionExpr -> GSSA Variable SINK" if is_source(x): #$ runtimeFlow="ModuleVariableNode for multiphase.is_source, l:-17 -> is_source" print("OK") #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-18 -> print" else: print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-20 -> print" -def SINK_F(x): +def SINK_F(x): #$ importTimeFlow="FunctionExpr -> GSSA Variable SINK_F" if is_source(x): #$ runtimeFlow="ModuleVariableNode for multiphase.is_source, l:-24 -> is_source" print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-25 -> print" else: print("OK") #$ runtimeFlow="ModuleVariableNode for multiphase.print, l:-27 -> print" -def set_foo(): +def set_foo(): #$ importTimeFlow="FunctionExpr -> GSSA Variable set_foo" global foo - foo = SOURCE #$ runtimeFlow="ModuleVariableNode for multiphase.SOURCE, l:-31 -> SOURCE" MISSING:importTimeFlow="ModuleVariableNode for multiphase.foo" + foo = SOURCE #$ runtimeFlow="ModuleVariableNode for multiphase.SOURCE, l:-31 -> SOURCE" # missing final definition of foo -foo = NONSOURCE +foo = NONSOURCE #$ importTimeFlow="NONSOURCE -> GSSA Variable foo" set_foo() @expects(2) -def test_phases(): +def test_phases(): #$ importTimeFlow="expects(..)(..), l:-1 -> GSSA Variable test_phases" global foo SINK(foo) #$ runtimeFlow="ModuleVariableNode for multiphase.SINK, l:-39 -> SINK" runtimeFlow="ModuleVariableNode for multiphase.foo, l:-39 -> foo" foo = NONSOURCE #$ runtimeFlow="ModuleVariableNode for multiphase.NONSOURCE, l:-40 -> NONSOURCE" From ba0dbd58718e435feb42f4a426b63018bdc92f64 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 11 Oct 2021 14:29:10 +0200 Subject: [PATCH 222/361] Java: Improve IncorrectSerializableMethods.ql; address review comments --- .../Serialization/IncorrectSerializableMethods.ql | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql index 60c5ac30523..815245d1a7d 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.ql @@ -15,15 +15,18 @@ import java from Method m, TypeSerializable serializable, string reason where + m.fromSource() and m.getDeclaringType().hasSupertype+(serializable) and ( m.hasStringSignature("readObject(ObjectInputStream)") or m.hasStringSignature("readObjectNoData()") or - m.hasName("writeObject(ObjectOutputStream)") + m.hasStringSignature("writeObject(ObjectOutputStream)") ) and ( not m.isPrivate() and reason = "Method must be private" - or m.isStatic() and reason = "Method must not be static" - or not m.getReturnType() instanceof VoidType and reason = "Return type must be void" + or + m.isStatic() and reason = "Method must not be static" + or + not m.getReturnType() instanceof VoidType and reason = "Return type must be void" ) -select m, reason +select m, "Not recognized by Java serialization framework: " + reason From c7fbddce54a622c55ed5a37e50e7fb041c3ab6d7 Mon Sep 17 00:00:00 2001 From: shati-patel <42641846+shati-patel@users.noreply.github.com> Date: Mon, 11 Oct 2021 15:02:25 +0100 Subject: [PATCH 223/361] Docs: Update beta note for packaging --- docs/codeql/reusables/beta-note-package-management.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/reusables/beta-note-package-management.rst b/docs/codeql/reusables/beta-note-package-management.rst index 025e89489ab..a4fd362a70c 100644 --- a/docs/codeql/reusables/beta-note-package-management.rst +++ b/docs/codeql/reusables/beta-note-package-management.rst @@ -2,4 +2,4 @@ Note - The CodeQL package management functionality, including CodeQL packs, is currently available as a beta release and is subject to change. During the beta release, CodeQL packs are available only using GitHub Packages - the GitHub Container registry. To use this beta functionality, install the beta release of the CodeQL CLI bundle from: https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.6.0-beta.1. \ No newline at end of file + The CodeQL package management functionality, including CodeQL packs, is currently available as a beta release and is subject to change. During the beta release, CodeQL packs are available only using GitHub Packages - the GitHub Container registry. To use this beta functionality, install version 2.6.0 or higher of the CodeQL CLI bundle from: https://github.com/github/codeql-action/releases. \ No newline at end of file From ac6acfb66039a7d26c381638e3930abb20697a16 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Oct 2021 15:36:00 +0100 Subject: [PATCH 224/361] C++: Use data flow. --- cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll index ec09eefea88..2f811ab83a0 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll @@ -1,6 +1,7 @@ import cpp private import semmle.code.cpp.models.interfaces.ArrayFunction private import semmle.code.cpp.models.implementations.Strcat +import semmle.code.cpp.dataflow.DataFlow private predicate mayAddNullTerminatorHelper(Expr e, VariableAccess va, Expr e0) { exists(StackVariable v0, Expr val | @@ -64,10 +65,9 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) { // function containing assembler code exists(AsmStmt s | s.getEnclosingFunction() = f) or - // function where the relevant parameter is returned (leaking it) - exists(ReturnStmt rs | - rs.getEnclosingFunction() = f and rs.getExpr().getAChild*() = f.getParameter(i).getAnAccess() - ) + // function where the relevant parameter is returned (leaking it to be potentially null terminated elsewhere) + DataFlow::localFlow(DataFlow::parameterNode(f.getParameter(i)), + DataFlow::exprNode(any(ReturnStmt rs).getExpr())) ) or // Call without target (e.g., function pointer call) From a8aa8e3bb400cdd56c5ac09b6737503c35e6ddd8 Mon Sep 17 00:00:00 2001 From: Tony Torralba <atorralba@users.noreply.github.com> Date: Mon, 11 Oct 2021 16:38:20 +0200 Subject: [PATCH 225/361] Use InlineExpectationsTest directly --- .../dataflow/taintsources/local.ql | 28 ++++++++++++++----- .../dataflow/taintsources/remote.ql | 28 ++++++++++++++----- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/taintsources/local.ql b/java/ql/test/library-tests/dataflow/taintsources/local.ql index 8cf3a34915d..61faff7a992 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/local.ql +++ b/java/ql/test/library-tests/dataflow/taintsources/local.ql @@ -1,6 +1,6 @@ import java import semmle.code.java.dataflow.FlowSources -import TestUtilities.InlineFlowTest +import TestUtilities.InlineExpectationsTest class LocalSource extends DataFlow::Node { LocalSource() { @@ -9,20 +9,34 @@ class LocalSource extends DataFlow::Node { } } -class LocalValueConf extends DefaultValueFlowConf { - override predicate isSource(DataFlow::Node n) { n instanceof LocalSource } +predicate isTestSink(DataFlow::Node n) { + exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument()) } -class LocalTaintConf extends DefaultTaintFlowConf { +class LocalValueConf extends DataFlow::Configuration { + LocalValueConf() { this = "LocalValueConf" } + override predicate isSource(DataFlow::Node n) { n instanceof LocalSource } + + override predicate isSink(DataFlow::Node n) { isTestSink(n) } } -class LocalFlowTest extends InlineFlowTest { +class LocalTaintConf extends TaintTracking::Configuration { + LocalTaintConf() { this = "LocalTaintConf" } + + override predicate isSource(DataFlow::Node n) { n instanceof LocalSource } + + override predicate isSink(DataFlow::Node n) { isTestSink(n) } +} + +class LocalFlowTest extends InlineExpectationsTest { + LocalFlowTest() { this = "LocalFlowTest" } + override string getARelevantTag() { result = ["hasLocalValueFlow", "hasLocalTaintFlow"] } override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasLocalValueFlow" and - exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) | + exists(DataFlow::Node src, DataFlow::Node sink | any(LocalValueConf c).hasFlow(src, sink) | sink.getLocation() = location and element = sink.toString() and value = "" @@ -30,7 +44,7 @@ class LocalFlowTest extends InlineFlowTest { or tag = "hasLocalTaintFlow" and exists(DataFlow::Node src, DataFlow::Node sink | - getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink) + any(LocalTaintConf c).hasFlow(src, sink) and not any(LocalValueConf c).hasFlow(src, sink) | sink.getLocation() = location and element = sink.toString() and diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.ql b/java/ql/test/library-tests/dataflow/taintsources/remote.ql index afb05e91893..df5ba85227e 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.ql +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.ql @@ -1,21 +1,35 @@ import java import semmle.code.java.dataflow.FlowSources -import TestUtilities.InlineFlowTest +import TestUtilities.InlineExpectationsTest -class RemoteValueConf extends DefaultValueFlowConf { - override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource } +predicate isTestSink(DataFlow::Node n) { + exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument()) } -class RemoteTaintConf extends DefaultTaintFlowConf { +class RemoteValueConf extends DataFlow::Configuration { + RemoteValueConf() { this = "RemoteValueConf" } + override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node n) { isTestSink(n) } } -class RemoteFlowTest extends InlineFlowTest { +class RemoteTaintConf extends TaintTracking::Configuration { + RemoteTaintConf() { this = "RemoteTaintConf" } + + override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node n) { isTestSink(n) } +} + +class RemoteFlowTest extends InlineExpectationsTest { + RemoteFlowTest() { this = "RemoteFlowTest" } + override string getARelevantTag() { result = ["hasRemoteValueFlow", "hasRemoteTaintFlow"] } override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasRemoteValueFlow" and - exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) | + exists(DataFlow::Node src, DataFlow::Node sink | any(RemoteValueConf c).hasFlow(src, sink) | sink.getLocation() = location and element = sink.toString() and value = "" @@ -23,7 +37,7 @@ class RemoteFlowTest extends InlineFlowTest { or tag = "hasRemoteTaintFlow" and exists(DataFlow::Node src, DataFlow::Node sink | - getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink) + any(RemoteTaintConf c).hasFlow(src, sink) and not any(RemoteValueConf c).hasFlow(src, sink) | sink.getLocation() = location and element = sink.toString() and From 4334acb6f2b48cb852ac23180421f0e5061e846b Mon Sep 17 00:00:00 2001 From: ihsinme <ihsinme@gmail.com> Date: Mon, 11 Oct 2021 18:40:03 +0300 Subject: [PATCH 226/361] Update FindWrapperFunctions.qhelp --- .../Security/CWE/CWE-1041/FindWrapperFunctions.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp index 109a806a5b8..cc8519a3410 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.qhelp @@ -3,7 +3,7 @@ "qhelp.dtd"> <qhelp> <overview> -<p>Finding for function calls for which wrapper functions exist.</p> +<p>The presence of a shell function with additional check indicates the possible risks of the call. Use this check everywhere.</p> </overview> From d52f95d24de53c99d52662cb4abb96b956fdf3f0 Mon Sep 17 00:00:00 2001 From: haby0 <ha_yub@163.com> Date: Tue, 12 Oct 2021 09:36:44 +0800 Subject: [PATCH 227/361] Auto Formatting --- python/ql/src/experimental/semmle/python/Frameworks.qll | 1 + .../ql/src/experimental/semmle/python/frameworks/Log.qll | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Frameworks.qll b/python/ql/src/experimental/semmle/python/Frameworks.qll index 5b5161499ff..2ad560cfc1e 100644 --- a/python/ql/src/experimental/semmle/python/Frameworks.qll +++ b/python/ql/src/experimental/semmle/python/Frameworks.qll @@ -1,6 +1,7 @@ /** * Helper file that imports all framework modeling. */ + private import experimental.semmle.python.frameworks.Stdlib private import experimental.semmle.python.frameworks.LDAP private import experimental.semmle.python.frameworks.NoSQL diff --git a/python/ql/src/experimental/semmle/python/frameworks/Log.qll b/python/ql/src/experimental/semmle/python/frameworks/Log.qll index 489bb859b1c..675b9be1c2d 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Log.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Log.qll @@ -37,7 +37,7 @@ private module log { override DataFlow::Node getAnInput() { this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and - result in [this.getArg(_), this.getArgByName(_) ] // this includes the arg named "msg" + result in [this.getArg(_), this.getArgByName(_)] // this includes the arg named "msg" or this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and result in [this.getArg(any(int i | i > 0)), this.getArgByName(any(string s | s != "level"))] @@ -61,7 +61,7 @@ private module log { override DataFlow::Node getAnInput() { this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and - result in [this.getArg(_), this.getArgByName(_) ] // this includes the arg named "msg" + result in [this.getArg(_), this.getArgByName(_)] // this includes the arg named "msg" or this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and result in [this.getArg(any(int i | i > 0)), this.getArgByName(any(string s | s != "level"))] @@ -84,7 +84,7 @@ private module log { override DataFlow::Node getAnInput() { this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and - result in [this.getArg(_), this.getArgByName(_) ] // this includes the arg named "msg" + result in [this.getArg(_), this.getArgByName(_)] // this includes the arg named "msg" or this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and result in [this.getArg(any(int i | i > 0)), this.getArgByName(any(string s | s != "level"))] @@ -109,7 +109,7 @@ private module log { override DataFlow::Node getAnInput() { this.getFunction().(DataFlow::AttrRead).getAttributeName() != "log" and - result in [this.getArg(_), this.getArgByName(_) ] // this includes the arg named "msg" + result in [this.getArg(_), this.getArgByName(_)] // this includes the arg named "msg" or this.getFunction().(DataFlow::AttrRead).getAttributeName() = "log" and result in [this.getArg(any(int i | i > 0)), this.getArgByName(any(string s | s != "level"))] From f34d1ee9971194424651a10a986bbeddf479eaeb Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Oct 2021 10:36:18 +0200 Subject: [PATCH 228/361] Python: Update test expectation following rename --- .../WeakSensitiveDataHashing.expected | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/python/ql/test/query-tests/Security/CWE-327-WeakSensitiveDataHashing/WeakSensitiveDataHashing.expected b/python/ql/test/query-tests/Security/CWE-327-WeakSensitiveDataHashing/WeakSensitiveDataHashing.expected index afd49cad997..24de077ac8f 100644 --- a/python/ql/test/query-tests/Security/CWE-327-WeakSensitiveDataHashing/WeakSensitiveDataHashing.expected +++ b/python/ql/test/query-tests/Security/CWE-327-WeakSensitiveDataHashing/WeakSensitiveDataHashing.expected @@ -1,24 +1,24 @@ edges -| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for Global Variable get_certificate in Module test_cryptodome | test_cryptodome.py:6:17:6:31 | ControlFlowNode for get_certificate | -| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for Global Variable get_password in Module test_cryptodome | test_cryptodome.py:13:17:13:28 | ControlFlowNode for get_password | -| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for Global Variable get_password in Module test_cryptodome | test_cryptodome.py:20:17:20:28 | ControlFlowNode for get_password | +| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for test_cryptodome.get_certificate | test_cryptodome.py:6:17:6:31 | ControlFlowNode for get_certificate | +| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for test_cryptodome.get_password | test_cryptodome.py:13:17:13:28 | ControlFlowNode for get_password | +| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for test_cryptodome.get_password | test_cryptodome.py:20:17:20:28 | ControlFlowNode for get_password | | test_cryptodome.py:2:23:2:34 | ControlFlowNode for ImportMember | test_cryptodome.py:2:23:2:34 | GSSA Variable get_password | -| test_cryptodome.py:2:23:2:34 | GSSA Variable get_password | test_cryptodome.py:0:0:0:0 | ModuleVariableNode for Global Variable get_password in Module test_cryptodome | +| test_cryptodome.py:2:23:2:34 | GSSA Variable get_password | test_cryptodome.py:0:0:0:0 | ModuleVariableNode for test_cryptodome.get_password | | test_cryptodome.py:2:37:2:51 | ControlFlowNode for ImportMember | test_cryptodome.py:2:37:2:51 | GSSA Variable get_certificate | -| test_cryptodome.py:2:37:2:51 | GSSA Variable get_certificate | test_cryptodome.py:0:0:0:0 | ModuleVariableNode for Global Variable get_certificate in Module test_cryptodome | +| test_cryptodome.py:2:37:2:51 | GSSA Variable get_certificate | test_cryptodome.py:0:0:0:0 | ModuleVariableNode for test_cryptodome.get_certificate | | test_cryptodome.py:6:17:6:31 | ControlFlowNode for get_certificate | test_cryptodome.py:8:19:8:27 | ControlFlowNode for dangerous | | test_cryptodome.py:6:17:6:33 | ControlFlowNode for get_certificate() | test_cryptodome.py:8:19:8:27 | ControlFlowNode for dangerous | | test_cryptodome.py:13:17:13:28 | ControlFlowNode for get_password | test_cryptodome.py:15:19:15:27 | ControlFlowNode for dangerous | | test_cryptodome.py:13:17:13:30 | ControlFlowNode for get_password() | test_cryptodome.py:15:19:15:27 | ControlFlowNode for dangerous | | test_cryptodome.py:20:17:20:28 | ControlFlowNode for get_password | test_cryptodome.py:24:19:24:27 | ControlFlowNode for dangerous | | test_cryptodome.py:20:17:20:30 | ControlFlowNode for get_password() | test_cryptodome.py:24:19:24:27 | ControlFlowNode for dangerous | -| test_cryptography.py:0:0:0:0 | ModuleVariableNode for Global Variable get_certificate in Module test_cryptography | test_cryptography.py:7:17:7:31 | ControlFlowNode for get_certificate | -| test_cryptography.py:0:0:0:0 | ModuleVariableNode for Global Variable get_password in Module test_cryptography | test_cryptography.py:15:17:15:28 | ControlFlowNode for get_password | -| test_cryptography.py:0:0:0:0 | ModuleVariableNode for Global Variable get_password in Module test_cryptography | test_cryptography.py:23:17:23:28 | ControlFlowNode for get_password | +| test_cryptography.py:0:0:0:0 | ModuleVariableNode for test_cryptography.get_certificate | test_cryptography.py:7:17:7:31 | ControlFlowNode for get_certificate | +| test_cryptography.py:0:0:0:0 | ModuleVariableNode for test_cryptography.get_password | test_cryptography.py:15:17:15:28 | ControlFlowNode for get_password | +| test_cryptography.py:0:0:0:0 | ModuleVariableNode for test_cryptography.get_password | test_cryptography.py:23:17:23:28 | ControlFlowNode for get_password | | test_cryptography.py:3:23:3:34 | ControlFlowNode for ImportMember | test_cryptography.py:3:23:3:34 | GSSA Variable get_password | -| test_cryptography.py:3:23:3:34 | GSSA Variable get_password | test_cryptography.py:0:0:0:0 | ModuleVariableNode for Global Variable get_password in Module test_cryptography | +| test_cryptography.py:3:23:3:34 | GSSA Variable get_password | test_cryptography.py:0:0:0:0 | ModuleVariableNode for test_cryptography.get_password | | test_cryptography.py:3:37:3:51 | ControlFlowNode for ImportMember | test_cryptography.py:3:37:3:51 | GSSA Variable get_certificate | -| test_cryptography.py:3:37:3:51 | GSSA Variable get_certificate | test_cryptography.py:0:0:0:0 | ModuleVariableNode for Global Variable get_certificate in Module test_cryptography | +| test_cryptography.py:3:37:3:51 | GSSA Variable get_certificate | test_cryptography.py:0:0:0:0 | ModuleVariableNode for test_cryptography.get_certificate | | test_cryptography.py:7:17:7:31 | ControlFlowNode for get_certificate | test_cryptography.py:9:19:9:27 | ControlFlowNode for dangerous | | test_cryptography.py:7:17:7:33 | ControlFlowNode for get_certificate() | test_cryptography.py:9:19:9:27 | ControlFlowNode for dangerous | | test_cryptography.py:15:17:15:28 | ControlFlowNode for get_password | test_cryptography.py:17:19:17:27 | ControlFlowNode for dangerous | @@ -26,8 +26,8 @@ edges | test_cryptography.py:23:17:23:28 | ControlFlowNode for get_password | test_cryptography.py:27:19:27:27 | ControlFlowNode for dangerous | | test_cryptography.py:23:17:23:30 | ControlFlowNode for get_password() | test_cryptography.py:27:19:27:27 | ControlFlowNode for dangerous | nodes -| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for Global Variable get_certificate in Module test_cryptodome | semmle.label | ModuleVariableNode for Global Variable get_certificate in Module test_cryptodome | -| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for Global Variable get_password in Module test_cryptodome | semmle.label | ModuleVariableNode for Global Variable get_password in Module test_cryptodome | +| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for test_cryptodome.get_certificate | semmle.label | ModuleVariableNode for test_cryptodome.get_certificate | +| test_cryptodome.py:0:0:0:0 | ModuleVariableNode for test_cryptodome.get_password | semmle.label | ModuleVariableNode for test_cryptodome.get_password | | test_cryptodome.py:2:23:2:34 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | test_cryptodome.py:2:23:2:34 | GSSA Variable get_password | semmle.label | GSSA Variable get_password | | test_cryptodome.py:2:37:2:51 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | @@ -41,8 +41,8 @@ nodes | test_cryptodome.py:20:17:20:28 | ControlFlowNode for get_password | semmle.label | ControlFlowNode for get_password | | test_cryptodome.py:20:17:20:30 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() | | test_cryptodome.py:24:19:24:27 | ControlFlowNode for dangerous | semmle.label | ControlFlowNode for dangerous | -| test_cryptography.py:0:0:0:0 | ModuleVariableNode for Global Variable get_certificate in Module test_cryptography | semmle.label | ModuleVariableNode for Global Variable get_certificate in Module test_cryptography | -| test_cryptography.py:0:0:0:0 | ModuleVariableNode for Global Variable get_password in Module test_cryptography | semmle.label | ModuleVariableNode for Global Variable get_password in Module test_cryptography | +| test_cryptography.py:0:0:0:0 | ModuleVariableNode for test_cryptography.get_certificate | semmle.label | ModuleVariableNode for test_cryptography.get_certificate | +| test_cryptography.py:0:0:0:0 | ModuleVariableNode for test_cryptography.get_password | semmle.label | ModuleVariableNode for test_cryptography.get_password | | test_cryptography.py:3:23:3:34 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | test_cryptography.py:3:23:3:34 | GSSA Variable get_password | semmle.label | GSSA Variable get_password | | test_cryptography.py:3:37:3:51 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | From b093aaaf27d5e359c6cf3b8eff8635e8572ec89f Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Oct 2021 11:23:27 +0200 Subject: [PATCH 229/361] Python: switch to type tracking for tracking compiled regexes --- .../lib/semmle/python/frameworks/Stdlib.qll | 71 +++++-------------- 1 file changed, 16 insertions(+), 55 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 5f66bc31b27..67b08117ae8 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1540,49 +1540,19 @@ private module StdlibPrivate { /** Helper module for tracking compiled regexes. */ private module CompiledRegexes { - private import semmle.python.dataflow.new.DataFlow4 - private import semmle.python.RegexTreeView - - // TODO: This module should be refactored once API graphs are more expressive. - // For now it uses data flow, so we pick the version with least chance of collision (4) . - /** A configuration for finding uses of compiled regexes. */ - class RegexDefinitionConfiguration extends DataFlow4::Configuration { - RegexDefinitionConfiguration() { this = "RegexDefinitionConfiguration" } - - override predicate isSource(DataFlow::Node source) { source instanceof RegexDefinitonSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof RegexDefinitionSink } + private DataFlow::TypeTrackingNode compiledRegex(DataFlow::TypeTracker t, DataFlow::Node regex) { + t.start() and + result = API::moduleImport("re").getMember("compile").getACall() and + regex in [ + result.(DataFlow::CallCfgNode).getArg(0), + result.(DataFlow::CallCfgNode).getArgByName("pattern") + ] + or + exists(DataFlow::TypeTracker t2 | result = compiledRegex(t2, regex).track(t2, t)) } - /** A regex compilation. */ - class RegexDefinitonSource extends DataFlow::CallCfgNode { - DataFlow::Node regexNode; - - RegexDefinitonSource() { - this = API::moduleImport("re").getMember("compile").getACall() and - regexNode in [this.getArg(0), this.getArgByName("pattern")] - } - - /** Gets the data flow node for the regex being compiled by this node. */ - DataFlow::Node getRegexNode() { result = regexNode } - } - - /** A use of a compiled regex. */ - class RegexDefinitionSink extends DataFlow::Node { - RegexExecutionMethod method; - DataFlow::CallCfgNode executingCall; - - RegexDefinitionSink() { - executingCall = - API::moduleImport("re").getMember("compile").getReturn().getMember(method).getACall() and - this = executingCall.getFunction().(DataFlow::AttrRead).getObject() - } - - /** Gets the method used to execute the regex. */ - RegexExecutionMethod getMethod() { result = method } - - /** Gets the data flow node for the executing call. */ - DataFlow::CallCfgNode getExecutingCall() { result = executingCall } + DataFlow::Node compiledRegex(DataFlow::Node regex) { + compiledRegex(DataFlow::TypeTracker::end(), regex).flowsTo(result) } } @@ -1608,28 +1578,19 @@ private module StdlibPrivate { * * See https://docs.python.org/3/library/re.html#regular-expression-objects */ - private class CompiledRegexExecution extends DataFlow::CallCfgNode, RegexExecution::Range { + private class CompiledRegexExecution extends DataFlow::MethodCallNode, RegexExecution::Range { DataFlow::Node regexNode; - RegexExecutionMethod method; + RegexExecutionMethod methodName; - CompiledRegexExecution() { - exists( - RegexDefinitionConfiguration conf, RegexDefinitonSource source, RegexDefinitionSink sink - | - conf.hasFlow(source, sink) and - regexNode = source.getRegexNode() and - method = sink.getMethod() and - this = sink.getExecutingCall() - ) - } + CompiledRegexExecution() { this.calls(compiledRegex(regexNode), methodName) } override DataFlow::Node getRegex() { result = regexNode } override DataFlow::Node getString() { - result in [this.getArg(getStringArgIndex(method) - 1), this.getArgByName("string")] + result in [this.getArg(getStringArgIndex(methodName) - 1), this.getArgByName("string")] } - override string getName() { result = "re." + method } + override string getName() { result = "re." + methodName } } /** From cd2c9e9ca3cd616caa048e2ed7279e389aa972f5 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 10 Aug 2021 15:20:11 +0100 Subject: [PATCH 230/361] Add Gson support to unsafe deserialization query --- .../code/java/dataflow/ExternalFlow.qll | 2 + .../code/java/frameworks/android/Android.qll | 57 ++++++ .../code/java/frameworks/android/Intent.qll | 31 +++ .../code/java/frameworks/google/Gson.qll | 35 ++++ .../security/UnsafeDeserializationQuery.qll | 18 +- .../security/CWE-502/AndroidManifest.xml | 24 +++ .../security/CWE-502/GsonActivity.java | 17 ++ .../security/CWE-502/GsonServlet.java | 77 ++++++++ .../security/CWE-502/ParcelableEntity.java | 42 +++++ .../test/query-tests/security/CWE-502/options | 2 +- .../android/os/Bundle.java | 12 ++ .../android/os/Parcelable.java | 25 +++ .../gson-2.8.6/com/google/gson/Gson.java | 31 +++ .../com/google/gson/GsonBuilder.java | 99 ++++++++++ .../com/google/gson/JsonIOException.java | 4 + .../com/google/gson/JsonSyntaxException.java | 4 + .../com/google/gson/TypeAdapter.java | 130 +++++++++++++ .../com/google/gson/TypeAdapterFactory.java | 28 +++ .../com/google/gson/reflect/TypeToken.java | 50 +++++ .../com/google/gson/stream/JsonReader.java | 66 +++++++ .../RuntimeTypeAdapterFactory.java | 178 ++++++++++++++++++ 21 files changed, 929 insertions(+), 3 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/frameworks/google/Gson.qll create mode 100755 java/ql/test/query-tests/security/CWE-502/AndroidManifest.xml create mode 100644 java/ql/test/query-tests/security/CWE-502/GsonActivity.java create mode 100644 java/ql/test/query-tests/security/CWE-502/GsonServlet.java create mode 100644 java/ql/test/query-tests/security/CWE-502/ParcelableEntity.java create mode 100644 java/ql/test/stubs/gson-2.8.6/com/google/gson/GsonBuilder.java create mode 100644 java/ql/test/stubs/gson-2.8.6/com/google/gson/JsonIOException.java create mode 100644 java/ql/test/stubs/gson-2.8.6/com/google/gson/JsonSyntaxException.java create mode 100644 java/ql/test/stubs/gson-2.8.6/com/google/gson/TypeAdapter.java create mode 100644 java/ql/test/stubs/gson-2.8.6/com/google/gson/TypeAdapterFactory.java create mode 100644 java/ql/test/stubs/gson-2.8.6/com/google/gson/reflect/TypeToken.java create mode 100644 java/ql/test/stubs/gson-2.8.6/com/google/gson/stream/JsonReader.java create mode 100644 java/ql/test/stubs/gson-2.8.6/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index add522f265e..cedeb71189c 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -77,6 +77,8 @@ private import FlowSummary */ private module Frameworks { private import internal.ContainerFlow + private import semmle.code.java.frameworks.android.Android + private import semmle.code.java.frameworks.android.Intent private import semmle.code.java.frameworks.android.XssSinks private import semmle.code.java.frameworks.android.Intent private import semmle.code.java.frameworks.ApacheHttp diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index 3bb07db2d9a..0999c952898 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -5,6 +5,7 @@ import java import semmle.code.java.dataflow.ExternalFlow import semmle.code.xml.AndroidManifest +private import semmle.code.java.dataflow.ExternalFlow /** * Gets a transitive superType avoiding magic optimisation @@ -202,3 +203,59 @@ private class ContentProviderSourceModels extends SourceModelCsv { ] } } + +/** Interface for classes whose instances can be written to and restored from a Parcel. */ +class TypeParcelable extends Interface { + TypeParcelable() { this.hasQualifiedName("android.os", "Parcelable") } +} + +/** + * A method that overrides `android.os.Parcelable.Creator.createFromParcel`. + */ +class CreateFromParcelMethod extends Method { + CreateFromParcelMethod() { + this.hasName("createFromParcel") and + this.getEnclosingCallable().getDeclaringType().getASupertype*() instanceof TypeParcelable + } +} + +private class TaintPropagationModels extends SummaryModelCsv { + override predicate row(string s) { + // BaseBundle getters + s = + "android.os;BaseBundle;true;get" + ["Boolean", "Double", "Int", "Long", "String"] + + ["", "Array"] + ";;;Argument[-1];ReturnValue;taint" + or + // Bundle getters + s = + "android.os;Bundle;true;get" + + [ + "Binder", "Bundle", "Byte", "ByteArray", "Char", "CharArray", "CharSequence", + "CharSequenceArray", "CharSequenceArrayList", "Float", "FloatArray", "IntegerArrayList", + "Parcelable", "ParcelableArray", "ParcelableArrayList", "Serializable", "Short", + "ShortArray", "Size", "SizeF", "SparseParcelableArray", "StringArrayList" + ] + ";;;Argument[-1];ReturnValue;taint" + or + // Intent readers that return their value + s = + "android.os;Parcel;false;read" + + [ + "Array", "ArrayList", "Boolean", "Bundle", "Byte", "Double", "FileDescriptor", "Float", + "HashMap", "Int", "Long", "Parcelable", "ParcelableArray", "PersistableBundle", + "Serializable", "Size", "SizeF", "SparseArray", "SparseBolleanArray", "String", + "StrongBinder", "TypedObject", "Value" + ] + ";;;Argument[-1];ReturnValue;taint" + or + // Intent readers that write to an existing object + s = + "android.os;Parcel;false;read" + + [ + "BinderArray", "BinderList", "BooleanArray", "ByteArray", "CharArray", "DoubleArray", + "FloatArray", "IntArray", "List", "LongArray", "Map", "ParcelableList", "StringArray", + "StringList", "TypedArray", "TypedList" + ] + ";;;Argument[-1];Argument[0];taint" + or + // One Intent method that aliases an argument to a return value + s = "android.os;Parcel;false;readParcelableList;;;Argument[0];ReturnValue;value" + } +} diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 47f0df13365..3798d91d99a 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -3,32 +3,53 @@ private import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.FlowSteps import semmle.code.java.dataflow.ExternalFlow +/** + * The class `android.content.Intent`. + */ class TypeIntent extends Class { TypeIntent() { hasQualifiedName("android.content", "Intent") } } +/** + * The class `android.app.Activity`. + */ class TypeActivity extends Class { TypeActivity() { hasQualifiedName("android.app", "Activity") } } +/** + * The class `android.content.Context`. + */ class TypeContext extends RefType { TypeContext() { hasQualifiedName("android.content", "Context") } } +/** + * The class `android.content.BroadcastReceiver`. + */ class TypeBroadcastReceiver extends Class { TypeBroadcastReceiver() { hasQualifiedName("android.content", "BroadcastReceiver") } } +/** + * The method `Activity.getIntent` + */ class AndroidGetIntentMethod extends Method { AndroidGetIntentMethod() { hasName("getIntent") and getDeclaringType() instanceof TypeActivity } } +/** + * The method `BroadcastReceiver.onReceive`. + */ class AndroidReceiveIntentMethod extends Method { AndroidReceiveIntentMethod() { hasName("onReceive") and getDeclaringType() instanceof TypeBroadcastReceiver } } +/** + * The method `Context.startActivity` or `startActivities`. + */ class ContextStartActivityMethod extends Method { ContextStartActivityMethod() { (hasName("startActivity") or hasName("startActivities")) and @@ -44,6 +65,16 @@ private class IntentFieldsInheritTaint extends DataFlow::SyntheticFieldContent, IntentFieldsInheritTaint() { this.getField().matches("android.content.Intent.%") } } +/** + * The method `Intent.getParcelableExtra`. + */ +class IntentGetParcelableExtraMethod extends Method { + IntentGetParcelableExtraMethod() { + hasName("getParcelableExtra") and + getDeclaringType() instanceof TypeIntent + } +} + private class IntentBundleFlowSteps extends SummaryModelCsv { override predicate row(string row) { row = diff --git a/java/ql/lib/semmle/code/java/frameworks/google/Gson.qll b/java/ql/lib/semmle/code/java/frameworks/google/Gson.qll new file mode 100644 index 00000000000..b0cb99bb5f8 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/google/Gson.qll @@ -0,0 +1,35 @@ +/** + * Provides classes for working with the Gson framework. + */ + +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.frameworks.android.Android +import semmle.code.java.frameworks.android.Intent + +/** The class `com.google.gson.Gson`. */ +class Gson extends RefType { + Gson() { this.hasQualifiedName("com.google.gson", "Gson") } +} + +/** The `fromJson` deserialization method. */ +class GsonDeserializeMethod extends Method { + GsonDeserializeMethod() { + this.getDeclaringType() instanceof Gson and + this.hasName("fromJson") + } +} + +/** + * Holds if `intentNode` is an `Intent` used in the context `(T)intentNode.getParcelableExtra(...)` and + * `parcelNode` is the corresponding parameter of `Parcelable.Creator<T> { public T createFromParcel(Parcel parcelNode) { }`. + */ +predicate intentFlowsToParcel(DataFlow::Node intentNode, DataFlow::Node parcelNode) { + exists(MethodAccess getParcelableExtraCall, CreateFromParcelMethod cfpm, Type createdType | + intentNode.asExpr() = getParcelableExtraCall.getQualifier() and + getParcelableExtraCall.getMethod() instanceof IntentGetParcelableExtraMethod and + DataFlow::localExprFlow(getParcelableExtraCall, any(Expr e | e.getType() = createdType)) and + parcelNode.asParameter() = cfpm.getParameter(0) and + cfpm.getReturnType() = createdType + ) +} diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index f4a7e91ff2e..41c15a83823 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -17,6 +17,7 @@ private import semmle.code.java.frameworks.Jackson private import semmle.code.java.frameworks.Jabsorb private import semmle.code.java.frameworks.JoddJson private import semmle.code.java.frameworks.Flexjson +private import semmle.code.java.frameworks.google.Gson private import semmle.code.java.frameworks.apache.Lang private import semmle.code.java.Reflection @@ -207,6 +208,10 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) { or m instanceof FlexjsonDeserializeMethod and sink = ma.getArgument(0) + or + m instanceof GsonDeserializeMethod and + sink = ma.getArgument(0) and + any(UnsafeTypeConfig config).hasFlowToExpr(ma.getArgument(1)) ) } @@ -249,6 +254,8 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration { createJacksonJsonParserStep(pred, succ) or createJacksonTreeNodeStep(pred, succ) + or + intentFlowsToParcel(pred, succ) } override predicate isSanitizer(DataFlow::Node node) { @@ -362,9 +369,15 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration { ma.getMethod() instanceof JabsorbUnmarshallMethod or ma.getMethod() instanceof JoddJsonParseMethod + or + ma.getMethod() instanceof GsonDeserializeMethod ) and // Note `JacksonTypeDescriptorType` includes plain old `java.lang.Class` - arg.getType() instanceof JacksonTypeDescriptorType and + ( + arg.getType() instanceof JacksonTypeDescriptorType + or + arg.getType().(RefType).hasQualifiedName("java.lang.reflect", "Type") + ) and arg = sink.asExpr() ) } @@ -375,7 +388,8 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration { */ override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { resolveClassStep(fromNode, toNode) or - looksLikeResolveClassStep(fromNode, toNode) + looksLikeResolveClassStep(fromNode, toNode) or + intentFlowsToParcel(fromNode, toNode) } } diff --git a/java/ql/test/query-tests/security/CWE-502/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-502/AndroidManifest.xml new file mode 100755 index 00000000000..6a9785b8da4 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-502/AndroidManifest.xml @@ -0,0 +1,24 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.app" + android:installLocation="auto" + android:versionCode="1" + android:versionName="0.1" > + + <uses-permission android:name="android.permission.INTERNET" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" > + <activity + android:name=".GsonActivity" + android:icon="@drawable/ic_launcher" + android:label="@string/app_name"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/java/ql/test/query-tests/security/CWE-502/GsonActivity.java b/java/ql/test/query-tests/security/CWE-502/GsonActivity.java new file mode 100644 index 00000000000..a080924c6cd --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-502/GsonActivity.java @@ -0,0 +1,17 @@ +package com.example.app; + +import android.app.Activity; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.Gson; + +public class GsonActivity extends Activity { + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(-1); + + ParcelableEntity entity = (ParcelableEntity) getIntent().getParcelableExtra("jsonEntity"); + } +} diff --git a/java/ql/test/query-tests/security/CWE-502/GsonServlet.java b/java/ql/test/query-tests/security/CWE-502/GsonServlet.java new file mode 100644 index 00000000000..47534d2d7a0 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-502/GsonServlet.java @@ -0,0 +1,77 @@ +import java.io.IOException; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.typeadapters.RuntimeTypeAdapterFactory; + +import com.example.User; +import com.thirdparty.Person; + +public class GsonServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + // GOOD: concrete class type specified + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + + Gson gson = new Gson(); + Object obj = gson.fromJson(json, User.class); + } + + @Override + // GOOD: concrete class type specified + public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + + Gson gson = new Gson(); + Object obj = gson.fromJson(json, Person.class); + } + + @Override + // BAD: allow class name to be controlled by remote source + public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + String clazz = req.getParameter("class"); + + try { + Gson gson = new Gson(); + Object obj = gson.fromJson(json, Class.forName(clazz)); // $unsafeDeserialization + } catch (ClassNotFoundException cne) { + throw new IOException(cne.getMessage()); + } + } + + @Override + // BAD: allow class name to be controlled by remote source even with a type adapter factory + public void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + String clazz = req.getParameter("class"); + + try { + RuntimeTypeAdapterFactory<User> runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory + .of(User.class, "type"); + Gson gson = new GsonBuilder().registerTypeAdapterFactory(runtimeTypeAdapterFactory).create(); + Object obj = gson.fromJson(json, Class.forName(clazz)); // $unsafeDeserialization + } catch (ClassNotFoundException cne) { + throw new IOException(cne.getMessage()); + } + } + + @Override + // GOOD: specify allowed class types without explicitly configured vulnerable subclass types + public void doTrace(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + String clazz = req.getParameter("class"); + + RuntimeTypeAdapterFactory<Person> runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory + .of(Person.class, "type"); + Gson gson = new GsonBuilder().registerTypeAdapterFactory(runtimeTypeAdapterFactory).create(); + Person obj = gson.fromJson(json, Person.class); + } +} \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-502/ParcelableEntity.java b/java/ql/test/query-tests/security/CWE-502/ParcelableEntity.java new file mode 100644 index 00000000000..e151af4a88a --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-502/ParcelableEntity.java @@ -0,0 +1,42 @@ +package com.example.app; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class ParcelableEntity implements Parcelable { + private static final Gson GSON = new GsonBuilder().create(); + + public ParcelableEntity(Object obj) { + this.obj = obj; + } + + private Object obj; + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeString(obj.getClass().getName()); + parcel.writeString(GSON.toJson(obj)); + } + + public static final Parcelable.Creator CREATOR = new Creator<ParcelableEntity>() { + @Override + public ParcelableEntity createFromParcel(Parcel parcel) { + try { + Class clazz = Class.forName(parcel.readString()); + Object obj = GSON.fromJson(parcel.readString(), clazz); // $unsafeDeserialization + return new ParcelableEntity(obj); + } + catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public ParcelableEntity[] newArray(int size) { + return new ParcelableEntity[size]; + } + }; +} diff --git a/java/ql/test/query-tests/security/CWE-502/options b/java/ql/test/query-tests/security/CWE-502/options index cdd0375684e..0e9cab2d100 100644 --- a/java/ql/test/query-tests/security/CWE-502/options +++ b/java/ql/test/query-tests/security/CWE-502/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3:${testdir}/../../../stubs/flexjson-2.1 +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3:${testdir}/../../../stubs/flexjson-2.1:${testdir}/../../../stubs/gson-2.8.6:${testdir}/../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Bundle.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Bundle.java index 6c074780ee4..d109f766c77 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/os/Bundle.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Bundle.java @@ -348,6 +348,18 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { return null; } + /** + * Returns the value associated with the given key, or null if + * no mapping of the desired type exists for the given key or a null + * value is explicitly associated with the key. + * + * @param key a String, or null + * @return a Parcelable value, or null + */ + public <T extends Parcelable> T getParcelable(String key) { + return null; + } + /** * Returns the value associated with the given key, or null if no mapping of the * desired type exists for the given key or a null value is explicitly diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Parcelable.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Parcelable.java index ba9942dbb79..e3c46053a7e 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/os/Parcelable.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Parcelable.java @@ -66,6 +66,31 @@ public interface Parcelable { */ public void writeToParcel(Parcel dest, int flags); + /** + * Interface that must be implemented and provided as a public CREATOR + * field that generates instances of your Parcelable class from a Parcel. + */ + public interface Creator<T> { + /** + * Create a new instance of the Parcelable class, instantiating it + * from the given Parcel whose data had previously been written by + * {@link Parcelable#writeToParcel Parcelable.writeToParcel()}. + * + * @param source The Parcel to read the object's data from. + * @return Returns a new instance of the Parcelable class. + */ + public T createFromParcel(Parcel source); + + /** + * Create a new array of the Parcelable class. + * + * @param size Size of the array. + * @return Returns an array of the Parcelable class, with every entry + * initialized to null. + */ + public T[] newArray(int size); + } + /** * Specialization of {@link Creator} that allows you to receive the ClassLoader * the object is being created in. diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/Gson.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/Gson.java index bbe53dc2a5f..a269763665b 100644 --- a/java/ql/test/stubs/gson-2.8.6/com/google/gson/Gson.java +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/Gson.java @@ -1,7 +1,38 @@ package com.google.gson; +import java.lang.reflect.Type; +import java.io.Reader; +import com.google.gson.stream.JsonReader; + public final class Gson { + public Gson() { + } + public String toJson(Object src) { return null; } + + public String toJson(Object src, Type typeOfSrc) { + return null; + } + + public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException { + return null; + } + + public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException { + return null; + } + + public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException { + return null; + } + + public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { + return null; + } + + public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { + return null; + } } diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/GsonBuilder.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/GsonBuilder.java new file mode 100644 index 00000000000..3853cb40356 --- /dev/null +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/GsonBuilder.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gson; + +import java.lang.reflect.Type; + +public final class GsonBuilder { + /** + * Creates a GsonBuilder instance that can be used to build Gson with various configuration + * settings. GsonBuilder follows the builder pattern, and it is typically used by first + * invoking various configuration methods to set desired options, and finally calling + * {@link #create()}. + */ + public GsonBuilder() { + } + + /** + * Constructs a GsonBuilder instance from a Gson instance. The newly constructed GsonBuilder + * has the same configuration as the previously built Gson instance. + * + * @param gson the gson instance whose configuration should by applied to a new GsonBuilder. + */ + GsonBuilder(Gson gson) { + } + + /** + * Configures Gson for custom serialization or deserialization. This method combines the + * registration of an {@link TypeAdapter}, {@link InstanceCreator}, {@link JsonSerializer}, and a + * {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements + * all the required interfaces for custom serialization with Gson. If a type adapter was + * previously registered for the specified {@code type}, it is overwritten. + * + * <p>This registers the type specified and no other types: you must manually register related + * types! For example, applications registering {@code boolean.class} should also register {@code + * Boolean.class}. + * + * @param type the type definition for the type adapter being registered + * @param typeAdapter This object must implement at least one of the {@link TypeAdapter}, + * {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + */ + public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) { + return null; + } + + /** + * Register a factory for type adapters. Registering a factory is useful when the type + * adapter needs to be configured based on the type of the field being processed. Gson + * is designed to handle a large number of factories, so you should consider registering + * them to be at par with registering an individual type adapter. + * + * @since 2.1 + */ + public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) { + return null; + } + + /** + * Configures Gson for custom serialization or deserialization for an inheritance type hierarchy. + * This method combines the registration of a {@link TypeAdapter}, {@link JsonSerializer} and + * a {@link JsonDeserializer}. If a type adapter was previously registered for the specified + * type hierarchy, it is overridden. If a type adapter is registered for a specific type in + * the type hierarchy, it will be invoked instead of the one registered for the type hierarchy. + * + * @param baseType the class definition for the type adapter being registered for the base class + * or interface + * @param typeAdapter This object must implement at least one of {@link TypeAdapter}, + * {@link JsonSerializer} or {@link JsonDeserializer} interfaces. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.7 + */ + public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) { + return null; + } + + /** + * Creates a {@link Gson} instance based on the current configuration. This method is free of + * side-effects to this {@code GsonBuilder} instance and hence can be called multiple times. + * + * @return an instance of Gson configured with the options currently set in this builder + */ + public Gson create() { + return null; + } +} \ No newline at end of file diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/JsonIOException.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/JsonIOException.java new file mode 100644 index 00000000000..a59ec65e6a3 --- /dev/null +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/JsonIOException.java @@ -0,0 +1,4 @@ +package com.google.gson; + +public final class JsonIOException extends RuntimeException { +} diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/JsonSyntaxException.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/JsonSyntaxException.java new file mode 100644 index 00000000000..c4dcc69b2ba --- /dev/null +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/JsonSyntaxException.java @@ -0,0 +1,4 @@ +package com.google.gson; + +public final class JsonSyntaxException extends RuntimeException { +} diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/TypeAdapter.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/TypeAdapter.java new file mode 100644 index 00000000000..73e6ef993b7 --- /dev/null +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/TypeAdapter.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gson; + +import com.google.gson.stream.JsonReader; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; + +public abstract class TypeAdapter<T> { + /** + * Converts {@code value} to a JSON document and writes it to {@code out}. + * Unlike Gson's similar {@link Gson#toJson(JsonElement, Appendable) toJson} + * method, this write is strict. Create a {@link + * JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call + * {@link #write(com.google.gson.stream.JsonWriter, Object)} for lenient + * writing. + * + * @param value the Java object to convert. May be null. + * @since 2.2 + */ + public final void toJson(Writer out, T value) throws IOException { + } + + /** + * This wrapper method is used to make a type adapter null tolerant. In general, a + * type adapter is required to handle nulls in write and read methods. Here is how this + * is typically done:<br> + * <pre> {@code + * + * Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class, + * new TypeAdapter<Foo>() { + * public Foo read(JsonReader in) throws IOException { + * if (in.peek() == JsonToken.NULL) { + * in.nextNull(); + * return null; + * } + * // read a Foo from in and return it + * } + * public void write(JsonWriter out, Foo src) throws IOException { + * if (src == null) { + * out.nullValue(); + * return; + * } + * // write src as JSON to out + * } + * }).create(); + * }</pre> + * You can avoid this boilerplate handling of nulls by wrapping your type adapter with + * this method. Here is how we will rewrite the above example: + * <pre> {@code + * + * Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class, + * new TypeAdapter<Foo>() { + * public Foo read(JsonReader in) throws IOException { + * // read a Foo from in and return it + * } + * public void write(JsonWriter out, Foo src) throws IOException { + * // write src as JSON to out + * } + * }.nullSafe()).create(); + * }</pre> + * Note that we didn't need to check for nulls in our type adapter after we used nullSafe. + */ + public final TypeAdapter<T> nullSafe() { + return null; + } + + /** + * Converts {@code value} to a JSON document. Unlike Gson's similar {@link + * Gson#toJson(Object) toJson} method, this write is strict. Create a {@link + * JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call + * {@link #write(com.google.gson.stream.JsonWriter, Object)} for lenient + * writing. + * + * @param value the Java object to convert. May be null. + * @since 2.2 + */ + public final String toJson(T value) { + return null; + } + + /** + * Reads one JSON value (an array, object, string, number, boolean or null) + * and converts it to a Java object. Returns the converted object. + * + * @return the converted Java object. May be null. + */ + public abstract T read(JsonReader in) throws IOException; + + /** + * Converts the JSON document in {@code in} to a Java object. Unlike Gson's + * similar {@link Gson#fromJson(java.io.Reader, Class) fromJson} method, this + * read is strict. Create a {@link JsonReader#setLenient(boolean) lenient} + * {@code JsonReader} and call {@link #read(JsonReader)} for lenient reading. + * + * @return the converted Java object. May be null. + * @since 2.2 + */ + public final T fromJson(Reader in) throws IOException { + return null; + } + + /** + * Converts the JSON document in {@code json} to a Java object. Unlike Gson's + * similar {@link Gson#fromJson(String, Class) fromJson} method, this read is + * strict. Create a {@link JsonReader#setLenient(boolean) lenient} {@code + * JsonReader} and call {@link #read(JsonReader)} for lenient reading. + * + * @return the converted Java object. May be null. + * @since 2.2 + */ + public final T fromJson(String json) throws IOException { + return null; + } +} diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/TypeAdapterFactory.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/TypeAdapterFactory.java new file mode 100644 index 00000000000..d6cc8133712 --- /dev/null +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/TypeAdapterFactory.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gson; + +import com.google.gson.reflect.TypeToken; + +public interface TypeAdapterFactory { + + /** + * Returns a type adapter for {@code type}, or null if this factory doesn't + * support {@code type}. + */ + <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type); +} \ No newline at end of file diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/reflect/TypeToken.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/reflect/TypeToken.java new file mode 100644 index 00000000000..a35b2a45b85 --- /dev/null +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/reflect/TypeToken.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gson.reflect; + +/** + * Represents a generic type {@code T}. Java doesn't yet provide a way to + * represent generic types, so this class does. Forces clients to create a + * subclass of this class which enables retrieval the type information even at + * runtime. + * + * <p>For example, to create a type literal for {@code List<String>}, you can + * create an empty anonymous inner class: + * + * <p> + * {@code TypeToken<List<String>> list = new TypeToken<List<String>>() {};} + * + * <p>This syntax cannot be used to create type literals that have wildcard + * parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}. + * + * @author Bob Lee + * @author Sven Mawson + * @author Jesse Wilson + */ +public class TypeToken<T> { + + /** + * Constructs a new type literal. Derives represented class from type + * parameter. + * + * <p>Clients create an empty anonymous subclass. Doing so embeds the type + * parameter in the anonymous class's type hierarchy so we can reconstitute it + * at runtime despite erasure. + */ + protected TypeToken() { + } +} \ No newline at end of file diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/stream/JsonReader.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/stream/JsonReader.java new file mode 100644 index 00000000000..5d0d2ad112f --- /dev/null +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/stream/JsonReader.java @@ -0,0 +1,66 @@ +package com.google.gson.stream; + +import java.io.Closeable; +import java.io.IOException; +import java.io.Reader; + +public class JsonReader implements Closeable { + public JsonReader(Reader in) { + } + + public final void setLenient(boolean lenient) { + } + + public final boolean isLenient() { + return false; + } + + public void beginArray() throws IOException { + } + + public void endArray() throws IOException { + } + + public void beginObject() throws IOException { + } + + public void endObject() throws IOException { + } + + public boolean hasNext() throws IOException { + return false; + } + + public String nextName() throws IOException { + return null; + } + + public String nextString() throws IOException { + return null; + } + + public boolean nextBoolean() throws IOException { + return false; + } + + public void nextNull() throws IOException { + } + + public double nextDouble() throws IOException { + return -1; + } + + public long nextLong() throws IOException { + return -1; + } + + public int nextInt() throws IOException { + return -1; + } + + public void close() throws IOException { + } + + public void skipValue() throws IOException { + } +} \ No newline at end of file diff --git a/java/ql/test/stubs/gson-2.8.6/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java b/java/ql/test/stubs/gson-2.8.6/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java new file mode 100644 index 00000000000..b808ccf4e1f --- /dev/null +++ b/java/ql/test/stubs/gson-2.8.6/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gson.typeadapters; + +import java.io.IOException; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; + +/** + * Adapts values whose runtime type may differ from their declaration type. This + * is necessary when a field's type is not the same type that GSON should create + * when deserializing that field. For example, consider these types: + * <pre> {@code + * abstract class Shape { + * int x; + * int y; + * } + * class Circle extends Shape { + * int radius; + * } + * class Rectangle extends Shape { + * int width; + * int height; + * } + * class Diamond extends Shape { + * int width; + * int height; + * } + * class Drawing { + * Shape bottomShape; + * Shape topShape; + * } + * }</pre> + * <p>Without additional type information, the serialized JSON is ambiguous. Is + * the bottom shape in this drawing a rectangle or a diamond? <pre> {@code + * { + * "bottomShape": { + * "width": 10, + * "height": 5, + * "x": 0, + * "y": 0 + * }, + * "topShape": { + * "radius": 2, + * "x": 4, + * "y": 1 + * } + * }}</pre> + * This class addresses this problem by adding type information to the + * serialized JSON and honoring that type information when the JSON is + * deserialized: <pre> {@code + * { + * "bottomShape": { + * "type": "Diamond", + * "width": 10, + * "height": 5, + * "x": 0, + * "y": 0 + * }, + * "topShape": { + * "type": "Circle", + * "radius": 2, + * "x": 4, + * "y": 1 + * } + * }}</pre> + * Both the type field name ({@code "type"}) and the type labels ({@code + * "Rectangle"}) are configurable. + * + * <h3>Registering Types</h3> + * Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field + * name to the {@link #of} factory method. If you don't supply an explicit type + * field name, {@code "type"} will be used. <pre> {@code + * RuntimeTypeAdapterFactory<Shape> shapeAdapterFactory + * = RuntimeTypeAdapterFactory.of(Shape.class, "type"); + * }</pre> + * Next register all of your subtypes. Every subtype must be explicitly + * registered. This protects your application from injection attacks. If you + * don't supply an explicit type label, the type's simple name will be used. + * <pre> {@code + * shapeAdapterFactory.registerSubtype(Rectangle.class, "Rectangle"); + * shapeAdapterFactory.registerSubtype(Circle.class, "Circle"); + * shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond"); + * }</pre> + * Finally, register the type adapter factory in your application's GSON builder: + * <pre> {@code + * Gson gson = new GsonBuilder() + * .registerTypeAdapterFactory(shapeAdapterFactory) + * .create(); + * }</pre> + * Like {@code GsonBuilder}, this API supports chaining: <pre> {@code + * RuntimeTypeAdapterFactory<Shape> shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class) + * .registerSubtype(Rectangle.class) + * .registerSubtype(Circle.class) + * .registerSubtype(Diamond.class); + * }</pre> + * + * <h3>Serialization and deserialization</h3> + * In order to serialize and deserialize a polymorphic object, + * you must specify the base type explicitly. + * <pre> {@code + * Diamond diamond = new Diamond(); + * String json = gson.toJson(diamond, Shape.class); + * }</pre> + * And then: + * <pre> {@code + * Shape shape = gson.fromJson(json, Shape.class); + * }</pre> + */ +public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory { + /** + * Creates a new runtime type adapter using for {@code baseType} using {@code + * typeFieldName} as the type field name. Type field names are case sensitive. + * {@code maintainType} flag decide if the type will be stored in pojo or not. + */ + public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName, boolean maintainType) { + return null; + } + + /** + * Creates a new runtime type adapter using for {@code baseType} using {@code + * typeFieldName} as the type field name. Type field names are case sensitive. + */ + public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) { + return null; + } + + /** + * Creates a new runtime type adapter for {@code baseType} using {@code "type"} as + * the type field name. + */ + public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType) { + return null; + } + + /** + * Registers {@code type} identified by {@code label}. Labels are case + * sensitive. + * + * @throws IllegalArgumentException if either {@code type} or {@code label} + * have already been registered on this type adapter. + */ + public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type, String label) { + return null; + } + + /** + * Registers {@code type} identified by its {@link Class#getSimpleName simple + * name}. Labels are case sensitive. + * + * @throws IllegalArgumentException if either {@code type} or its simple name + * have already been registered on this type adapter. + */ + public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type) { + return null; + } + + public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) { + return null; + } +} From fc0b18cf61bb9086e617c9866bd2655e57411bfc Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 10 Aug 2021 16:38:11 +0100 Subject: [PATCH 231/361] Add tests for Android flow steps --- .../code/java/frameworks/android/Android.qll | 2 +- .../frameworks/android/flow-steps/Test.java | 824 +++++++++++++++++ .../frameworks/android/flow-steps/options | 1 + .../android/flow-steps/test.expected | 0 .../frameworks/android/flow-steps/test.ql | 53 ++ .../android/accounts/Account.java | 21 + .../android/database/CharArrayBuffer.java | 13 + .../android/database/ContentObserver.java | 17 + .../android/database/DataSetObserver.java | 11 + .../database/DatabaseErrorHandler.java | 10 + .../database/sqlite/SQLiteClosable.java | 16 + .../database/sqlite/SQLiteCursorDriver.java | 15 + .../database/sqlite/SQLiteDatabase.java | 122 +++ .../database/sqlite/SQLiteProgram.java | 19 + .../android/database/sqlite/SQLiteQuery.java | 11 + .../database/sqlite/SQLiteStatement.java | 18 + .../sqlite/SQLiteTransactionListener.java | 11 + .../android/graphics/Bitmap.java | 97 ++ .../android/graphics/BitmapFactory.java | 54 ++ .../android/graphics/BlendMode.java | 10 + .../android/graphics/Canvas.java | 138 +++ .../android/graphics/Color.java | 80 ++ .../android/graphics/ColorFilter.java | 9 + .../android/graphics/ColorSpace.java | 122 +++ .../android/graphics/DrawFilter.java | 10 + .../android/graphics/Insets.java | 29 + .../android/graphics/MaskFilter.java | 10 + .../android/graphics/Matrix.java | 74 ++ .../android/graphics/Movie.java | 23 + .../android/graphics/NinePatch.java | 31 + .../android/graphics/Outline.java | 28 + .../android/graphics/Paint.java | 212 +++++ .../android/graphics/Path.java | 73 ++ .../android/graphics/PathEffect.java | 10 + .../android/graphics/Picture.java | 18 + .../android/graphics/Point.java | 26 + .../android/graphics/PorterDuff.java | 14 + .../android/graphics/RecordingCanvas.java | 83 ++ .../android/graphics/Rect.java | 52 ++ .../android/graphics/RectF.java | 53 ++ .../android/graphics/Region.java | 53 ++ .../android/graphics/RenderNode.java | 82 ++ .../android/graphics/Shader.java | 12 + .../android/graphics/Typeface.java | 33 + .../android/graphics/Xfermode.java | 9 + .../android/graphics/drawable/Drawable.java | 111 +++ .../android/graphics/drawable/Icon.java | 52 ++ .../android/graphics/text/MeasuredText.java | 13 + .../android/hardware/HardwareBuffer.java | 49 + .../android/icu/util/ULocale.java | 138 +++ .../google-android-9.0.0/android/net/Uri.java | 593 ++---------- .../android/os/BaseBundle.java | 865 +----------------- .../android/os/Bundle.java | 587 ++---------- .../android/os/Handler.java | 53 ++ .../android/os/IBinder.java | 32 + .../android/os/IInterface.java | 10 + .../android/os/LocaleList.java | 32 + .../android/os/Looper.java | 25 + .../android/os/Message.java | 44 + .../android/os/MessageQueue.java | 27 + .../android/os/Messenger.java | 25 + .../android/os/Parcel.java | 794 +++------------- .../android/os/Parcelable.java | 121 +-- .../android/os/PersistableBundle.java | 23 + .../android/os/UserHandle.java | 21 + .../android/util/AttributeSet.java | 31 + .../android/util/DisplayMetrics.java | 46 + .../android/util/Printer.java | 9 + .../android/util/Size.java | 16 + .../android/util/SizeF.java | 16 + .../android/util/SparseArray.java | 27 + .../android/util/SparseBooleanArray.java | 27 + .../android/util/TypedValue.java | 73 ++ .../android/view/Display.java | 88 ++ .../android/view/DisplayCutout.java | 26 + .../org/xmlpull/v1/XmlPullParser.java | 64 ++ .../org/xmlpull/v1/XmlSerializer.java | 35 + 77 files changed, 4050 insertions(+), 2632 deletions(-) create mode 100644 java/ql/test/library-tests/frameworks/android/flow-steps/Test.java create mode 100644 java/ql/test/library-tests/frameworks/android/flow-steps/options create mode 100644 java/ql/test/library-tests/frameworks/android/flow-steps/test.expected create mode 100644 java/ql/test/library-tests/frameworks/android/flow-steps/test.ql create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/accounts/Account.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/CharArrayBuffer.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/ContentObserver.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/DataSetObserver.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/DatabaseErrorHandler.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteClosable.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteCursorDriver.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteDatabase.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteProgram.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteQuery.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteStatement.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteTransactionListener.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Bitmap.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/BitmapFactory.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/BlendMode.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Canvas.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Color.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/ColorFilter.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/ColorSpace.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/DrawFilter.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Insets.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/MaskFilter.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Matrix.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Movie.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/NinePatch.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Outline.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Paint.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Path.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/PathEffect.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Picture.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Point.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/PorterDuff.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/RecordingCanvas.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Rect.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/RectF.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Region.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/RenderNode.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Shader.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Typeface.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/Xfermode.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/drawable/Drawable.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/drawable/Icon.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/graphics/text/MeasuredText.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/hardware/HardwareBuffer.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/icu/util/ULocale.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/Handler.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/IBinder.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/IInterface.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/LocaleList.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/Looper.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/Message.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/MessageQueue.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/Messenger.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/PersistableBundle.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/os/UserHandle.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/util/AttributeSet.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/util/DisplayMetrics.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/util/Printer.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/util/Size.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/util/SizeF.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/util/SparseArray.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/util/SparseBooleanArray.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/util/TypedValue.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/view/Display.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/view/DisplayCutout.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/org/xmlpull/v1/XmlPullParser.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/org/xmlpull/v1/XmlSerializer.java diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index 0999c952898..a7f0a875a22 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -242,7 +242,7 @@ private class TaintPropagationModels extends SummaryModelCsv { [ "Array", "ArrayList", "Boolean", "Bundle", "Byte", "Double", "FileDescriptor", "Float", "HashMap", "Int", "Long", "Parcelable", "ParcelableArray", "PersistableBundle", - "Serializable", "Size", "SizeF", "SparseArray", "SparseBolleanArray", "String", + "Serializable", "Size", "SizeF", "SparseArray", "SparseBooleanArray", "String", "StrongBinder", "TypedObject", "Value" ] + ";;;Argument[-1];ReturnValue;taint" or diff --git a/java/ql/test/library-tests/frameworks/android/flow-steps/Test.java b/java/ql/test/library-tests/frameworks/android/flow-steps/Test.java new file mode 100644 index 00000000000..b8f7e910c02 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/flow-steps/Test.java @@ -0,0 +1,824 @@ +package generatedtest; + +import android.content.Intent; +import android.os.BaseBundle; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; +import android.os.PersistableBundle; +import android.util.Size; +import android.util.SizeF; +import android.util.SparseArray; +import android.util.SparseBooleanArray; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { return null; } + void sink(Object o) { } + + public void test() throws Exception { + + { + // "android.content;Intent;true;getBooleanArrayExtra;;;Argument[-1];ReturnValue;taint" + boolean[] out = null; + Intent in = (Intent)source(); + out = in.getBooleanArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getBooleanExtra;;;Argument[-1];ReturnValue;taint" + boolean out = false; + Intent in = (Intent)source(); + out = in.getBooleanExtra(null, false); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getBundleExtra;;;Argument[-1];ReturnValue;taint" + Bundle out = null; + Intent in = (Intent)source(); + out = in.getBundleExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getByteArrayExtra;;;Argument[-1];ReturnValue;taint" + byte[] out = null; + Intent in = (Intent)source(); + out = in.getByteArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getByteExtra;;;Argument[-1];ReturnValue;taint" + byte out = 0; + Intent in = (Intent)source(); + out = in.getByteExtra(null, (byte)0); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getCharArrayExtra;;;Argument[-1];ReturnValue;taint" + char[] out = null; + Intent in = (Intent)source(); + out = in.getCharArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getCharExtra;;;Argument[-1];ReturnValue;taint" + char out = 'a'; + Intent in = (Intent)source(); + out = in.getCharExtra(null, 'a'); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getCharSequenceArrayExtra;;;Argument[-1];ReturnValue;taint" + CharSequence[] out = null; + Intent in = (Intent)source(); + out = in.getCharSequenceArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Intent in = (Intent)source(); + out = in.getCharSequenceArrayListExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getCharSequenceExtra;;;Argument[-1];ReturnValue;taint" + CharSequence out = null; + Intent in = (Intent)source(); + out = in.getCharSequenceExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getDoubleArrayExtra;;;Argument[-1];ReturnValue;taint" + double[] out = null; + Intent in = (Intent)source(); + out = in.getDoubleArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getDoubleExtra;;;Argument[-1];ReturnValue;taint" + double out = 0.0; + Intent in = (Intent)source(); + out = in.getDoubleExtra(null, 0.0); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getExtras;;;Argument[-1];ReturnValue;taint" + Bundle out = null; + Intent in = (Intent)source(); + out = in.getExtras(); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getFloatArrayExtra;;;Argument[-1];ReturnValue;taint" + float[] out = null; + Intent in = (Intent)source(); + out = in.getFloatArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getFloatExtra;;;Argument[-1];ReturnValue;taint" + float out = 0.0f; + Intent in = (Intent)source(); + out = in.getFloatExtra(null, 0.0f); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getIntArrayExtra;;;Argument[-1];ReturnValue;taint" + int[] out = null; + Intent in = (Intent)source(); + out = in.getIntArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getIntExtra;;;Argument[-1];ReturnValue;taint" + int out = 0; + Intent in = (Intent)source(); + out = in.getIntExtra(null, 0); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getIntegerArrayListExtra;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Intent in = (Intent)source(); + out = in.getIntegerArrayListExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getLongArrayExtra;;;Argument[-1];ReturnValue;taint" + long[] out = null; + Intent in = (Intent)source(); + out = in.getLongArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getLongExtra;;;Argument[-1];ReturnValue;taint" + long out = 0L; + Intent in = (Intent)source(); + out = in.getLongExtra(null, 0L); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getParcelableArrayExtra;;;Argument[-1];ReturnValue;taint" + Parcelable[] out = null; + Intent in = (Intent)source(); + out = in.getParcelableArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getParcelableArrayListExtra;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Intent in = (Intent)source(); + out = in.getParcelableArrayListExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getParcelableExtra;;;Argument[-1];ReturnValue;taint" + Parcelable out = null; + Intent in = (Intent)source(); + out = in.getParcelableExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getSerializableExtra;;;Argument[-1];ReturnValue;taint" + Serializable out = null; + Intent in = (Intent)source(); + out = in.getSerializableExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getShortArrayExtra;;;Argument[-1];ReturnValue;taint" + short[] out = null; + Intent in = (Intent)source(); + out = in.getShortArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getShortExtra;;;Argument[-1];ReturnValue;taint" + short out = 0; + Intent in = (Intent)source(); + out = in.getShortExtra(null, (short)0); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getStringArrayExtra;;;Argument[-1];ReturnValue;taint" + String[] out = null; + Intent in = (Intent)source(); + out = in.getStringArrayExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getStringArrayListExtra;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Intent in = (Intent)source(); + out = in.getStringArrayListExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.content;Intent;true;getStringExtra;;;Argument[-1];ReturnValue;taint" + String out = null; + Intent in = (Intent)source(); + out = in.getStringExtra(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getBoolean;;;Argument[-1];ReturnValue;taint" + boolean out = false; + BaseBundle in = (BaseBundle)source(); + out = in.getBoolean(null, false); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getBoolean;;;Argument[-1];ReturnValue;taint" + boolean out = false; + BaseBundle in = (BaseBundle)source(); + out = in.getBoolean(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getBooleanArray;;;Argument[-1];ReturnValue;taint" + boolean[] out = null; + BaseBundle in = (BaseBundle)source(); + out = in.getBooleanArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getDouble;;;Argument[-1];ReturnValue;taint" + double out = 0.0; + BaseBundle in = (BaseBundle)source(); + out = in.getDouble(null, 0.0); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getDouble;;;Argument[-1];ReturnValue;taint" + double out = 0.0; + BaseBundle in = (BaseBundle)source(); + out = in.getDouble(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getDoubleArray;;;Argument[-1];ReturnValue;taint" + double[] out = null; + BaseBundle in = (BaseBundle)source(); + out = in.getDoubleArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getInt;;;Argument[-1];ReturnValue;taint" + int out = 0; + BaseBundle in = (BaseBundle)source(); + out = in.getInt(null, 0); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getInt;;;Argument[-1];ReturnValue;taint" + int out = 0; + BaseBundle in = (BaseBundle)source(); + out = in.getInt(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getIntArray;;;Argument[-1];ReturnValue;taint" + int[] out = null; + BaseBundle in = (BaseBundle)source(); + out = in.getIntArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getLong;;;Argument[-1];ReturnValue;taint" + long out = 0L; + BaseBundle in = (BaseBundle)source(); + out = in.getLong(null, 0L); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getLong;;;Argument[-1];ReturnValue;taint" + long out = 0L; + BaseBundle in = (BaseBundle)source(); + out = in.getLong(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getLongArray;;;Argument[-1];ReturnValue;taint" + long[] out = null; + BaseBundle in = (BaseBundle)source(); + out = in.getLongArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getString;;;Argument[-1];ReturnValue;taint" + String out = null; + BaseBundle in = (BaseBundle)source(); + out = in.getString(null, null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getString;;;Argument[-1];ReturnValue;taint" + String out = null; + BaseBundle in = (BaseBundle)source(); + out = in.getString(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;BaseBundle;true;getStringArray;;;Argument[-1];ReturnValue;taint" + String[] out = null; + BaseBundle in = (BaseBundle)source(); + out = in.getStringArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getBinder;;;Argument[-1];ReturnValue;taint" + IBinder out = null; + Bundle in = (Bundle)source(); + out = in.getBinder(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getBundle;;;Argument[-1];ReturnValue;taint" + Bundle out = null; + Bundle in = (Bundle)source(); + out = in.getBundle(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getByte;;;Argument[-1];ReturnValue;taint" + byte out = 0; + Bundle in = (Bundle)source(); + out = in.getByte(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getByte;;;Argument[-1];ReturnValue;taint" + byte out = 0; + Bundle in = (Bundle)source(); + out = in.getByte(null, (byte)0); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getByteArray;;;Argument[-1];ReturnValue;taint" + byte[] out = null; + Bundle in = (Bundle)source(); + out = in.getByteArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getChar;;;Argument[-1];ReturnValue;taint" + char out = 'a'; + Bundle in = (Bundle)source(); + out = in.getChar(null, 'a'); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getChar;;;Argument[-1];ReturnValue;taint" + char out = 'a'; + Bundle in = (Bundle)source(); + out = in.getChar(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getCharArray;;;Argument[-1];ReturnValue;taint" + char[] out = null; + Bundle in = (Bundle)source(); + out = in.getCharArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getCharSequence;;;Argument[-1];ReturnValue;taint" + CharSequence out = null; + Bundle in = (Bundle)source(); + out = in.getCharSequence(null, null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getCharSequence;;;Argument[-1];ReturnValue;taint" + CharSequence out = null; + Bundle in = (Bundle)source(); + out = in.getCharSequence(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getCharSequenceArray;;;Argument[-1];ReturnValue;taint" + CharSequence[] out = null; + Bundle in = (Bundle)source(); + out = in.getCharSequenceArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getCharSequenceArrayList;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Bundle in = (Bundle)source(); + out = in.getCharSequenceArrayList(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getFloat;;;Argument[-1];ReturnValue;taint" + float out = 0.0f; + Bundle in = (Bundle)source(); + out = in.getFloat(null, 0.0f); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getFloat;;;Argument[-1];ReturnValue;taint" + float out = 0.0f; + Bundle in = (Bundle)source(); + out = in.getFloat(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getFloatArray;;;Argument[-1];ReturnValue;taint" + float[] out = null; + Bundle in = (Bundle)source(); + out = in.getFloatArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getIntegerArrayList;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Bundle in = (Bundle)source(); + out = in.getIntegerArrayList(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getParcelable;;;Argument[-1];ReturnValue;taint" + Parcelable out = null; + Bundle in = (Bundle)source(); + out = in.getParcelable(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getParcelableArray;;;Argument[-1];ReturnValue;taint" + Parcelable[] out = null; + Bundle in = (Bundle)source(); + out = in.getParcelableArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getParcelableArrayList;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Bundle in = (Bundle)source(); + out = in.getParcelableArrayList(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getSerializable;;;Argument[-1];ReturnValue;taint" + Serializable out = null; + Bundle in = (Bundle)source(); + out = in.getSerializable(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getShort;;;Argument[-1];ReturnValue;taint" + short out = 0; + Bundle in = (Bundle)source(); + out = in.getShort(null, (short)0); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getShort;;;Argument[-1];ReturnValue;taint" + short out = 0; + Bundle in = (Bundle)source(); + out = in.getShort(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getShortArray;;;Argument[-1];ReturnValue;taint" + short[] out = null; + Bundle in = (Bundle)source(); + out = in.getShortArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getSize;;;Argument[-1];ReturnValue;taint" + Size out = null; + Bundle in = (Bundle)source(); + out = in.getSize(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getSizeF;;;Argument[-1];ReturnValue;taint" + SizeF out = null; + Bundle in = (Bundle)source(); + out = in.getSizeF(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getSparseParcelableArray;;;Argument[-1];ReturnValue;taint" + SparseArray out = null; + Bundle in = (Bundle)source(); + out = in.getSparseParcelableArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Bundle;true;getStringArrayList;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Bundle in = (Bundle)source(); + out = in.getStringArrayList(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readArray;;;Argument[-1];ReturnValue;taint" + Object[] out = null; + Parcel in = (Parcel)source(); + out = in.readArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readArrayList;;;Argument[-1];ReturnValue;taint" + ArrayList out = null; + Parcel in = (Parcel)source(); + out = in.readArrayList(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readBinderArray;;;Argument[-1];Argument[0];taint" + IBinder[] out = null; + Parcel in = (Parcel)source(); + in.readBinderArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readBinderList;;;Argument[-1];Argument[0];taint" + List out = null; + Parcel in = (Parcel)source(); + in.readBinderList(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readBoolean;;;Argument[-1];ReturnValue;taint" + boolean out = false; + Parcel in = (Parcel)source(); + out = in.readBoolean(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readBooleanArray;;;Argument[-1];Argument[0];taint" + boolean[] out = null; + Parcel in = (Parcel)source(); + in.readBooleanArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readBundle;;;Argument[-1];ReturnValue;taint" + Bundle out = null; + Parcel in = (Parcel)source(); + out = in.readBundle(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readBundle;;;Argument[-1];ReturnValue;taint" + Bundle out = null; + Parcel in = (Parcel)source(); + out = in.readBundle(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readByte;;;Argument[-1];ReturnValue;taint" + byte out = 0; + Parcel in = (Parcel)source(); + out = in.readByte(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readByteArray;;;Argument[-1];Argument[0];taint" + byte[] out = null; + Parcel in = (Parcel)source(); + in.readByteArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readCharArray;;;Argument[-1];Argument[0];taint" + char[] out = null; + Parcel in = (Parcel)source(); + in.readCharArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readDouble;;;Argument[-1];ReturnValue;taint" + double out = 0.0; + Parcel in = (Parcel)source(); + out = in.readDouble(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readDoubleArray;;;Argument[-1];Argument[0];taint" + double[] out = null; + Parcel in = (Parcel)source(); + in.readDoubleArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readFileDescriptor;;;Argument[-1];ReturnValue;taint" + ParcelFileDescriptor out = null; + Parcel in = (Parcel)source(); + out = in.readFileDescriptor(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readFloat;;;Argument[-1];ReturnValue;taint" + float out = 0.0f; + Parcel in = (Parcel)source(); + out = in.readFloat(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readFloatArray;;;Argument[-1];Argument[0];taint" + float[] out = null; + Parcel in = (Parcel)source(); + in.readFloatArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readHashMap;;;Argument[-1];ReturnValue;taint" + HashMap out = null; + Parcel in = (Parcel)source(); + out = in.readHashMap(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readInt;;;Argument[-1];ReturnValue;taint" + int out = 0; + Parcel in = (Parcel)source(); + out = in.readInt(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readIntArray;;;Argument[-1];Argument[0];taint" + int[] out = null; + Parcel in = (Parcel)source(); + in.readIntArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readList;;;Argument[-1];Argument[0];taint" + List out = null; + Parcel in = (Parcel)source(); + in.readList(out, null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readLong;;;Argument[-1];ReturnValue;taint" + long out = 0L; + Parcel in = (Parcel)source(); + out = in.readLong(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readLongArray;;;Argument[-1];Argument[0];taint" + long[] out = null; + Parcel in = (Parcel)source(); + in.readLongArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readMap;;;Argument[-1];Argument[0];taint" + Map out = null; + Parcel in = (Parcel)source(); + in.readMap(out, null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readParcelable;;;Argument[-1];ReturnValue;taint" + Parcelable out = null; + Parcel in = (Parcel)source(); + out = in.readParcelable(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readParcelableArray;;;Argument[-1];ReturnValue;taint" + Parcelable[] out = null; + Parcel in = (Parcel)source(); + out = in.readParcelableArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readParcelableList;;;Argument[-1];Argument[0];taint" + List out = null; + Parcel in = (Parcel)source(); + in.readParcelableList(out, null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readParcelableList;;;Argument[0];ReturnValue;value" + List out = null; + List in = (List)source(); + Parcel instance = null; + out = instance.readParcelableList(in, null); + sink(out); // $ hasValueFlow + } + { + // "android.os;Parcel;false;readPersistableBundle;;;Argument[-1];ReturnValue;taint" + PersistableBundle out = null; + Parcel in = (Parcel)source(); + out = in.readPersistableBundle(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readPersistableBundle;;;Argument[-1];ReturnValue;taint" + PersistableBundle out = null; + Parcel in = (Parcel)source(); + out = in.readPersistableBundle(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readSerializable;;;Argument[-1];ReturnValue;taint" + Serializable out = null; + Parcel in = (Parcel)source(); + out = in.readSerializable(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readSize;;;Argument[-1];ReturnValue;taint" + Size out = null; + Parcel in = (Parcel)source(); + out = in.readSize(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readSizeF;;;Argument[-1];ReturnValue;taint" + SizeF out = null; + Parcel in = (Parcel)source(); + out = in.readSizeF(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readSparseArray;;;Argument[-1];ReturnValue;taint" + SparseArray out = null; + Parcel in = (Parcel)source(); + out = in.readSparseArray(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readSparseBooleanArray;;;Argument[-1];ReturnValue;taint" + SparseBooleanArray out = null; + Parcel in = (Parcel)source(); + out = in.readSparseBooleanArray(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readString;;;Argument[-1];ReturnValue;taint" + String out = null; + Parcel in = (Parcel)source(); + out = in.readString(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readStringArray;;;Argument[-1];Argument[0];taint" + String[] out = null; + Parcel in = (Parcel)source(); + in.readStringArray(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readStringList;;;Argument[-1];Argument[0];taint" + List out = null; + Parcel in = (Parcel)source(); + in.readStringList(out); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readStrongBinder;;;Argument[-1];ReturnValue;taint" + IBinder out = null; + Parcel in = (Parcel)source(); + out = in.readStrongBinder(); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readTypedArray;;;Argument[-1];Argument[0];taint" + Object[] out = null; + Parcel in = (Parcel)source(); + in.readTypedArray(out, null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readTypedList;;;Argument[-1];Argument[0];taint" + List out = null; + Parcel in = (Parcel)source(); + in.readTypedList(out, null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readTypedObject;;;Argument[-1];ReturnValue;taint" + Object out = null; + Parcel in = (Parcel)source(); + out = in.readTypedObject(null); + sink(out); // $ hasTaintFlow + } + { + // "android.os;Parcel;false;readValue;;;Argument[-1];ReturnValue;taint" + Object out = null; + Parcel in = (Parcel)source(); + out = in.readValue(null); + sink(out); // $ hasTaintFlow + } + + } + +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/android/flow-steps/options b/java/ql/test/library-tests/frameworks/android/flow-steps/options new file mode 100644 index 00000000000..33cdc1ea940 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/flow-steps/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/library-tests/frameworks/android/flow-steps/test.expected b/java/ql/test/library-tests/frameworks/android/flow-steps/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/android/flow-steps/test.ql b/java/ql/test/library-tests/frameworks/android/flow-steps/test.ql new file mode 100644 index 00000000000..465161863cc --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/flow-steps/test.ql @@ -0,0 +1,53 @@ +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.ExternalFlow +import semmle.code.java.dataflow.TaintTracking +import TestUtilities.InlineExpectationsTest + +class ValueFlowConf extends DataFlow::Configuration { + ValueFlowConf() { this = "qltest:valueFlowConf" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().hasName("sink") + } +} + +class TaintFlowConf extends TaintTracking::Configuration { + TaintFlowConf() { this = "qltest:taintFlowConf" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().hasName("sink") + } +} + +class HasFlowTest extends InlineExpectationsTest { + HasFlowTest() { this = "HasFlowTest" } + + override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, ValueFlowConf conf | conf.hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + or + tag = "hasTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, TaintFlowConf conf | + conf.hasFlow(src, sink) and not any(ValueFlowConf c).hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/accounts/Account.java b/java/ql/test/stubs/google-android-9.0.0/android/accounts/Account.java new file mode 100644 index 00000000000..806f076452e --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/accounts/Account.java @@ -0,0 +1,21 @@ +// Generated automatically from android.accounts.Account for testing purposes + +package android.accounts; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Account implements Parcelable +{ + protected Account() {} + public Account(Parcel p0){} + public Account(String p0, String p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final String name = null; + public final String type = null; + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<Account> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/CharArrayBuffer.java b/java/ql/test/stubs/google-android-9.0.0/android/database/CharArrayBuffer.java new file mode 100644 index 00000000000..b75eff88239 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/CharArrayBuffer.java @@ -0,0 +1,13 @@ +// Generated automatically from android.database.CharArrayBuffer for testing purposes + +package android.database; + + +public class CharArrayBuffer +{ + protected CharArrayBuffer() {} + public CharArrayBuffer(char[] p0){} + public CharArrayBuffer(int p0){} + public char[] data = null; + public int sizeCopied = 0; +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/ContentObserver.java b/java/ql/test/stubs/google-android-9.0.0/android/database/ContentObserver.java new file mode 100644 index 00000000000..4ba6000e93d --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/ContentObserver.java @@ -0,0 +1,17 @@ +// Generated automatically from android.database.ContentObserver for testing purposes + +package android.database; + +import android.net.Uri; +import android.os.Handler; + +abstract public class ContentObserver +{ + protected ContentObserver() {} + public ContentObserver(Handler p0){} + public boolean deliverSelfNotifications(){ return false; } + public final void dispatchChange(boolean p0){} + public final void dispatchChange(boolean p0, Uri p1){} + public void onChange(boolean p0){} + public void onChange(boolean p0, Uri p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/DataSetObserver.java b/java/ql/test/stubs/google-android-9.0.0/android/database/DataSetObserver.java new file mode 100644 index 00000000000..6ca449b2e95 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/DataSetObserver.java @@ -0,0 +1,11 @@ +// Generated automatically from android.database.DataSetObserver for testing purposes + +package android.database; + + +abstract public class DataSetObserver +{ + public DataSetObserver(){} + public void onChanged(){} + public void onInvalidated(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/DatabaseErrorHandler.java b/java/ql/test/stubs/google-android-9.0.0/android/database/DatabaseErrorHandler.java new file mode 100644 index 00000000000..c52eb9698a7 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/DatabaseErrorHandler.java @@ -0,0 +1,10 @@ +// Generated automatically from android.database.DatabaseErrorHandler for testing purposes + +package android.database; + +import android.database.sqlite.SQLiteDatabase; + +public interface DatabaseErrorHandler +{ + void onCorruption(SQLiteDatabase p0); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteClosable.java b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteClosable.java new file mode 100644 index 00000000000..8295e8d0d61 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteClosable.java @@ -0,0 +1,16 @@ +// Generated automatically from android.database.sqlite.SQLiteClosable for testing purposes + +package android.database.sqlite; + +import java.io.Closeable; + +abstract public class SQLiteClosable implements Closeable +{ + protected abstract void onAllReferencesReleased(); + protected void onAllReferencesReleasedFromContainer(){} + public SQLiteClosable(){} + public void acquireReference(){} + public void close(){} + public void releaseReference(){} + public void releaseReferenceFromContainer(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteCursorDriver.java b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteCursorDriver.java new file mode 100644 index 00000000000..3d5cb99a2d0 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteCursorDriver.java @@ -0,0 +1,15 @@ +// Generated automatically from android.database.sqlite.SQLiteCursorDriver for testing purposes + +package android.database.sqlite; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +public interface SQLiteCursorDriver +{ + Cursor query(SQLiteDatabase.CursorFactory p0, String[] p1); + void cursorClosed(); + void cursorDeactivated(); + void cursorRequeried(Cursor p0); + void setBindArguments(String[] p0); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteDatabase.java b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteDatabase.java new file mode 100644 index 00000000000..5e6895f0c53 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteDatabase.java @@ -0,0 +1,122 @@ +// Generated automatically from android.database.sqlite.SQLiteDatabase for testing purposes + +package android.database.sqlite; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.DatabaseErrorHandler; +import android.database.sqlite.SQLiteClosable; +import android.database.sqlite.SQLiteCursorDriver; +import android.database.sqlite.SQLiteQuery; +import android.database.sqlite.SQLiteStatement; +import android.database.sqlite.SQLiteTransactionListener; +import android.os.CancellationSignal; +import android.util.Pair; +import java.io.File; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +public class SQLiteDatabase extends SQLiteClosable +{ + protected SQLiteDatabase() {} + protected void finalize(){} + protected void onAllReferencesReleased(){} + public Cursor query(String p0, String[] p1, String p2, String[] p3, String p4, String p5, String p6){ return null; } + public Cursor query(String p0, String[] p1, String p2, String[] p3, String p4, String p5, String p6, String p7){ return null; } + public Cursor query(boolean p0, String p1, String[] p2, String p3, String[] p4, String p5, String p6, String p7, String p8){ return null; } + public Cursor query(boolean p0, String p1, String[] p2, String p3, String[] p4, String p5, String p6, String p7, String p8, CancellationSignal p9){ return null; } + public Cursor queryWithFactory(SQLiteDatabase.CursorFactory p0, boolean p1, String p2, String[] p3, String p4, String[] p5, String p6, String p7, String p8, String p9){ return null; } + public Cursor queryWithFactory(SQLiteDatabase.CursorFactory p0, boolean p1, String p2, String[] p3, String p4, String[] p5, String p6, String p7, String p8, String p9, CancellationSignal p10){ return null; } + public Cursor rawQuery(String p0, String[] p1){ return null; } + public Cursor rawQuery(String p0, String[] p1, CancellationSignal p2){ return null; } + public Cursor rawQueryWithFactory(SQLiteDatabase.CursorFactory p0, String p1, String[] p2, String p3){ return null; } + public Cursor rawQueryWithFactory(SQLiteDatabase.CursorFactory p0, String p1, String[] p2, String p3, CancellationSignal p4){ return null; } + public List<Pair<String, String>> getAttachedDbs(){ return null; } + public Map<String, String> getSyncedTables(){ return null; } + public SQLiteStatement compileStatement(String p0){ return null; } + public String getPath(){ return null; } + public String toString(){ return null; } + public boolean enableWriteAheadLogging(){ return false; } + public boolean inTransaction(){ return false; } + public boolean isDatabaseIntegrityOk(){ return false; } + public boolean isDbLockedByCurrentThread(){ return false; } + public boolean isDbLockedByOtherThreads(){ return false; } + public boolean isOpen(){ return false; } + public boolean isReadOnly(){ return false; } + public boolean isWriteAheadLoggingEnabled(){ return false; } + public boolean needUpgrade(int p0){ return false; } + public boolean yieldIfContended(){ return false; } + public boolean yieldIfContendedSafely(){ return false; } + public boolean yieldIfContendedSafely(long p0){ return false; } + public int delete(String p0, String p1, String[] p2){ return 0; } + public int getVersion(){ return 0; } + public int update(String p0, ContentValues p1, String p2, String[] p3){ return 0; } + public int updateWithOnConflict(String p0, ContentValues p1, String p2, String[] p3, int p4){ return 0; } + public long getMaximumSize(){ return 0; } + public long getPageSize(){ return 0; } + public long insert(String p0, String p1, ContentValues p2){ return 0; } + public long insertOrThrow(String p0, String p1, ContentValues p2){ return 0; } + public long insertWithOnConflict(String p0, String p1, ContentValues p2, int p3){ return 0; } + public long replace(String p0, String p1, ContentValues p2){ return 0; } + public long replaceOrThrow(String p0, String p1, ContentValues p2){ return 0; } + public long setMaximumSize(long p0){ return 0; } + public static SQLiteDatabase create(SQLiteDatabase.CursorFactory p0){ return null; } + public static SQLiteDatabase createInMemory(SQLiteDatabase.OpenParams p0){ return null; } + public static SQLiteDatabase openDatabase(File p0, SQLiteDatabase.OpenParams p1){ return null; } + public static SQLiteDatabase openDatabase(String p0, SQLiteDatabase.CursorFactory p1, int p2){ return null; } + public static SQLiteDatabase openDatabase(String p0, SQLiteDatabase.CursorFactory p1, int p2, DatabaseErrorHandler p3){ return null; } + public static SQLiteDatabase openOrCreateDatabase(File p0, SQLiteDatabase.CursorFactory p1){ return null; } + public static SQLiteDatabase openOrCreateDatabase(String p0, SQLiteDatabase.CursorFactory p1){ return null; } + public static SQLiteDatabase openOrCreateDatabase(String p0, SQLiteDatabase.CursorFactory p1, DatabaseErrorHandler p2){ return null; } + public static String findEditTable(String p0){ return null; } + public static boolean deleteDatabase(File p0){ return false; } + public static int CONFLICT_ABORT = 0; + public static int CONFLICT_FAIL = 0; + public static int CONFLICT_IGNORE = 0; + public static int CONFLICT_NONE = 0; + public static int CONFLICT_REPLACE = 0; + public static int CONFLICT_ROLLBACK = 0; + public static int CREATE_IF_NECESSARY = 0; + public static int ENABLE_WRITE_AHEAD_LOGGING = 0; + public static int MAX_SQL_CACHE_SIZE = 0; + public static int NO_LOCALIZED_COLLATORS = 0; + public static int OPEN_READONLY = 0; + public static int OPEN_READWRITE = 0; + public static int SQLITE_MAX_LIKE_PATTERN_LENGTH = 0; + public static int releaseMemory(){ return 0; } + public void beginTransaction(){} + public void beginTransactionNonExclusive(){} + public void beginTransactionWithListener(SQLiteTransactionListener p0){} + public void beginTransactionWithListenerNonExclusive(SQLiteTransactionListener p0){} + public void disableWriteAheadLogging(){} + public void endTransaction(){} + public void execSQL(String p0){} + public void execSQL(String p0, Object[] p1){} + public void markTableSyncable(String p0, String p1){} + public void markTableSyncable(String p0, String p1, String p2){} + public void setForeignKeyConstraintsEnabled(boolean p0){} + public void setLocale(Locale p0){} + public void setLockingEnabled(boolean p0){} + public void setMaxSqlCacheSize(int p0){} + public void setPageSize(long p0){} + public void setTransactionSuccessful(){} + public void setVersion(int p0){} + public void validateSql(String p0, CancellationSignal p1){} + static public class OpenParams + { + protected OpenParams() {} + public DatabaseErrorHandler getErrorHandler(){ return null; } + public SQLiteDatabase.CursorFactory getCursorFactory(){ return null; } + public String getJournalMode(){ return null; } + public String getSynchronousMode(){ return null; } + public int getLookasideSlotCount(){ return 0; } + public int getLookasideSlotSize(){ return 0; } + public int getOpenFlags(){ return 0; } + public long getIdleConnectionTimeout(){ return 0; } + } + static public interface CursorFactory + { + Cursor newCursor(SQLiteDatabase p0, SQLiteCursorDriver p1, String p2, SQLiteQuery p3); + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteProgram.java b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteProgram.java new file mode 100644 index 00000000000..ca78c8d99f6 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteProgram.java @@ -0,0 +1,19 @@ +// Generated automatically from android.database.sqlite.SQLiteProgram for testing purposes + +package android.database.sqlite; + +import android.database.sqlite.SQLiteClosable; + +abstract public class SQLiteProgram extends SQLiteClosable +{ + protected SQLiteProgram() {} + protected void onAllReferencesReleased(){} + public final int getUniqueId(){ return 0; } + public void bindAllArgsAsStrings(String[] p0){} + public void bindBlob(int p0, byte[] p1){} + public void bindDouble(int p0, double p1){} + public void bindLong(int p0, long p1){} + public void bindNull(int p0){} + public void bindString(int p0, String p1){} + public void clearBindings(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteQuery.java b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteQuery.java new file mode 100644 index 00000000000..80ff0c84998 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteQuery.java @@ -0,0 +1,11 @@ +// Generated automatically from android.database.sqlite.SQLiteQuery for testing purposes + +package android.database.sqlite; + +import android.database.sqlite.SQLiteProgram; + +public class SQLiteQuery extends SQLiteProgram +{ + protected SQLiteQuery() {} + public String toString(){ return null; } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteStatement.java b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteStatement.java new file mode 100644 index 00000000000..d7b96baf0f3 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteStatement.java @@ -0,0 +1,18 @@ +// Generated automatically from android.database.sqlite.SQLiteStatement for testing purposes + +package android.database.sqlite; + +import android.database.sqlite.SQLiteProgram; +import android.os.ParcelFileDescriptor; + +public class SQLiteStatement extends SQLiteProgram +{ + protected SQLiteStatement() {} + public ParcelFileDescriptor simpleQueryForBlobFileDescriptor(){ return null; } + public String simpleQueryForString(){ return null; } + public String toString(){ return null; } + public int executeUpdateDelete(){ return 0; } + public long executeInsert(){ return 0; } + public long simpleQueryForLong(){ return 0; } + public void execute(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteTransactionListener.java b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteTransactionListener.java new file mode 100644 index 00000000000..31895691b11 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/database/sqlite/SQLiteTransactionListener.java @@ -0,0 +1,11 @@ +// Generated automatically from android.database.sqlite.SQLiteTransactionListener for testing purposes + +package android.database.sqlite; + + +public interface SQLiteTransactionListener +{ + void onBegin(); + void onCommit(); + void onRollback(); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Bitmap.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Bitmap.java new file mode 100644 index 00000000000..991895a6ed3 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Bitmap.java @@ -0,0 +1,97 @@ +// Generated automatically from android.graphics.Bitmap for testing purposes + +package android.graphics; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorSpace; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Picture; +import android.hardware.HardwareBuffer; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DisplayMetrics; +import java.io.OutputStream; +import java.nio.Buffer; + +public class Bitmap implements Parcelable +{ + public Bitmap copy(Bitmap.Config p0, boolean p1){ return null; } + public Bitmap extractAlpha(){ return null; } + public Bitmap extractAlpha(Paint p0, int[] p1){ return null; } + public Bitmap.Config getConfig(){ return null; } + public Color getColor(int p0, int p1){ return null; } + public ColorSpace getColorSpace(){ return null; } + public boolean compress(Bitmap.CompressFormat p0, int p1, OutputStream p2){ return false; } + public boolean hasAlpha(){ return false; } + public boolean hasMipMap(){ return false; } + public boolean isMutable(){ return false; } + public boolean isPremultiplied(){ return false; } + public boolean isRecycled(){ return false; } + public boolean sameAs(Bitmap p0){ return false; } + public byte[] getNinePatchChunk(){ return null; } + public int describeContents(){ return 0; } + public int getAllocationByteCount(){ return 0; } + public int getByteCount(){ return 0; } + public int getDensity(){ return 0; } + public int getGenerationId(){ return 0; } + public int getHeight(){ return 0; } + public int getPixel(int p0, int p1){ return 0; } + public int getRowBytes(){ return 0; } + public int getScaledHeight(Canvas p0){ return 0; } + public int getScaledHeight(DisplayMetrics p0){ return 0; } + public int getScaledHeight(int p0){ return 0; } + public int getScaledWidth(Canvas p0){ return 0; } + public int getScaledWidth(DisplayMetrics p0){ return 0; } + public int getScaledWidth(int p0){ return 0; } + public int getWidth(){ return 0; } + public static Bitmap createBitmap(Bitmap p0){ return null; } + public static Bitmap createBitmap(Bitmap p0, int p1, int p2, int p3, int p4){ return null; } + public static Bitmap createBitmap(Bitmap p0, int p1, int p2, int p3, int p4, Matrix p5, boolean p6){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int p1, int p2, Bitmap.Config p3){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int p1, int p2, Bitmap.Config p3, boolean p4){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int p1, int p2, Bitmap.Config p3, boolean p4, ColorSpace p5){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int[] p1, int p2, int p3, Bitmap.Config p4){ return null; } + public static Bitmap createBitmap(DisplayMetrics p0, int[] p1, int p2, int p3, int p4, int p5, Bitmap.Config p6){ return null; } + public static Bitmap createBitmap(Picture p0){ return null; } + public static Bitmap createBitmap(Picture p0, int p1, int p2, Bitmap.Config p3){ return null; } + public static Bitmap createBitmap(int p0, int p1, Bitmap.Config p2){ return null; } + public static Bitmap createBitmap(int p0, int p1, Bitmap.Config p2, boolean p3){ return null; } + public static Bitmap createBitmap(int p0, int p1, Bitmap.Config p2, boolean p3, ColorSpace p4){ return null; } + public static Bitmap createBitmap(int[] p0, int p1, int p2, Bitmap.Config p3){ return null; } + public static Bitmap createBitmap(int[] p0, int p1, int p2, int p3, int p4, Bitmap.Config p5){ return null; } + public static Bitmap createScaledBitmap(Bitmap p0, int p1, int p2, boolean p3){ return null; } + public static Bitmap wrapHardwareBuffer(HardwareBuffer p0, ColorSpace p1){ return null; } + public static Parcelable.Creator<Bitmap> CREATOR = null; + public static int DENSITY_NONE = 0; + public void copyPixelsFromBuffer(Buffer p0){} + public void copyPixelsToBuffer(Buffer p0){} + public void eraseColor(int p0){} + public void eraseColor(long p0){} + public void getPixels(int[] p0, int p1, int p2, int p3, int p4, int p5, int p6){} + public void prepareToDraw(){} + public void reconfigure(int p0, int p1, Bitmap.Config p2){} + public void recycle(){} + public void setColorSpace(ColorSpace p0){} + public void setConfig(Bitmap.Config p0){} + public void setDensity(int p0){} + public void setHasAlpha(boolean p0){} + public void setHasMipMap(boolean p0){} + public void setHeight(int p0){} + public void setPixel(int p0, int p1, int p2){} + public void setPixels(int[] p0, int p1, int p2, int p3, int p4, int p5, int p6){} + public void setPremultiplied(boolean p0){} + public void setWidth(int p0){} + public void writeToParcel(Parcel p0, int p1){} + static public enum CompressFormat + { + JPEG, PNG, WEBP; + private CompressFormat() {} + } + static public enum Config + { + ALPHA_8, ARGB_4444, ARGB_8888, HARDWARE, RGBA_F16, RGB_565; + private Config() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/BitmapFactory.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/BitmapFactory.java new file mode 100644 index 00000000000..f6e05c10de9 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/BitmapFactory.java @@ -0,0 +1,54 @@ +// Generated automatically from android.graphics.BitmapFactory for testing purposes + +package android.graphics; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.ColorSpace; +import android.graphics.Rect; +import android.util.TypedValue; +import java.io.FileDescriptor; +import java.io.InputStream; + +public class BitmapFactory +{ + public BitmapFactory(){} + public static Bitmap decodeByteArray(byte[] p0, int p1, int p2){ return null; } + public static Bitmap decodeByteArray(byte[] p0, int p1, int p2, BitmapFactory.Options p3){ return null; } + public static Bitmap decodeFile(String p0){ return null; } + public static Bitmap decodeFile(String p0, BitmapFactory.Options p1){ return null; } + public static Bitmap decodeFileDescriptor(FileDescriptor p0){ return null; } + public static Bitmap decodeFileDescriptor(FileDescriptor p0, Rect p1, BitmapFactory.Options p2){ return null; } + public static Bitmap decodeResource(Resources p0, int p1){ return null; } + public static Bitmap decodeResource(Resources p0, int p1, BitmapFactory.Options p2){ return null; } + public static Bitmap decodeResourceStream(Resources p0, TypedValue p1, InputStream p2, Rect p3, BitmapFactory.Options p4){ return null; } + public static Bitmap decodeStream(InputStream p0){ return null; } + public static Bitmap decodeStream(InputStream p0, Rect p1, BitmapFactory.Options p2){ return null; } + static public class Options + { + public Bitmap inBitmap = null; + public Bitmap.Config inPreferredConfig = null; + public Bitmap.Config outConfig = null; + public ColorSpace inPreferredColorSpace = null; + public ColorSpace outColorSpace = null; + public Options(){} + public String outMimeType = null; + public boolean inDither = false; + public boolean inInputShareable = false; + public boolean inJustDecodeBounds = false; + public boolean inMutable = false; + public boolean inPreferQualityOverSpeed = false; + public boolean inPremultiplied = false; + public boolean inPurgeable = false; + public boolean inScaled = false; + public boolean mCancel = false; + public byte[] inTempStorage = null; + public int inDensity = 0; + public int inSampleSize = 0; + public int inScreenDensity = 0; + public int inTargetDensity = 0; + public int outHeight = 0; + public int outWidth = 0; + public void requestCancelDecode(){} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/BlendMode.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/BlendMode.java new file mode 100644 index 00000000000..32510e36bdd --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/BlendMode.java @@ -0,0 +1,10 @@ +// Generated automatically from android.graphics.BlendMode for testing purposes + +package android.graphics; + + +public enum BlendMode +{ + CLEAR, COLOR, COLOR_BURN, COLOR_DODGE, DARKEN, DIFFERENCE, DST, DST_ATOP, DST_IN, DST_OUT, DST_OVER, EXCLUSION, HARD_LIGHT, HUE, LIGHTEN, LUMINOSITY, MODULATE, MULTIPLY, OVERLAY, PLUS, SATURATION, SCREEN, SOFT_LIGHT, SRC, SRC_ATOP, SRC_IN, SRC_OUT, SRC_OVER, XOR; + private BlendMode() {} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Canvas.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Canvas.java new file mode 100644 index 00000000000..128cf70d32d --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Canvas.java @@ -0,0 +1,138 @@ +// Generated automatically from android.graphics.Canvas for testing purposes + +package android.graphics; + +import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.DrawFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Picture; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; +import android.graphics.RenderNode; +import android.graphics.text.MeasuredText; + +public class Canvas +{ + public Canvas(){} + public Canvas(Bitmap p0){} + public DrawFilter getDrawFilter(){ return null; } + public boolean clipOutPath(Path p0){ return false; } + public boolean clipOutRect(Rect p0){ return false; } + public boolean clipOutRect(RectF p0){ return false; } + public boolean clipOutRect(float p0, float p1, float p2, float p3){ return false; } + public boolean clipOutRect(int p0, int p1, int p2, int p3){ return false; } + public boolean clipPath(Path p0){ return false; } + public boolean clipPath(Path p0, Region.Op p1){ return false; } + public boolean clipRect(Rect p0){ return false; } + public boolean clipRect(Rect p0, Region.Op p1){ return false; } + public boolean clipRect(RectF p0){ return false; } + public boolean clipRect(RectF p0, Region.Op p1){ return false; } + public boolean clipRect(float p0, float p1, float p2, float p3){ return false; } + public boolean clipRect(float p0, float p1, float p2, float p3, Region.Op p4){ return false; } + public boolean clipRect(int p0, int p1, int p2, int p3){ return false; } + public boolean getClipBounds(Rect p0){ return false; } + public boolean isHardwareAccelerated(){ return false; } + public boolean isOpaque(){ return false; } + public boolean quickReject(Path p0, Canvas.EdgeType p1){ return false; } + public boolean quickReject(RectF p0, Canvas.EdgeType p1){ return false; } + public boolean quickReject(float p0, float p1, float p2, float p3, Canvas.EdgeType p4){ return false; } + public final Matrix getMatrix(){ return null; } + public final Rect getClipBounds(){ return null; } + public final void rotate(float p0, float p1, float p2){} + public final void scale(float p0, float p1, float p2, float p3){} + public int getDensity(){ return 0; } + public int getHeight(){ return 0; } + public int getMaximumBitmapHeight(){ return 0; } + public int getMaximumBitmapWidth(){ return 0; } + public int getSaveCount(){ return 0; } + public int getWidth(){ return 0; } + public int save(){ return 0; } + public int saveLayer(RectF p0, Paint p1){ return 0; } + public int saveLayer(RectF p0, Paint p1, int p2){ return 0; } + public int saveLayer(float p0, float p1, float p2, float p3, Paint p4){ return 0; } + public int saveLayer(float p0, float p1, float p2, float p3, Paint p4, int p5){ return 0; } + public int saveLayerAlpha(RectF p0, int p1){ return 0; } + public int saveLayerAlpha(RectF p0, int p1, int p2){ return 0; } + public int saveLayerAlpha(float p0, float p1, float p2, float p3, int p4){ return 0; } + public int saveLayerAlpha(float p0, float p1, float p2, float p3, int p4, int p5){ return 0; } + public static int ALL_SAVE_FLAG = 0; + public void concat(Matrix p0){} + public void disableZ(){} + public void drawARGB(int p0, int p1, int p2, int p3){} + public void drawArc(RectF p0, float p1, float p2, boolean p3, Paint p4){} + public void drawArc(float p0, float p1, float p2, float p3, float p4, float p5, boolean p6, Paint p7){} + public void drawBitmap(Bitmap p0, Matrix p1, Paint p2){} + public void drawBitmap(Bitmap p0, Rect p1, Rect p2, Paint p3){} + public void drawBitmap(Bitmap p0, Rect p1, RectF p2, Paint p3){} + public void drawBitmap(Bitmap p0, float p1, float p2, Paint p3){} + public void drawBitmap(int[] p0, int p1, int p2, float p3, float p4, int p5, int p6, boolean p7, Paint p8){} + public void drawBitmap(int[] p0, int p1, int p2, int p3, int p4, int p5, int p6, boolean p7, Paint p8){} + public void drawBitmapMesh(Bitmap p0, int p1, int p2, float[] p3, int p4, int[] p5, int p6, Paint p7){} + public void drawCircle(float p0, float p1, float p2, Paint p3){} + public void drawColor(int p0){} + public void drawColor(int p0, BlendMode p1){} + public void drawColor(int p0, PorterDuff.Mode p1){} + public void drawColor(long p0){} + public void drawColor(long p0, BlendMode p1){} + public void drawDoubleRoundRect(RectF p0, float p1, float p2, RectF p3, float p4, float p5, Paint p6){} + public void drawDoubleRoundRect(RectF p0, float[] p1, RectF p2, float[] p3, Paint p4){} + public void drawLine(float p0, float p1, float p2, float p3, Paint p4){} + public void drawLines(float[] p0, Paint p1){} + public void drawLines(float[] p0, int p1, int p2, Paint p3){} + public void drawOval(RectF p0, Paint p1){} + public void drawOval(float p0, float p1, float p2, float p3, Paint p4){} + public void drawPaint(Paint p0){} + public void drawPath(Path p0, Paint p1){} + public void drawPicture(Picture p0){} + public void drawPicture(Picture p0, Rect p1){} + public void drawPicture(Picture p0, RectF p1){} + public void drawPoint(float p0, float p1, Paint p2){} + public void drawPoints(float[] p0, Paint p1){} + public void drawPoints(float[] p0, int p1, int p2, Paint p3){} + public void drawPosText(String p0, float[] p1, Paint p2){} + public void drawPosText(char[] p0, int p1, int p2, float[] p3, Paint p4){} + public void drawRGB(int p0, int p1, int p2){} + public void drawRect(Rect p0, Paint p1){} + public void drawRect(RectF p0, Paint p1){} + public void drawRect(float p0, float p1, float p2, float p3, Paint p4){} + public void drawRenderNode(RenderNode p0){} + public void drawRoundRect(RectF p0, float p1, float p2, Paint p3){} + public void drawRoundRect(float p0, float p1, float p2, float p3, float p4, float p5, Paint p6){} + public void drawText(CharSequence p0, int p1, int p2, float p3, float p4, Paint p5){} + public void drawText(String p0, float p1, float p2, Paint p3){} + public void drawText(String p0, int p1, int p2, float p3, float p4, Paint p5){} + public void drawText(char[] p0, int p1, int p2, float p3, float p4, Paint p5){} + public void drawTextOnPath(String p0, Path p1, float p2, float p3, Paint p4){} + public void drawTextOnPath(char[] p0, int p1, int p2, Path p3, float p4, float p5, Paint p6){} + public void drawTextRun(CharSequence p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public void drawTextRun(MeasuredText p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public void drawTextRun(char[] p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public void drawVertices(Canvas.VertexMode p0, int p1, float[] p2, int p3, float[] p4, int p5, int[] p6, int p7, short[] p8, int p9, int p10, Paint p11){} + public void enableZ(){} + public void getMatrix(Matrix p0){} + public void restore(){} + public void restoreToCount(int p0){} + public void rotate(float p0){} + public void scale(float p0, float p1){} + public void setBitmap(Bitmap p0){} + public void setDensity(int p0){} + public void setDrawFilter(DrawFilter p0){} + public void setMatrix(Matrix p0){} + public void skew(float p0, float p1){} + public void translate(float p0, float p1){} + static public enum EdgeType + { + AA, BW; + private EdgeType() {} + } + static public enum VertexMode + { + TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP; + private VertexMode() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Color.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Color.java new file mode 100644 index 00000000000..45f1e68548c --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Color.java @@ -0,0 +1,80 @@ +// Generated automatically from android.graphics.Color for testing purposes + +package android.graphics; + +import android.graphics.ColorSpace; + +public class Color +{ + public Color convert(ColorSpace p0){ return null; } + public Color(){} + public ColorSpace getColorSpace(){ return null; } + public ColorSpace.Model getModel(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isSrgb(){ return false; } + public boolean isWideGamut(){ return false; } + public float alpha(){ return 0; } + public float blue(){ return 0; } + public float getComponent(int p0){ return 0; } + public float green(){ return 0; } + public float luminance(){ return 0; } + public float red(){ return 0; } + public float[] getComponents(){ return null; } + public float[] getComponents(float[] p0){ return null; } + public int getComponentCount(){ return 0; } + public int hashCode(){ return 0; } + public int toArgb(){ return 0; } + public long pack(){ return 0; } + public static Color valueOf(float p0, float p1, float p2){ return null; } + public static Color valueOf(float p0, float p1, float p2, float p3){ return null; } + public static Color valueOf(float p0, float p1, float p2, float p3, ColorSpace p4){ return null; } + public static Color valueOf(float[] p0, ColorSpace p1){ return null; } + public static Color valueOf(int p0){ return null; } + public static Color valueOf(long p0){ return null; } + public static ColorSpace colorSpace(long p0){ return null; } + public static boolean isInColorSpace(long p0, ColorSpace p1){ return false; } + public static boolean isSrgb(long p0){ return false; } + public static boolean isWideGamut(long p0){ return false; } + public static float alpha(long p0){ return 0; } + public static float blue(long p0){ return 0; } + public static float green(long p0){ return 0; } + public static float luminance(int p0){ return 0; } + public static float luminance(long p0){ return 0; } + public static float red(long p0){ return 0; } + public static int BLACK = 0; + public static int BLUE = 0; + public static int CYAN = 0; + public static int DKGRAY = 0; + public static int GRAY = 0; + public static int GREEN = 0; + public static int HSVToColor(float[] p0){ return 0; } + public static int HSVToColor(int p0, float[] p1){ return 0; } + public static int LTGRAY = 0; + public static int MAGENTA = 0; + public static int RED = 0; + public static int TRANSPARENT = 0; + public static int WHITE = 0; + public static int YELLOW = 0; + public static int alpha(int p0){ return 0; } + public static int argb(float p0, float p1, float p2, float p3){ return 0; } + public static int argb(int p0, int p1, int p2, int p3){ return 0; } + public static int blue(int p0){ return 0; } + public static int green(int p0){ return 0; } + public static int parseColor(String p0){ return 0; } + public static int red(int p0){ return 0; } + public static int rgb(float p0, float p1, float p2){ return 0; } + public static int rgb(int p0, int p1, int p2){ return 0; } + public static int toArgb(long p0){ return 0; } + public static long convert(float p0, float p1, float p2, float p3, ColorSpace p4, ColorSpace p5){ return 0; } + public static long convert(float p0, float p1, float p2, float p3, ColorSpace.Connector p4){ return 0; } + public static long convert(int p0, ColorSpace p1){ return 0; } + public static long convert(long p0, ColorSpace p1){ return 0; } + public static long convert(long p0, ColorSpace.Connector p1){ return 0; } + public static long pack(float p0, float p1, float p2){ return 0; } + public static long pack(float p0, float p1, float p2, float p3){ return 0; } + public static long pack(float p0, float p1, float p2, float p3, ColorSpace p4){ return 0; } + public static long pack(int p0){ return 0; } + public static void RGBToHSV(int p0, int p1, int p2, float[] p3){} + public static void colorToHSV(int p0, float[] p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/ColorFilter.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/ColorFilter.java new file mode 100644 index 00000000000..06a565743de --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/ColorFilter.java @@ -0,0 +1,9 @@ +// Generated automatically from android.graphics.ColorFilter for testing purposes + +package android.graphics; + + +public class ColorFilter +{ + public ColorFilter(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/ColorSpace.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/ColorSpace.java new file mode 100644 index 00000000000..06993b43be5 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/ColorSpace.java @@ -0,0 +1,122 @@ +// Generated automatically from android.graphics.ColorSpace for testing purposes + +package android.graphics; + +import java.util.function.DoubleUnaryOperator; + +abstract public class ColorSpace +{ + protected ColorSpace() {} + public ColorSpace.Model getModel(){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public abstract boolean isWideGamut(); + public abstract float getMaxValue(int p0); + public abstract float getMinValue(int p0); + public abstract float[] fromXyz(float[] p0); + public abstract float[] toXyz(float[] p0); + public boolean equals(Object p0){ return false; } + public boolean isSrgb(){ return false; } + public float[] fromXyz(float p0, float p1, float p2){ return null; } + public float[] toXyz(float p0, float p1, float p2){ return null; } + public int getComponentCount(){ return 0; } + public int getId(){ return 0; } + public int hashCode(){ return 0; } + public static ColorSpace adapt(ColorSpace p0, float[] p1){ return null; } + public static ColorSpace adapt(ColorSpace p0, float[] p1, ColorSpace.Adaptation p2){ return null; } + public static ColorSpace get(ColorSpace.Named p0){ return null; } + public static ColorSpace match(float[] p0, ColorSpace.Rgb.TransferParameters p1){ return null; } + public static ColorSpace.Connector connect(ColorSpace p0){ return null; } + public static ColorSpace.Connector connect(ColorSpace p0, ColorSpace p1){ return null; } + public static ColorSpace.Connector connect(ColorSpace p0, ColorSpace p1, ColorSpace.RenderIntent p2){ return null; } + public static ColorSpace.Connector connect(ColorSpace p0, ColorSpace.RenderIntent p1){ return null; } + public static float[] ILLUMINANT_A = null; + public static float[] ILLUMINANT_B = null; + public static float[] ILLUMINANT_C = null; + public static float[] ILLUMINANT_D50 = null; + public static float[] ILLUMINANT_D55 = null; + public static float[] ILLUMINANT_D60 = null; + public static float[] ILLUMINANT_D65 = null; + public static float[] ILLUMINANT_D75 = null; + public static float[] ILLUMINANT_E = null; + public static int MAX_ID = 0; + public static int MIN_ID = 0; + static public class Connector + { + protected Connector() {} + public ColorSpace getDestination(){ return null; } + public ColorSpace getSource(){ return null; } + public ColorSpace.RenderIntent getRenderIntent(){ return null; } + public float[] transform(float p0, float p1, float p2){ return null; } + public float[] transform(float[] p0){ return null; } + } + static public class Rgb extends ColorSpace + { + protected Rgb() {} + public ColorSpace.Rgb.TransferParameters getTransferParameters(){ return null; } + public DoubleUnaryOperator getEotf(){ return null; } + public DoubleUnaryOperator getOetf(){ return null; } + public Rgb(String p0, float[] p1, ColorSpace.Rgb.TransferParameters p2){} + public Rgb(String p0, float[] p1, DoubleUnaryOperator p2, DoubleUnaryOperator p3){} + public Rgb(String p0, float[] p1, double p2){} + public Rgb(String p0, float[] p1, float[] p2, ColorSpace.Rgb.TransferParameters p3){} + public Rgb(String p0, float[] p1, float[] p2, DoubleUnaryOperator p3, DoubleUnaryOperator p4, float p5, float p6){} + public Rgb(String p0, float[] p1, float[] p2, double p3){} + public boolean equals(Object p0){ return false; } + public boolean isSrgb(){ return false; } + public boolean isWideGamut(){ return false; } + public float getMaxValue(int p0){ return 0; } + public float getMinValue(int p0){ return 0; } + public float[] fromLinear(float p0, float p1, float p2){ return null; } + public float[] fromLinear(float[] p0){ return null; } + public float[] fromXyz(float[] p0){ return null; } + public float[] getInverseTransform(){ return null; } + public float[] getInverseTransform(float[] p0){ return null; } + public float[] getPrimaries(){ return null; } + public float[] getPrimaries(float[] p0){ return null; } + public float[] getTransform(){ return null; } + public float[] getTransform(float[] p0){ return null; } + public float[] getWhitePoint(){ return null; } + public float[] getWhitePoint(float[] p0){ return null; } + public float[] toLinear(float p0, float p1, float p2){ return null; } + public float[] toLinear(float[] p0){ return null; } + public float[] toXyz(float[] p0){ return null; } + public int hashCode(){ return 0; } + static public class TransferParameters + { + protected TransferParameters() {} + public TransferParameters(double p0, double p1, double p2, double p3, double p4){} + public TransferParameters(double p0, double p1, double p2, double p3, double p4, double p5, double p6){} + public boolean equals(Object p0){ return false; } + public final double a = 0; + public final double b = 0; + public final double c = 0; + public final double d = 0; + public final double e = 0; + public final double f = 0; + public final double g = 0; + public int hashCode(){ return 0; } + } + } + static public enum Adaptation + { + BRADFORD, CIECAT02, VON_KRIES; + private Adaptation() {} + } + static public enum Model + { + CMYK, LAB, RGB, XYZ; + private Model() {} + public int getComponentCount(){ return 0; } + } + static public enum Named + { + ACES, ACESCG, ADOBE_RGB, BT2020, BT709, CIE_LAB, CIE_XYZ, DCI_P3, DISPLAY_P3, EXTENDED_SRGB, LINEAR_EXTENDED_SRGB, LINEAR_SRGB, NTSC_1953, PRO_PHOTO_RGB, SMPTE_C, SRGB; + private Named() {} + } + static public enum RenderIntent + { + ABSOLUTE, PERCEPTUAL, RELATIVE, SATURATION; + private RenderIntent() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/DrawFilter.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/DrawFilter.java new file mode 100644 index 00000000000..ed760270a81 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/DrawFilter.java @@ -0,0 +1,10 @@ +// Generated automatically from android.graphics.DrawFilter for testing purposes + +package android.graphics; + + +public class DrawFilter +{ + protected void finalize(){} + public DrawFilter(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Insets.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Insets.java new file mode 100644 index 00000000000..3e61e03cd68 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Insets.java @@ -0,0 +1,29 @@ +// Generated automatically from android.graphics.Insets for testing purposes + +package android.graphics; + +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; + +public class Insets implements Parcelable +{ + protected Insets() {} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final int bottom = 0; + public final int left = 0; + public final int right = 0; + public final int top = 0; + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Insets NONE = null; + public static Insets add(Insets p0, Insets p1){ return null; } + public static Insets max(Insets p0, Insets p1){ return null; } + public static Insets min(Insets p0, Insets p1){ return null; } + public static Insets of(Rect p0){ return null; } + public static Insets of(int p0, int p1, int p2, int p3){ return null; } + public static Insets subtract(Insets p0, Insets p1){ return null; } + public static Parcelable.Creator<Insets> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/MaskFilter.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/MaskFilter.java new file mode 100644 index 00000000000..0355b5c1206 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/MaskFilter.java @@ -0,0 +1,10 @@ +// Generated automatically from android.graphics.MaskFilter for testing purposes + +package android.graphics; + + +public class MaskFilter +{ + protected void finalize(){} + public MaskFilter(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Matrix.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Matrix.java new file mode 100644 index 00000000000..fc003bac004 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Matrix.java @@ -0,0 +1,74 @@ +// Generated automatically from android.graphics.Matrix for testing purposes + +package android.graphics; + +import android.graphics.RectF; + +public class Matrix +{ + public Matrix(){} + public Matrix(Matrix p0){} + public String toShortString(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean invert(Matrix p0){ return false; } + public boolean isAffine(){ return false; } + public boolean isIdentity(){ return false; } + public boolean mapRect(RectF p0){ return false; } + public boolean mapRect(RectF p0, RectF p1){ return false; } + public boolean postConcat(Matrix p0){ return false; } + public boolean postRotate(float p0){ return false; } + public boolean postRotate(float p0, float p1, float p2){ return false; } + public boolean postScale(float p0, float p1){ return false; } + public boolean postScale(float p0, float p1, float p2, float p3){ return false; } + public boolean postSkew(float p0, float p1){ return false; } + public boolean postSkew(float p0, float p1, float p2, float p3){ return false; } + public boolean postTranslate(float p0, float p1){ return false; } + public boolean preConcat(Matrix p0){ return false; } + public boolean preRotate(float p0){ return false; } + public boolean preRotate(float p0, float p1, float p2){ return false; } + public boolean preScale(float p0, float p1){ return false; } + public boolean preScale(float p0, float p1, float p2, float p3){ return false; } + public boolean preSkew(float p0, float p1){ return false; } + public boolean preSkew(float p0, float p1, float p2, float p3){ return false; } + public boolean preTranslate(float p0, float p1){ return false; } + public boolean rectStaysRect(){ return false; } + public boolean setConcat(Matrix p0, Matrix p1){ return false; } + public boolean setPolyToPoly(float[] p0, int p1, float[] p2, int p3, int p4){ return false; } + public boolean setRectToRect(RectF p0, RectF p1, Matrix.ScaleToFit p2){ return false; } + public float mapRadius(float p0){ return 0; } + public int hashCode(){ return 0; } + public static int MPERSP_0 = 0; + public static int MPERSP_1 = 0; + public static int MPERSP_2 = 0; + public static int MSCALE_X = 0; + public static int MSCALE_Y = 0; + public static int MSKEW_X = 0; + public static int MSKEW_Y = 0; + public static int MTRANS_X = 0; + public static int MTRANS_Y = 0; + public void getValues(float[] p0){} + public void mapPoints(float[] p0){} + public void mapPoints(float[] p0, float[] p1){} + public void mapPoints(float[] p0, int p1, float[] p2, int p3, int p4){} + public void mapVectors(float[] p0){} + public void mapVectors(float[] p0, float[] p1){} + public void mapVectors(float[] p0, int p1, float[] p2, int p3, int p4){} + public void reset(){} + public void set(Matrix p0){} + public void setRotate(float p0){} + public void setRotate(float p0, float p1, float p2){} + public void setScale(float p0, float p1){} + public void setScale(float p0, float p1, float p2, float p3){} + public void setSinCos(float p0, float p1){} + public void setSinCos(float p0, float p1, float p2, float p3){} + public void setSkew(float p0, float p1){} + public void setSkew(float p0, float p1, float p2, float p3){} + public void setTranslate(float p0, float p1){} + public void setValues(float[] p0){} + static public enum ScaleToFit + { + CENTER, END, FILL, START; + private ScaleToFit() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Movie.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Movie.java new file mode 100644 index 00000000000..dd531ba7e04 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Movie.java @@ -0,0 +1,23 @@ +// Generated automatically from android.graphics.Movie for testing purposes + +package android.graphics; + +import android.graphics.Canvas; +import android.graphics.Paint; +import java.io.InputStream; + +public class Movie +{ + protected Movie() {} + protected void finalize(){} + public boolean isOpaque(){ return false; } + public boolean setTime(int p0){ return false; } + public int duration(){ return 0; } + public int height(){ return 0; } + public int width(){ return 0; } + public static Movie decodeByteArray(byte[] p0, int p1, int p2){ return null; } + public static Movie decodeFile(String p0){ return null; } + public static Movie decodeStream(InputStream p0){ return null; } + public void draw(Canvas p0, float p1, float p2){} + public void draw(Canvas p0, float p1, float p2, Paint p3){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/NinePatch.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/NinePatch.java new file mode 100644 index 00000000000..0fa7bc2eb69 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/NinePatch.java @@ -0,0 +1,31 @@ +// Generated automatically from android.graphics.NinePatch for testing purposes + +package android.graphics; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; + +public class NinePatch +{ + protected NinePatch() {} + protected void finalize(){} + public Bitmap getBitmap(){ return null; } + public NinePatch(Bitmap p0, byte[] p1){} + public NinePatch(Bitmap p0, byte[] p1, String p2){} + public Paint getPaint(){ return null; } + public String getName(){ return null; } + public final Region getTransparentRegion(Rect p0){ return null; } + public final boolean hasAlpha(){ return false; } + public int getDensity(){ return 0; } + public int getHeight(){ return 0; } + public int getWidth(){ return 0; } + public static boolean isNinePatchChunk(byte[] p0){ return false; } + public void draw(Canvas p0, Rect p1){} + public void draw(Canvas p0, Rect p1, Paint p2){} + public void draw(Canvas p0, RectF p1){} + public void setPaint(Paint p0){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Outline.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Outline.java new file mode 100644 index 00000000000..806c40a9807 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Outline.java @@ -0,0 +1,28 @@ +// Generated automatically from android.graphics.Outline for testing purposes + +package android.graphics; + +import android.graphics.Path; +import android.graphics.Rect; + +public class Outline +{ + public Outline(){} + public Outline(Outline p0){} + public boolean canClip(){ return false; } + public boolean getRect(Rect p0){ return false; } + public boolean isEmpty(){ return false; } + public float getAlpha(){ return 0; } + public float getRadius(){ return 0; } + public void offset(int p0, int p1){} + public void set(Outline p0){} + public void setAlpha(float p0){} + public void setConvexPath(Path p0){} + public void setEmpty(){} + public void setOval(Rect p0){} + public void setOval(int p0, int p1, int p2, int p3){} + public void setRect(Rect p0){} + public void setRect(int p0, int p1, int p2, int p3){} + public void setRoundRect(Rect p0, float p1){} + public void setRoundRect(int p0, int p1, int p2, int p3, float p4){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Paint.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Paint.java new file mode 100644 index 00000000000..810aecc3617 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Paint.java @@ -0,0 +1,212 @@ +// Generated automatically from android.graphics.Paint for testing purposes + +package android.graphics; + +import android.graphics.BlendMode; +import android.graphics.ColorFilter; +import android.graphics.MaskFilter; +import android.graphics.Path; +import android.graphics.PathEffect; +import android.graphics.Rect; +import android.graphics.Shader; +import android.graphics.Typeface; +import android.graphics.Xfermode; +import android.os.LocaleList; +import java.util.Locale; + +public class Paint +{ + public BlendMode getBlendMode(){ return null; } + public ColorFilter getColorFilter(){ return null; } + public ColorFilter setColorFilter(ColorFilter p0){ return null; } + public Locale getTextLocale(){ return null; } + public LocaleList getTextLocales(){ return null; } + public MaskFilter getMaskFilter(){ return null; } + public MaskFilter setMaskFilter(MaskFilter p0){ return null; } + public Paint(){} + public Paint(Paint p0){} + public Paint(int p0){} + public Paint.Align getTextAlign(){ return null; } + public Paint.Cap getStrokeCap(){ return null; } + public Paint.FontMetrics getFontMetrics(){ return null; } + public Paint.FontMetricsInt getFontMetricsInt(){ return null; } + public Paint.Join getStrokeJoin(){ return null; } + public Paint.Style getStyle(){ return null; } + public PathEffect getPathEffect(){ return null; } + public PathEffect setPathEffect(PathEffect p0){ return null; } + public Shader getShader(){ return null; } + public Shader setShader(Shader p0){ return null; } + public String getFontFeatureSettings(){ return null; } + public String getFontVariationSettings(){ return null; } + public Typeface getTypeface(){ return null; } + public Typeface setTypeface(Typeface p0){ return null; } + public Xfermode getXfermode(){ return null; } + public Xfermode setXfermode(Xfermode p0){ return null; } + public boolean equalsForTextMeasurement(Paint p0){ return false; } + public boolean getFillPath(Path p0, Path p1){ return false; } + public boolean hasGlyph(String p0){ return false; } + public boolean isElegantTextHeight(){ return false; } + public boolean setFontVariationSettings(String p0){ return false; } + public final boolean isAntiAlias(){ return false; } + public final boolean isDither(){ return false; } + public final boolean isFakeBoldText(){ return false; } + public final boolean isFilterBitmap(){ return false; } + public final boolean isLinearText(){ return false; } + public final boolean isStrikeThruText(){ return false; } + public final boolean isSubpixelText(){ return false; } + public final boolean isUnderlineText(){ return false; } + public float ascent(){ return 0; } + public float descent(){ return 0; } + public float getFontMetrics(Paint.FontMetrics p0){ return 0; } + public float getFontSpacing(){ return 0; } + public float getLetterSpacing(){ return 0; } + public float getRunAdvance(CharSequence p0, int p1, int p2, int p3, int p4, boolean p5, int p6){ return 0; } + public float getRunAdvance(char[] p0, int p1, int p2, int p3, int p4, boolean p5, int p6){ return 0; } + public float getShadowLayerDx(){ return 0; } + public float getShadowLayerDy(){ return 0; } + public float getShadowLayerRadius(){ return 0; } + public float getStrikeThruPosition(){ return 0; } + public float getStrikeThruThickness(){ return 0; } + public float getStrokeMiter(){ return 0; } + public float getStrokeWidth(){ return 0; } + public float getTextRunAdvances(char[] p0, int p1, int p2, int p3, int p4, boolean p5, float[] p6, int p7){ return 0; } + public float getTextScaleX(){ return 0; } + public float getTextSize(){ return 0; } + public float getTextSkewX(){ return 0; } + public float getUnderlinePosition(){ return 0; } + public float getUnderlineThickness(){ return 0; } + public float getWordSpacing(){ return 0; } + public float measureText(CharSequence p0, int p1, int p2){ return 0; } + public float measureText(String p0){ return 0; } + public float measureText(String p0, int p1, int p2){ return 0; } + public float measureText(char[] p0, int p1, int p2){ return 0; } + public int breakText(CharSequence p0, int p1, int p2, boolean p3, float p4, float[] p5){ return 0; } + public int breakText(String p0, boolean p1, float p2, float[] p3){ return 0; } + public int breakText(char[] p0, int p1, int p2, float p3, float[] p4){ return 0; } + public int getAlpha(){ return 0; } + public int getColor(){ return 0; } + public int getEndHyphenEdit(){ return 0; } + public int getFlags(){ return 0; } + public int getFontMetricsInt(Paint.FontMetricsInt p0){ return 0; } + public int getHinting(){ return 0; } + public int getOffsetForAdvance(CharSequence p0, int p1, int p2, int p3, int p4, boolean p5, float p6){ return 0; } + public int getOffsetForAdvance(char[] p0, int p1, int p2, int p3, int p4, boolean p5, float p6){ return 0; } + public int getShadowLayerColor(){ return 0; } + public int getStartHyphenEdit(){ return 0; } + public int getTextRunCursor(CharSequence p0, int p1, int p2, boolean p3, int p4, int p5){ return 0; } + public int getTextRunCursor(char[] p0, int p1, int p2, boolean p3, int p4, int p5){ return 0; } + public int getTextWidths(CharSequence p0, int p1, int p2, float[] p3){ return 0; } + public int getTextWidths(String p0, float[] p1){ return 0; } + public int getTextWidths(String p0, int p1, int p2, float[] p3){ return 0; } + public int getTextWidths(char[] p0, int p1, int p2, float[] p3){ return 0; } + public long getColorLong(){ return 0; } + public long getShadowLayerColorLong(){ return 0; } + public static int ANTI_ALIAS_FLAG = 0; + public static int CURSOR_AFTER = 0; + public static int CURSOR_AT = 0; + public static int CURSOR_AT_OR_AFTER = 0; + public static int CURSOR_AT_OR_BEFORE = 0; + public static int CURSOR_BEFORE = 0; + public static int DEV_KERN_TEXT_FLAG = 0; + public static int DITHER_FLAG = 0; + public static int EMBEDDED_BITMAP_TEXT_FLAG = 0; + public static int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 0; + public static int END_HYPHEN_EDIT_INSERT_HYPHEN = 0; + public static int END_HYPHEN_EDIT_INSERT_MAQAF = 0; + public static int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 0; + public static int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 0; + public static int END_HYPHEN_EDIT_NO_EDIT = 0; + public static int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 0; + public static int FAKE_BOLD_TEXT_FLAG = 0; + public static int FILTER_BITMAP_FLAG = 0; + public static int HINTING_OFF = 0; + public static int HINTING_ON = 0; + public static int LINEAR_TEXT_FLAG = 0; + public static int START_HYPHEN_EDIT_INSERT_HYPHEN = 0; + public static int START_HYPHEN_EDIT_INSERT_ZWJ = 0; + public static int START_HYPHEN_EDIT_NO_EDIT = 0; + public static int STRIKE_THRU_TEXT_FLAG = 0; + public static int SUBPIXEL_TEXT_FLAG = 0; + public static int UNDERLINE_TEXT_FLAG = 0; + public void clearShadowLayer(){} + public void getTextBounds(CharSequence p0, int p1, int p2, Rect p3){} + public void getTextBounds(String p0, int p1, int p2, Rect p3){} + public void getTextBounds(char[] p0, int p1, int p2, Rect p3){} + public void getTextPath(String p0, int p1, int p2, float p3, float p4, Path p5){} + public void getTextPath(char[] p0, int p1, int p2, float p3, float p4, Path p5){} + public void reset(){} + public void set(Paint p0){} + public void setARGB(int p0, int p1, int p2, int p3){} + public void setAlpha(int p0){} + public void setAntiAlias(boolean p0){} + public void setBlendMode(BlendMode p0){} + public void setColor(int p0){} + public void setColor(long p0){} + public void setDither(boolean p0){} + public void setElegantTextHeight(boolean p0){} + public void setEndHyphenEdit(int p0){} + public void setFakeBoldText(boolean p0){} + public void setFilterBitmap(boolean p0){} + public void setFlags(int p0){} + public void setFontFeatureSettings(String p0){} + public void setHinting(int p0){} + public void setLetterSpacing(float p0){} + public void setLinearText(boolean p0){} + public void setShadowLayer(float p0, float p1, float p2, int p3){} + public void setShadowLayer(float p0, float p1, float p2, long p3){} + public void setStartHyphenEdit(int p0){} + public void setStrikeThruText(boolean p0){} + public void setStrokeCap(Paint.Cap p0){} + public void setStrokeJoin(Paint.Join p0){} + public void setStrokeMiter(float p0){} + public void setStrokeWidth(float p0){} + public void setStyle(Paint.Style p0){} + public void setSubpixelText(boolean p0){} + public void setTextAlign(Paint.Align p0){} + public void setTextLocale(Locale p0){} + public void setTextLocales(LocaleList p0){} + public void setTextScaleX(float p0){} + public void setTextSize(float p0){} + public void setTextSkewX(float p0){} + public void setUnderlineText(boolean p0){} + public void setWordSpacing(float p0){} + static public class FontMetrics + { + public FontMetrics(){} + public float ascent = 0; + public float bottom = 0; + public float descent = 0; + public float leading = 0; + public float top = 0; + } + static public class FontMetricsInt + { + public FontMetricsInt(){} + public String toString(){ return null; } + public int ascent = 0; + public int bottom = 0; + public int descent = 0; + public int leading = 0; + public int top = 0; + } + static public enum Align + { + CENTER, LEFT, RIGHT; + private Align() {} + } + static public enum Cap + { + BUTT, ROUND, SQUARE; + private Cap() {} + } + static public enum Join + { + BEVEL, MITER, ROUND; + private Join() {} + } + static public enum Style + { + FILL, FILL_AND_STROKE, STROKE; + private Style() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Path.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Path.java new file mode 100644 index 00000000000..c7164e37b01 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Path.java @@ -0,0 +1,73 @@ +// Generated automatically from android.graphics.Path for testing purposes + +package android.graphics; + +import android.graphics.Matrix; +import android.graphics.RectF; + +public class Path +{ + public Path(){} + public Path(Path p0){} + public Path.FillType getFillType(){ return null; } + public boolean isConvex(){ return false; } + public boolean isEmpty(){ return false; } + public boolean isInverseFillType(){ return false; } + public boolean isRect(RectF p0){ return false; } + public boolean op(Path p0, Path p1, Path.Op p2){ return false; } + public boolean op(Path p0, Path.Op p1){ return false; } + public float[] approximate(float p0){ return null; } + public void addArc(RectF p0, float p1, float p2){} + public void addArc(float p0, float p1, float p2, float p3, float p4, float p5){} + public void addCircle(float p0, float p1, float p2, Path.Direction p3){} + public void addOval(RectF p0, Path.Direction p1){} + public void addOval(float p0, float p1, float p2, float p3, Path.Direction p4){} + public void addPath(Path p0){} + public void addPath(Path p0, Matrix p1){} + public void addPath(Path p0, float p1, float p2){} + public void addRect(RectF p0, Path.Direction p1){} + public void addRect(float p0, float p1, float p2, float p3, Path.Direction p4){} + public void addRoundRect(RectF p0, float p1, float p2, Path.Direction p3){} + public void addRoundRect(RectF p0, float[] p1, Path.Direction p2){} + public void addRoundRect(float p0, float p1, float p2, float p3, float p4, float p5, Path.Direction p6){} + public void addRoundRect(float p0, float p1, float p2, float p3, float[] p4, Path.Direction p5){} + public void arcTo(RectF p0, float p1, float p2){} + public void arcTo(RectF p0, float p1, float p2, boolean p3){} + public void arcTo(float p0, float p1, float p2, float p3, float p4, float p5, boolean p6){} + public void close(){} + public void computeBounds(RectF p0, boolean p1){} + public void cubicTo(float p0, float p1, float p2, float p3, float p4, float p5){} + public void incReserve(int p0){} + public void lineTo(float p0, float p1){} + public void moveTo(float p0, float p1){} + public void offset(float p0, float p1){} + public void offset(float p0, float p1, Path p2){} + public void quadTo(float p0, float p1, float p2, float p3){} + public void rCubicTo(float p0, float p1, float p2, float p3, float p4, float p5){} + public void rLineTo(float p0, float p1){} + public void rMoveTo(float p0, float p1){} + public void rQuadTo(float p0, float p1, float p2, float p3){} + public void reset(){} + public void rewind(){} + public void set(Path p0){} + public void setFillType(Path.FillType p0){} + public void setLastPoint(float p0, float p1){} + public void toggleInverseFillType(){} + public void transform(Matrix p0){} + public void transform(Matrix p0, Path p1){} + static public enum Direction + { + CCW, CW; + private Direction() {} + } + static public enum FillType + { + EVEN_ODD, INVERSE_EVEN_ODD, INVERSE_WINDING, WINDING; + private FillType() {} + } + static public enum Op + { + DIFFERENCE, INTERSECT, REVERSE_DIFFERENCE, UNION, XOR; + private Op() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/PathEffect.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/PathEffect.java new file mode 100644 index 00000000000..c9ca9aeae86 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/PathEffect.java @@ -0,0 +1,10 @@ +// Generated automatically from android.graphics.PathEffect for testing purposes + +package android.graphics; + + +public class PathEffect +{ + protected void finalize(){} + public PathEffect(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Picture.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Picture.java new file mode 100644 index 00000000000..328321a2139 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Picture.java @@ -0,0 +1,18 @@ +// Generated automatically from android.graphics.Picture for testing purposes + +package android.graphics; + +import android.graphics.Canvas; + +public class Picture +{ + protected void finalize(){} + public Canvas beginRecording(int p0, int p1){ return null; } + public Picture(){} + public Picture(Picture p0){} + public boolean requiresHardwareAcceleration(){ return false; } + public int getHeight(){ return 0; } + public int getWidth(){ return 0; } + public void draw(Canvas p0){} + public void endRecording(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Point.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Point.java new file mode 100644 index 00000000000..0e97248f44b --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Point.java @@ -0,0 +1,26 @@ +// Generated automatically from android.graphics.Point for testing purposes + +package android.graphics; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Point implements Parcelable +{ + public Point(){} + public Point(Point p0){} + public Point(int p0, int p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final boolean equals(int p0, int p1){ return false; } + public final void negate(){} + public final void offset(int p0, int p1){} + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int x = 0; + public int y = 0; + public static Parcelable.Creator<Point> CREATOR = null; + public void readFromParcel(Parcel p0){} + public void set(int p0, int p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/PorterDuff.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/PorterDuff.java new file mode 100644 index 00000000000..39a82e655d6 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/PorterDuff.java @@ -0,0 +1,14 @@ +// Generated automatically from android.graphics.PorterDuff for testing purposes + +package android.graphics; + + +public class PorterDuff +{ + public PorterDuff(){} + static public enum Mode + { + ADD, CLEAR, DARKEN, DST, DST_ATOP, DST_IN, DST_OUT, DST_OVER, LIGHTEN, MULTIPLY, OVERLAY, SCREEN, SRC, SRC_ATOP, SRC_IN, SRC_OUT, SRC_OVER, XOR; + private Mode() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/RecordingCanvas.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/RecordingCanvas.java new file mode 100644 index 00000000000..3616f4275fe --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/RecordingCanvas.java @@ -0,0 +1,83 @@ +// Generated automatically from android.graphics.RecordingCanvas for testing purposes + +package android.graphics; + +import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.NinePatch; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Picture; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.RenderNode; +import android.graphics.text.MeasuredText; + +public class RecordingCanvas extends Canvas +{ + protected RecordingCanvas() {} + public boolean isHardwareAccelerated(){ return false; } + public boolean isOpaque(){ return false; } + public final void drawARGB(int p0, int p1, int p2, int p3){} + public final void drawArc(RectF p0, float p1, float p2, boolean p3, Paint p4){} + public final void drawArc(float p0, float p1, float p2, float p3, float p4, float p5, boolean p6, Paint p7){} + public final void drawBitmap(Bitmap p0, Matrix p1, Paint p2){} + public final void drawBitmap(Bitmap p0, Rect p1, Rect p2, Paint p3){} + public final void drawBitmap(Bitmap p0, Rect p1, RectF p2, Paint p3){} + public final void drawBitmap(Bitmap p0, float p1, float p2, Paint p3){} + public final void drawBitmap(int[] p0, int p1, int p2, float p3, float p4, int p5, int p6, boolean p7, Paint p8){} + public final void drawBitmap(int[] p0, int p1, int p2, int p3, int p4, int p5, int p6, boolean p7, Paint p8){} + public final void drawBitmapMesh(Bitmap p0, int p1, int p2, float[] p3, int p4, int[] p5, int p6, Paint p7){} + public final void drawCircle(float p0, float p1, float p2, Paint p3){} + public final void drawColor(int p0){} + public final void drawColor(int p0, BlendMode p1){} + public final void drawColor(int p0, PorterDuff.Mode p1){} + public final void drawColor(long p0, BlendMode p1){} + public final void drawDoubleRoundRect(RectF p0, float p1, float p2, RectF p3, float p4, float p5, Paint p6){} + public final void drawDoubleRoundRect(RectF p0, float[] p1, RectF p2, float[] p3, Paint p4){} + public final void drawLine(float p0, float p1, float p2, float p3, Paint p4){} + public final void drawLines(float[] p0, Paint p1){} + public final void drawLines(float[] p0, int p1, int p2, Paint p3){} + public final void drawOval(RectF p0, Paint p1){} + public final void drawOval(float p0, float p1, float p2, float p3, Paint p4){} + public final void drawPaint(Paint p0){} + public final void drawPatch(NinePatch p0, Rect p1, Paint p2){} + public final void drawPatch(NinePatch p0, RectF p1, Paint p2){} + public final void drawPath(Path p0, Paint p1){} + public final void drawPicture(Picture p0){} + public final void drawPicture(Picture p0, Rect p1){} + public final void drawPicture(Picture p0, RectF p1){} + public final void drawPoint(float p0, float p1, Paint p2){} + public final void drawPoints(float[] p0, Paint p1){} + public final void drawPoints(float[] p0, int p1, int p2, Paint p3){} + public final void drawPosText(String p0, float[] p1, Paint p2){} + public final void drawPosText(char[] p0, int p1, int p2, float[] p3, Paint p4){} + public final void drawRGB(int p0, int p1, int p2){} + public final void drawRect(Rect p0, Paint p1){} + public final void drawRect(RectF p0, Paint p1){} + public final void drawRect(float p0, float p1, float p2, float p3, Paint p4){} + public final void drawRoundRect(RectF p0, float p1, float p2, Paint p3){} + public final void drawRoundRect(float p0, float p1, float p2, float p3, float p4, float p5, Paint p6){} + public final void drawText(CharSequence p0, int p1, int p2, float p3, float p4, Paint p5){} + public final void drawText(String p0, float p1, float p2, Paint p3){} + public final void drawText(String p0, int p1, int p2, float p3, float p4, Paint p5){} + public final void drawText(char[] p0, int p1, int p2, float p3, float p4, Paint p5){} + public final void drawTextOnPath(String p0, Path p1, float p2, float p3, Paint p4){} + public final void drawTextOnPath(char[] p0, int p1, int p2, Path p3, float p4, float p5, Paint p6){} + public final void drawTextRun(CharSequence p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public final void drawTextRun(char[] p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public final void drawVertices(Canvas.VertexMode p0, int p1, float[] p2, int p3, float[] p4, int p5, int[] p6, int p7, short[] p8, int p9, int p10, Paint p11){} + public int getHeight(){ return 0; } + public int getMaximumBitmapHeight(){ return 0; } + public int getMaximumBitmapWidth(){ return 0; } + public int getWidth(){ return 0; } + public void disableZ(){} + public void drawRenderNode(RenderNode p0){} + public void drawTextRun(MeasuredText p0, int p1, int p2, int p3, int p4, float p5, float p6, boolean p7, Paint p8){} + public void enableZ(){} + public void setBitmap(Bitmap p0){} + public void setDensity(int p0){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Rect.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Rect.java new file mode 100644 index 00000000000..c29950cb31d --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Rect.java @@ -0,0 +1,52 @@ +// Generated automatically from android.graphics.Rect for testing purposes + +package android.graphics; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Rect implements Parcelable +{ + public Rect(){} + public Rect(Rect p0){} + public Rect(int p0, int p1, int p2, int p3){} + public String flattenToString(){ return null; } + public String toShortString(){ return null; } + public String toString(){ return null; } + public boolean contains(Rect p0){ return false; } + public boolean contains(int p0, int p1){ return false; } + public boolean contains(int p0, int p1, int p2, int p3){ return false; } + public boolean equals(Object p0){ return false; } + public boolean intersect(Rect p0){ return false; } + public boolean intersect(int p0, int p1, int p2, int p3){ return false; } + public boolean intersects(int p0, int p1, int p2, int p3){ return false; } + public boolean isEmpty(){ return false; } + public boolean setIntersect(Rect p0, Rect p1){ return false; } + public float exactCenterX(){ return 0; } + public float exactCenterY(){ return 0; } + public int bottom = 0; + public int centerX(){ return 0; } + public int centerY(){ return 0; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int height(){ return 0; } + public int left = 0; + public int right = 0; + public int top = 0; + public int width(){ return 0; } + public static Parcelable.Creator<Rect> CREATOR = null; + public static Rect unflattenFromString(String p0){ return null; } + public static boolean intersects(Rect p0, Rect p1){ return false; } + public void inset(int p0, int p1){} + public void offset(int p0, int p1){} + public void offsetTo(int p0, int p1){} + public void readFromParcel(Parcel p0){} + public void set(Rect p0){} + public void set(int p0, int p1, int p2, int p3){} + public void setEmpty(){} + public void sort(){} + public void union(Rect p0){} + public void union(int p0, int p1){} + public void union(int p0, int p1, int p2, int p3){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/RectF.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/RectF.java new file mode 100644 index 00000000000..59489dd3f17 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/RectF.java @@ -0,0 +1,53 @@ +// Generated automatically from android.graphics.RectF for testing purposes + +package android.graphics; + +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; + +public class RectF implements Parcelable +{ + public RectF(){} + public RectF(Rect p0){} + public RectF(RectF p0){} + public RectF(float p0, float p1, float p2, float p3){} + public String toShortString(){ return null; } + public String toString(){ return null; } + public boolean contains(RectF p0){ return false; } + public boolean contains(float p0, float p1){ return false; } + public boolean contains(float p0, float p1, float p2, float p3){ return false; } + public boolean equals(Object p0){ return false; } + public boolean intersect(RectF p0){ return false; } + public boolean intersect(float p0, float p1, float p2, float p3){ return false; } + public boolean intersects(float p0, float p1, float p2, float p3){ return false; } + public boolean setIntersect(RectF p0, RectF p1){ return false; } + public final boolean isEmpty(){ return false; } + public final float centerX(){ return 0; } + public final float centerY(){ return 0; } + public final float height(){ return 0; } + public final float width(){ return 0; } + public float bottom = 0; + public float left = 0; + public float right = 0; + public float top = 0; + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<RectF> CREATOR = null; + public static boolean intersects(RectF p0, RectF p1){ return false; } + public void inset(float p0, float p1){} + public void offset(float p0, float p1){} + public void offsetTo(float p0, float p1){} + public void readFromParcel(Parcel p0){} + public void round(Rect p0){} + public void roundOut(Rect p0){} + public void set(Rect p0){} + public void set(RectF p0){} + public void set(float p0, float p1, float p2, float p3){} + public void setEmpty(){} + public void sort(){} + public void union(RectF p0){} + public void union(float p0, float p1){} + public void union(float p0, float p1, float p2, float p3){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Region.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Region.java new file mode 100644 index 00000000000..7fbd2b4dafc --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Region.java @@ -0,0 +1,53 @@ +// Generated automatically from android.graphics.Region for testing purposes + +package android.graphics; + +import android.graphics.Path; +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; + +public class Region implements Parcelable +{ + protected void finalize(){} + public Path getBoundaryPath(){ return null; } + public Rect getBounds(){ return null; } + public Region(){} + public Region(Rect p0){} + public Region(Region p0){} + public Region(int p0, int p1, int p2, int p3){} + public String toString(){ return null; } + public boolean contains(int p0, int p1){ return false; } + public boolean equals(Object p0){ return false; } + public boolean getBoundaryPath(Path p0){ return false; } + public boolean getBounds(Rect p0){ return false; } + public boolean isComplex(){ return false; } + public boolean isEmpty(){ return false; } + public boolean isRect(){ return false; } + public boolean op(Rect p0, Region p1, Region.Op p2){ return false; } + public boolean op(Rect p0, Region.Op p1){ return false; } + public boolean op(Region p0, Region p1, Region.Op p2){ return false; } + public boolean op(Region p0, Region.Op p1){ return false; } + public boolean op(int p0, int p1, int p2, int p3, Region.Op p4){ return false; } + public boolean quickContains(Rect p0){ return false; } + public boolean quickContains(int p0, int p1, int p2, int p3){ return false; } + public boolean quickReject(Rect p0){ return false; } + public boolean quickReject(Region p0){ return false; } + public boolean quickReject(int p0, int p1, int p2, int p3){ return false; } + public boolean set(Rect p0){ return false; } + public boolean set(Region p0){ return false; } + public boolean set(int p0, int p1, int p2, int p3){ return false; } + public boolean setPath(Path p0, Region p1){ return false; } + public final boolean union(Rect p0){ return false; } + public int describeContents(){ return 0; } + public static Parcelable.Creator<Region> CREATOR = null; + public void setEmpty(){} + public void translate(int p0, int p1){} + public void translate(int p0, int p1, Region p2){} + public void writeToParcel(Parcel p0, int p1){} + static public enum Op + { + DIFFERENCE, INTERSECT, REPLACE, REVERSE_DIFFERENCE, UNION, XOR; + private Op() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/RenderNode.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/RenderNode.java new file mode 100644 index 00000000000..9384cd4cd4e --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/RenderNode.java @@ -0,0 +1,82 @@ +// Generated automatically from android.graphics.RenderNode for testing purposes + +package android.graphics; + +import android.graphics.Matrix; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.RecordingCanvas; +import android.graphics.Rect; + +public class RenderNode +{ + protected RenderNode() {} + public RecordingCanvas beginRecording(){ return null; } + public RecordingCanvas beginRecording(int p0, int p1){ return null; } + public RenderNode(String p0){} + public boolean getClipToBounds(){ return false; } + public boolean getClipToOutline(){ return false; } + public boolean getUseCompositingLayer(){ return false; } + public boolean hasDisplayList(){ return false; } + public boolean hasIdentityMatrix(){ return false; } + public boolean hasOverlappingRendering(){ return false; } + public boolean hasShadow(){ return false; } + public boolean isForceDarkAllowed(){ return false; } + public boolean isPivotExplicitlySet(){ return false; } + public boolean offsetLeftAndRight(int p0){ return false; } + public boolean offsetTopAndBottom(int p0){ return false; } + public boolean resetPivot(){ return false; } + public boolean setAlpha(float p0){ return false; } + public boolean setAmbientShadowColor(int p0){ return false; } + public boolean setCameraDistance(float p0){ return false; } + public boolean setClipRect(Rect p0){ return false; } + public boolean setClipToBounds(boolean p0){ return false; } + public boolean setClipToOutline(boolean p0){ return false; } + public boolean setElevation(float p0){ return false; } + public boolean setForceDarkAllowed(boolean p0){ return false; } + public boolean setHasOverlappingRendering(boolean p0){ return false; } + public boolean setOutline(Outline p0){ return false; } + public boolean setPivotX(float p0){ return false; } + public boolean setPivotY(float p0){ return false; } + public boolean setPosition(Rect p0){ return false; } + public boolean setPosition(int p0, int p1, int p2, int p3){ return false; } + public boolean setProjectBackwards(boolean p0){ return false; } + public boolean setProjectionReceiver(boolean p0){ return false; } + public boolean setRotationX(float p0){ return false; } + public boolean setRotationY(float p0){ return false; } + public boolean setRotationZ(float p0){ return false; } + public boolean setScaleX(float p0){ return false; } + public boolean setScaleY(float p0){ return false; } + public boolean setSpotShadowColor(int p0){ return false; } + public boolean setTranslationX(float p0){ return false; } + public boolean setTranslationY(float p0){ return false; } + public boolean setTranslationZ(float p0){ return false; } + public boolean setUseCompositingLayer(boolean p0, Paint p1){ return false; } + public float getAlpha(){ return 0; } + public float getCameraDistance(){ return 0; } + public float getElevation(){ return 0; } + public float getPivotX(){ return 0; } + public float getPivotY(){ return 0; } + public float getRotationX(){ return 0; } + public float getRotationY(){ return 0; } + public float getRotationZ(){ return 0; } + public float getScaleX(){ return 0; } + public float getScaleY(){ return 0; } + public float getTranslationX(){ return 0; } + public float getTranslationY(){ return 0; } + public float getTranslationZ(){ return 0; } + public int getAmbientShadowColor(){ return 0; } + public int getBottom(){ return 0; } + public int getHeight(){ return 0; } + public int getLeft(){ return 0; } + public int getRight(){ return 0; } + public int getSpotShadowColor(){ return 0; } + public int getTop(){ return 0; } + public int getWidth(){ return 0; } + public long computeApproximateMemoryUsage(){ return 0; } + public long getUniqueId(){ return 0; } + public void discardDisplayList(){} + public void endRecording(){} + public void getInverseMatrix(Matrix p0){} + public void getMatrix(Matrix p0){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Shader.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Shader.java new file mode 100644 index 00000000000..3e845aa0c0a --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Shader.java @@ -0,0 +1,12 @@ +// Generated automatically from android.graphics.Shader for testing purposes + +package android.graphics; + +import android.graphics.Matrix; + +public class Shader +{ + public Shader(){} + public boolean getLocalMatrix(Matrix p0){ return false; } + public void setLocalMatrix(Matrix p0){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Typeface.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Typeface.java new file mode 100644 index 00000000000..a2ab630e8d0 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Typeface.java @@ -0,0 +1,33 @@ +// Generated automatically from android.graphics.Typeface for testing purposes + +package android.graphics; + +import android.content.res.AssetManager; +import java.io.File; + +public class Typeface +{ + protected Typeface() {} + public boolean equals(Object p0){ return false; } + public final boolean isBold(){ return false; } + public final boolean isItalic(){ return false; } + public int getStyle(){ return 0; } + public int getWeight(){ return 0; } + public int hashCode(){ return 0; } + public static Typeface DEFAULT = null; + public static Typeface DEFAULT_BOLD = null; + public static Typeface MONOSPACE = null; + public static Typeface SANS_SERIF = null; + public static Typeface SERIF = null; + public static Typeface create(String p0, int p1){ return null; } + public static Typeface create(Typeface p0, int p1){ return null; } + public static Typeface create(Typeface p0, int p1, boolean p2){ return null; } + public static Typeface createFromAsset(AssetManager p0, String p1){ return null; } + public static Typeface createFromFile(File p0){ return null; } + public static Typeface createFromFile(String p0){ return null; } + public static Typeface defaultFromStyle(int p0){ return null; } + public static int BOLD = 0; + public static int BOLD_ITALIC = 0; + public static int ITALIC = 0; + public static int NORMAL = 0; +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/Xfermode.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Xfermode.java new file mode 100644 index 00000000000..7b6e5ade001 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/Xfermode.java @@ -0,0 +1,9 @@ +// Generated automatically from android.graphics.Xfermode for testing purposes + +package android.graphics; + + +public class Xfermode +{ + public Xfermode(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/drawable/Drawable.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/drawable/Drawable.java new file mode 100644 index 00000000000..5bb5b00f898 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/drawable/Drawable.java @@ -0,0 +1,111 @@ +// Generated automatically from android.graphics.drawable.Drawable for testing purposes + +package android.graphics.drawable; + +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.graphics.BitmapFactory; +import android.graphics.BlendMode; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Insets; +import android.graphics.Outline; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.Region; +import android.util.AttributeSet; +import android.util.TypedValue; +import java.io.InputStream; +import org.xmlpull.v1.XmlPullParser; + +abstract public class Drawable +{ + abstract static public class ConstantState + { + public ConstantState(){} + public Drawable newDrawable(Resources p0){ return null; } + public Drawable newDrawable(Resources p0, Resources.Theme p1){ return null; } + public abstract Drawable newDrawable(); + public abstract int getChangingConfigurations(); + public boolean canApplyTheme(){ return false; } + } + protected boolean onLevelChange(int p0){ return false; } + protected boolean onStateChange(int[] p0){ return false; } + protected void onBoundsChange(Rect p0){} + public ColorFilter getColorFilter(){ return null; } + public Drawable getCurrent(){ return null; } + public Drawable mutate(){ return null; } + public Drawable(){} + public Drawable.Callback getCallback(){ return null; } + public Drawable.ConstantState getConstantState(){ return null; } + public Insets getOpticalInsets(){ return null; } + public Rect getDirtyBounds(){ return null; } + public Region getTransparentRegion(){ return null; } + public abstract int getOpacity(); + public abstract void draw(Canvas p0); + public abstract void setAlpha(int p0); + public abstract void setColorFilter(ColorFilter p0); + public boolean canApplyTheme(){ return false; } + public boolean getPadding(Rect p0){ return false; } + public boolean isAutoMirrored(){ return false; } + public boolean isFilterBitmap(){ return false; } + public boolean isProjected(){ return false; } + public boolean isStateful(){ return false; } + public boolean onLayoutDirectionChanged(int p0){ return false; } + public boolean setState(int[] p0){ return false; } + public boolean setVisible(boolean p0, boolean p1){ return false; } + public final Rect copyBounds(){ return null; } + public final Rect getBounds(){ return null; } + public final boolean isVisible(){ return false; } + public final boolean setLayoutDirection(int p0){ return false; } + public final boolean setLevel(int p0){ return false; } + public final int getLevel(){ return 0; } + public final void copyBounds(Rect p0){} + public final void setCallback(Drawable.Callback p0){} + public int getAlpha(){ return 0; } + public int getChangingConfigurations(){ return 0; } + public int getIntrinsicHeight(){ return 0; } + public int getIntrinsicWidth(){ return 0; } + public int getLayoutDirection(){ return 0; } + public int getMinimumHeight(){ return 0; } + public int getMinimumWidth(){ return 0; } + public int[] getState(){ return null; } + public static Drawable createFromPath(String p0){ return null; } + public static Drawable createFromResourceStream(Resources p0, TypedValue p1, InputStream p2, String p3){ return null; } + public static Drawable createFromResourceStream(Resources p0, TypedValue p1, InputStream p2, String p3, BitmapFactory.Options p4){ return null; } + public static Drawable createFromStream(InputStream p0, String p1){ return null; } + public static Drawable createFromXml(Resources p0, XmlPullParser p1){ return null; } + public static Drawable createFromXml(Resources p0, XmlPullParser p1, Resources.Theme p2){ return null; } + public static Drawable createFromXmlInner(Resources p0, XmlPullParser p1, AttributeSet p2){ return null; } + public static Drawable createFromXmlInner(Resources p0, XmlPullParser p1, AttributeSet p2, Resources.Theme p3){ return null; } + public static int resolveOpacity(int p0, int p1){ return 0; } + public void applyTheme(Resources.Theme p0){} + public void clearColorFilter(){} + public void getHotspotBounds(Rect p0){} + public void getOutline(Outline p0){} + public void inflate(Resources p0, XmlPullParser p1, AttributeSet p2){} + public void inflate(Resources p0, XmlPullParser p1, AttributeSet p2, Resources.Theme p3){} + public void invalidateSelf(){} + public void jumpToCurrentState(){} + public void scheduleSelf(Runnable p0, long p1){} + public void setAutoMirrored(boolean p0){} + public void setBounds(Rect p0){} + public void setBounds(int p0, int p1, int p2, int p3){} + public void setChangingConfigurations(int p0){} + public void setColorFilter(int p0, PorterDuff.Mode p1){} + public void setDither(boolean p0){} + public void setFilterBitmap(boolean p0){} + public void setHotspot(float p0, float p1){} + public void setHotspotBounds(int p0, int p1, int p2, int p3){} + public void setTint(int p0){} + public void setTintBlendMode(BlendMode p0){} + public void setTintList(ColorStateList p0){} + public void setTintMode(PorterDuff.Mode p0){} + public void unscheduleSelf(Runnable p0){} + static public interface Callback + { + void invalidateDrawable(Drawable p0); + void scheduleDrawable(Drawable p0, Runnable p1, long p2); + void unscheduleDrawable(Drawable p0, Runnable p1); + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/drawable/Icon.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/drawable/Icon.java new file mode 100644 index 00000000000..69faa775482 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/drawable/Icon.java @@ -0,0 +1,52 @@ +// Generated automatically from android.graphics.drawable.Icon for testing purposes + +package android.graphics.drawable; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; + +public class Icon implements Parcelable +{ + protected Icon() {} + public Drawable loadDrawable(Context p0){ return null; } + public Icon setTint(int p0){ return null; } + public Icon setTintBlendMode(BlendMode p0){ return null; } + public Icon setTintList(ColorStateList p0){ return null; } + public Icon setTintMode(PorterDuff.Mode p0){ return null; } + public String getResPackage(){ return null; } + public String toString(){ return null; } + public Uri getUri(){ return null; } + public int describeContents(){ return 0; } + public int getResId(){ return 0; } + public int getType(){ return 0; } + public static Icon createWithAdaptiveBitmap(Bitmap p0){ return null; } + public static Icon createWithBitmap(Bitmap p0){ return null; } + public static Icon createWithContentUri(String p0){ return null; } + public static Icon createWithContentUri(Uri p0){ return null; } + public static Icon createWithData(byte[] p0, int p1, int p2){ return null; } + public static Icon createWithFilePath(String p0){ return null; } + public static Icon createWithResource(Context p0, int p1){ return null; } + public static Icon createWithResource(String p0, int p1){ return null; } + public static Parcelable.Creator<Icon> CREATOR = null; + public static int TYPE_ADAPTIVE_BITMAP = 0; + public static int TYPE_BITMAP = 0; + public static int TYPE_DATA = 0; + public static int TYPE_RESOURCE = 0; + public static int TYPE_URI = 0; + public void loadDrawableAsync(Context p0, Icon.OnDrawableLoadedListener p1, Handler p2){} + public void loadDrawableAsync(Context p0, Message p1){} + public void writeToParcel(Parcel p0, int p1){} + static public interface OnDrawableLoadedListener + { + void onDrawableLoaded(Drawable p0); + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/graphics/text/MeasuredText.java b/java/ql/test/stubs/google-android-9.0.0/android/graphics/text/MeasuredText.java new file mode 100644 index 00000000000..c737bd5dfc1 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/graphics/text/MeasuredText.java @@ -0,0 +1,13 @@ +// Generated automatically from android.graphics.text.MeasuredText for testing purposes + +package android.graphics.text; + +import android.graphics.Rect; + +public class MeasuredText +{ + protected MeasuredText() {} + public float getCharWidthAt(int p0){ return 0; } + public float getWidth(int p0, int p1){ return 0; } + public void getBounds(int p0, int p1, Rect p2){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/hardware/HardwareBuffer.java b/java/ql/test/stubs/google-android-9.0.0/android/hardware/HardwareBuffer.java new file mode 100644 index 00000000000..d2998f52be9 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/hardware/HardwareBuffer.java @@ -0,0 +1,49 @@ +// Generated automatically from android.hardware.HardwareBuffer for testing purposes + +package android.hardware; + +import android.os.Parcel; +import android.os.Parcelable; + +public class HardwareBuffer implements AutoCloseable, Parcelable +{ + protected HardwareBuffer() {} + protected void finalize(){} + public boolean isClosed(){ return false; } + public int describeContents(){ return 0; } + public int getFormat(){ return 0; } + public int getHeight(){ return 0; } + public int getLayers(){ return 0; } + public int getWidth(){ return 0; } + public long getUsage(){ return 0; } + public static HardwareBuffer create(int p0, int p1, int p2, int p3, long p4){ return null; } + public static Parcelable.Creator<HardwareBuffer> CREATOR = null; + public static boolean isSupported(int p0, int p1, int p2, int p3, long p4){ return false; } + public static int BLOB = 0; + public static int DS_24UI8 = 0; + public static int DS_FP32UI8 = 0; + public static int D_16 = 0; + public static int D_24 = 0; + public static int D_FP32 = 0; + public static int RGBA_1010102 = 0; + public static int RGBA_8888 = 0; + public static int RGBA_FP16 = 0; + public static int RGBX_8888 = 0; + public static int RGB_565 = 0; + public static int RGB_888 = 0; + public static int S_UI8 = 0; + public static long USAGE_CPU_READ_OFTEN = 0; + public static long USAGE_CPU_READ_RARELY = 0; + public static long USAGE_CPU_WRITE_OFTEN = 0; + public static long USAGE_CPU_WRITE_RARELY = 0; + public static long USAGE_GPU_COLOR_OUTPUT = 0; + public static long USAGE_GPU_CUBE_MAP = 0; + public static long USAGE_GPU_DATA_BUFFER = 0; + public static long USAGE_GPU_MIPMAP_COMPLETE = 0; + public static long USAGE_GPU_SAMPLED_IMAGE = 0; + public static long USAGE_PROTECTED_CONTENT = 0; + public static long USAGE_SENSOR_DIRECT_DATA = 0; + public static long USAGE_VIDEO_ENCODE = 0; + public void close(){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/icu/util/ULocale.java b/java/ql/test/stubs/google-android-9.0.0/android/icu/util/ULocale.java new file mode 100644 index 00000000000..1e1ea662c22 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/icu/util/ULocale.java @@ -0,0 +1,138 @@ +// Generated automatically from android.icu.util.ULocale for testing purposes + +package android.icu.util; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; + +public class ULocale implements Comparable<ULocale>, Serializable +{ + protected ULocale() {} + public Iterator<String> getKeywords(){ return null; } + public Locale toLocale(){ return null; } + public Object clone(){ return null; } + public Set<Character> getExtensionKeys(){ return null; } + public Set<String> getUnicodeLocaleAttributes(){ return null; } + public Set<String> getUnicodeLocaleKeys(){ return null; } + public String getBaseName(){ return null; } + public String getCharacterOrientation(){ return null; } + public String getCountry(){ return null; } + public String getDisplayCountry(){ return null; } + public String getDisplayCountry(ULocale p0){ return null; } + public String getDisplayKeywordValue(String p0){ return null; } + public String getDisplayKeywordValue(String p0, ULocale p1){ return null; } + public String getDisplayLanguage(){ return null; } + public String getDisplayLanguage(ULocale p0){ return null; } + public String getDisplayLanguageWithDialect(){ return null; } + public String getDisplayLanguageWithDialect(ULocale p0){ return null; } + public String getDisplayName(){ return null; } + public String getDisplayName(ULocale p0){ return null; } + public String getDisplayNameWithDialect(){ return null; } + public String getDisplayNameWithDialect(ULocale p0){ return null; } + public String getDisplayScript(){ return null; } + public String getDisplayScript(ULocale p0){ return null; } + public String getDisplayVariant(){ return null; } + public String getDisplayVariant(ULocale p0){ return null; } + public String getExtension(char p0){ return null; } + public String getISO3Country(){ return null; } + public String getISO3Language(){ return null; } + public String getKeywordValue(String p0){ return null; } + public String getLanguage(){ return null; } + public String getLineOrientation(){ return null; } + public String getName(){ return null; } + public String getScript(){ return null; } + public String getUnicodeLocaleType(String p0){ return null; } + public String getVariant(){ return null; } + public String toLanguageTag(){ return null; } + public String toString(){ return null; } + public ULocale getFallback(){ return null; } + public ULocale setKeywordValue(String p0, String p1){ return null; } + public ULocale(String p0){} + public ULocale(String p0, String p1){} + public ULocale(String p0, String p1, String p2){} + public boolean equals(Object p0){ return false; } + public boolean isRightToLeft(){ return false; } + public int compareTo(ULocale p0){ return 0; } + public int hashCode(){ return 0; } + public static Iterator<String> getKeywords(String p0){ return null; } + public static String canonicalize(String p0){ return null; } + public static String getBaseName(String p0){ return null; } + public static String getCountry(String p0){ return null; } + public static String getDisplayCountry(String p0, String p1){ return null; } + public static String getDisplayCountry(String p0, ULocale p1){ return null; } + public static String getDisplayKeyword(String p0){ return null; } + public static String getDisplayKeyword(String p0, String p1){ return null; } + public static String getDisplayKeyword(String p0, ULocale p1){ return null; } + public static String getDisplayKeywordValue(String p0, String p1, String p2){ return null; } + public static String getDisplayKeywordValue(String p0, String p1, ULocale p2){ return null; } + public static String getDisplayLanguage(String p0, String p1){ return null; } + public static String getDisplayLanguage(String p0, ULocale p1){ return null; } + public static String getDisplayLanguageWithDialect(String p0, String p1){ return null; } + public static String getDisplayLanguageWithDialect(String p0, ULocale p1){ return null; } + public static String getDisplayName(String p0, String p1){ return null; } + public static String getDisplayName(String p0, ULocale p1){ return null; } + public static String getDisplayNameWithDialect(String p0, String p1){ return null; } + public static String getDisplayNameWithDialect(String p0, ULocale p1){ return null; } + public static String getDisplayScript(String p0, String p1){ return null; } + public static String getDisplayScript(String p0, ULocale p1){ return null; } + public static String getDisplayVariant(String p0, String p1){ return null; } + public static String getDisplayVariant(String p0, ULocale p1){ return null; } + public static String getFallback(String p0){ return null; } + public static String getISO3Country(String p0){ return null; } + public static String getISO3Language(String p0){ return null; } + public static String getKeywordValue(String p0, String p1){ return null; } + public static String getLanguage(String p0){ return null; } + public static String getName(String p0){ return null; } + public static String getScript(String p0){ return null; } + public static String getVariant(String p0){ return null; } + public static String setKeywordValue(String p0, String p1, String p2){ return null; } + public static String toLegacyKey(String p0){ return null; } + public static String toLegacyType(String p0, String p1){ return null; } + public static String toUnicodeLocaleKey(String p0){ return null; } + public static String toUnicodeLocaleType(String p0, String p1){ return null; } + public static String[] getISOCountries(){ return null; } + public static String[] getISOLanguages(){ return null; } + public static ULocale CANADA = null; + public static ULocale CANADA_FRENCH = null; + public static ULocale CHINA = null; + public static ULocale CHINESE = null; + public static ULocale ENGLISH = null; + public static ULocale FRANCE = null; + public static ULocale FRENCH = null; + public static ULocale GERMAN = null; + public static ULocale GERMANY = null; + public static ULocale ITALIAN = null; + public static ULocale ITALY = null; + public static ULocale JAPAN = null; + public static ULocale JAPANESE = null; + public static ULocale KOREA = null; + public static ULocale KOREAN = null; + public static ULocale PRC = null; + public static ULocale ROOT = null; + public static ULocale SIMPLIFIED_CHINESE = null; + public static ULocale TAIWAN = null; + public static ULocale TRADITIONAL_CHINESE = null; + public static ULocale UK = null; + public static ULocale US = null; + public static ULocale acceptLanguage(String p0, ULocale[] p1, boolean[] p2){ return null; } + public static ULocale acceptLanguage(String p0, boolean[] p1){ return null; } + public static ULocale acceptLanguage(ULocale[] p0, ULocale[] p1, boolean[] p2){ return null; } + public static ULocale acceptLanguage(ULocale[] p0, boolean[] p1){ return null; } + public static ULocale addLikelySubtags(ULocale p0){ return null; } + public static ULocale createCanonical(String p0){ return null; } + public static ULocale forLanguageTag(String p0){ return null; } + public static ULocale forLocale(Locale p0){ return null; } + public static ULocale getDefault(){ return null; } + public static ULocale getDefault(ULocale.Category p0){ return null; } + public static ULocale minimizeSubtags(ULocale p0){ return null; } + public static ULocale[] getAvailableLocales(){ return null; } + public static char PRIVATE_USE_EXTENSION = '0'; + public static char UNICODE_LOCALE_EXTENSION = '0'; + static public enum Category + { + DISPLAY, FORMAT; + private Category() {} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/net/Uri.java b/java/ql/test/stubs/google-android-9.0.0/android/net/Uri.java index 2b63354b8f2..38ad75077d6 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/net/Uri.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/net/Uri.java @@ -1,545 +1,76 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; +// Generated automatically from android.net.Uri for testing purposes -import android.content.Intent; +package android.net; import android.os.Parcel; import android.os.Parcelable; - import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.RandomAccess; import java.util.Set; -/** - * Immutable URI reference. A URI reference includes a URI and a fragment, the - * component of the URI following a '#'. Builds and parses URI references which - * conform to <a href="http://www.faqs.org/rfcs/rfc2396.html">RFC 2396</a>. - * - * <p> - * In the interest of performance, this class performs little to no validation. - * Behavior is undefined for invalid input. This class is very forgiving--in the - * face of invalid input, it will return garbage rather than throw an exception - * unless otherwise specified. - */ -public abstract class Uri implements Parcelable, Comparable<Uri> { - /* - * This class aims to do as little up front work as possible. To accomplish - * that, we vary the implementation depending on what the user passes in. For - * example, we have one implementation if the user passes in a URI string - * (StringUri) and another if the user passes in the individual components - * (OpaqueUri). Concurrency notes*: Like any truly immutable object, this class - * is safe for concurrent use. This class uses a caching pattern in some places - * where it doesn't use volatile or synchronized. This is safe to do with ints - * because getting or setting an int is atomic. It's safe to do with a String - * because the internal fields are final and the memory model guarantees other - * threads won't see a partially initialized instance. We are not guaranteed - * that some threads will immediately see changes from other threads on certain - * platforms, but we don't mind if those threads reconstruct the cached result. - * As a result, we get thread safe caching with no concurrency overhead, which - * means the most common case, access from a single thread, is as fast as - * possible. From the Java Language spec.: "17.5 Final Field Semantics ... when - * the object is seen by another thread, that thread will always see the - * correctly constructed version of that object's final fields. It will also see - * versions of any object or array referenced by those final fields that are at - * least as up-to-date as the final fields are." In that same vein, all - * non-transient fields within Uri implementations should be final and immutable - * so as to ensure true immutability for clients even when they don't use proper - * concurrency control. For reference, from RFC 2396: "4.3. Parsing a URI - * Reference A URI reference is typically parsed according to the four main - * components and fragment identifier in order to determine what components are - * present and whether the reference is relative or absolute. The individual - * components are then parsed for their subparts and, if not opaque, to verify - * their validity. Although the BNF defines what is allowed in each component, - * it is ambiguous in terms of differentiating between an authority component - * and a path component that begins with two slash characters. The greedy - * algorithm is used for disambiguation: the left-most matching rule soaks up as - * much of the URI reference string as it is capable of matching. In other - * words, the authority component wins." The "four main components" of a - * hierarchical URI consist of <scheme>://<authority><path>?<query> - */ - - /** - * NOTE: EMPTY accesses this field during its own initialization, so this field - * *must* be initialized first, or else EMPTY will see a null value! - * - * Placeholder for strings which haven't been cached. This enables us to cache - * null. We intentionally create a new String instance so we can compare its - * identity and there is no chance we will confuse it with user data. - */ - - /** - * Returns true if this URI is hierarchical like "http://google.com". Absolute - * URIs are hierarchical if the scheme-specific part starts with a '/'. Relative - * URIs are always hierarchical. - */ - public abstract boolean isHierarchical(); - - /** - * Returns true if this URI is opaque like "mailto:nobody@google.com". The - * scheme-specific part of an opaque URI cannot start with a '/'. - */ - public boolean isOpaque() { - return false; - } - - /** - * Returns true if this URI is relative, i.e. if it doesn't contain an - * explicit scheme. - * - * @return true if this URI is relative, false if it's absolute - */ - public abstract boolean isRelative(); - - /** - * Returns true if this URI is absolute, i.e. if it contains an explicit - * scheme. - * - * @return true if this URI is absolute, false if it's relative - */ - public boolean isAbsolute() { - return !isRelative(); - } - - /** - * Gets the scheme of this URI. Example: "http" - * - * @return the scheme or null if this is a relative URI - */ - public abstract String getScheme(); - - /** - * Gets the scheme-specific part of this URI, i.e. everything between the - * scheme separator ':' and the fragment separator '#'. If this is a relative - * URI, this method returns the entire URI. Decodes escaped octets. - * - * <p> - * Example: "//www.google.com/search?q=android" - * - * @return the decoded scheme-specific-part - */ - public abstract String getSchemeSpecificPart(); - - /** - * Gets the scheme-specific part of this URI, i.e. everything between the - * scheme separator ':' and the fragment separator '#'. If this is a relative - * URI, this method returns the entire URI. Leaves escaped octets intact. - * - * <p> - * Example: "//www.google.com/search?q=android" - * - * @return the decoded scheme-specific-part - */ - public abstract String getEncodedSchemeSpecificPart(); - - /** - * Gets the decoded authority part of this URI. For server addresses, the - * authority is structured as follows: - * {@code [ userinfo '@' ] host [ ':' port ]} - * - * <p> - * Examples: "google.com", "bob@google.com:80" - * - * @return the authority for this URI or null if not present - */ - public abstract String getAuthority(); - - /** - * Gets the encoded authority part of this URI. For server addresses, the - * authority is structured as follows: - * {@code [ userinfo '@' ] host [ ':' port ]} - * - * <p> - * Examples: "google.com", "bob@google.com:80" - * - * @return the authority for this URI or null if not present - */ - public abstract String getEncodedAuthority(); - - /** - * Gets the decoded user information from the authority. For example, if the - * authority is "nobody@google.com", this method will return "nobody". - * - * @return the user info for this URI or null if not present - */ - public abstract String getUserInfo(); - - /** - * Gets the encoded user information from the authority. For example, if the - * authority is "nobody@google.com", this method will return "nobody". - * - * @return the user info for this URI or null if not present - */ - public abstract String getEncodedUserInfo(); - - /** - * Gets the encoded host from the authority for this URI. For example, if the - * authority is "bob@google.com", this method will return "google.com". - * - * @return the host for this URI or null if not present - */ - public abstract String getHost(); - - /** - * Gets the port from the authority for this URI. For example, if the authority - * is "google.com:80", this method will return 80. - * - * @return the port for this URI or -1 if invalid or not present - */ - public abstract int getPort(); - - /** - * Gets the decoded path. - * - * @return the decoded path, or null if this is not a hierarchical URI (like - * "mailto:nobody@google.com") or the URI is invalid - */ - public abstract String getPath(); - - /** - * Gets the encoded path. - * - * @return the encoded path, or null if this is not a hierarchical URI (like - * "mailto:nobody@google.com") or the URI is invalid - */ - public abstract String getEncodedPath(); - - /** - * Gets the decoded query component from this URI. The query comes after the - * query separator ('?') and before the fragment separator ('#'). This method - * would return "q=android" for "http://www.google.com/search?q=android". - * - * @return the decoded query or null if there isn't one - */ - public abstract String getQuery(); - - /** - * Gets the encoded query component from this URI. The query comes after the - * query separator ('?') and before the fragment separator ('#'). This method - * would return "q=android" for "http://www.google.com/search?q=android". - * - * @return the encoded query or null if there isn't one - */ - public abstract String getEncodedQuery(); - - /** - * Gets the decoded fragment part of this URI, everything after the '#'. - * - * @return the decoded fragment or null if there isn't one - */ - public abstract String getFragment(); - - /** - * Gets the encoded fragment part of this URI, everything after the '#'. - * - * @return the encoded fragment or null if there isn't one - */ - public abstract String getEncodedFragment(); - - /** - * Gets the decoded path segments. - * - * @return decoded path segments, each without a leading or trailing '/' - */ +abstract public class Uri implements Comparable<Uri>, Parcelable +{ + public List<String> getQueryParameters(String p0){ return null; } + public Set<String> getQueryParameterNames(){ return null; } + public String getQueryParameter(String p0){ return null; } + public Uri normalizeScheme(){ return null; } public abstract List<String> getPathSegments(); - - /** - * Gets the decoded last segment in the path. - * - * @return the decoded last segment or null if the path is empty - */ + public abstract String getAuthority(); + public abstract String getEncodedAuthority(); + public abstract String getEncodedFragment(); + public abstract String getEncodedPath(); + public abstract String getEncodedQuery(); + public abstract String getEncodedSchemeSpecificPart(); + public abstract String getEncodedUserInfo(); + public abstract String getFragment(); + public abstract String getHost(); public abstract String getLastPathSegment(); - - /** - * Compares this Uri to another object for equality. Returns true if the encoded - * string representations of this Uri and the given Uri are equal. Case counts. - * Paths are not normalized. If one Uri specifies a default port explicitly and - * the other leaves it implicit, they will not be considered equal. - */ - public boolean equals(Object o) { - return false; - } - - /** - * Hashes the encoded string represention of this Uri consistently with - * {@link #equals(Object)}. - */ - public int hashCode() { - return -1; - } - - /** - * Compares the string representation of this Uri with that of another. - */ - public int compareTo(Uri other) { - return -1; - } - - /** - * Returns the encoded string representation of this URI. Example: - * "http://google.com/" - */ + public abstract String getPath(); + public abstract String getQuery(); + public abstract String getScheme(); + public abstract String getSchemeSpecificPart(); + public abstract String getUserInfo(); public abstract String toString(); - - /** - * Return a string representation of the URI that is safe to print to logs and - * other places where PII should be avoided. - * - * @hide - */ - public String toSafeString() { - return null; - } - - /** - * Creates a Uri which parses the given encoded URI string. - * - * @param uriString an RFC 2396-compliant, encoded URI - * @throws NullPointerException if uriString is null - * @return Uri for this given uri string - */ - public static Uri parse(String uriString) { - return null; - } - - /** - * Creates a Uri from a file. The URI has the form "file://<absolute path>". - * Encodes path characters with the exception of '/'. - * - * <p> - * Example: "file:///tmp/android.txt" - * - * @throws NullPointerException if file is null - * @return a Uri for the given file - */ - public static Uri fromFile(File file) { - return null; - } - - /** - * Creates an opaque Uri from the given components. Encodes the ssp which means - * this method cannot be used to create hierarchical URIs. - * - * @param scheme of the URI - * @param ssp scheme-specific-part, everything between the scheme separator - * (':') and the fragment separator ('#'), which will get - * encoded - * @param fragment fragment, everything after the '#', null if undefined, will - * get encoded - * - * @throws NullPointerException if scheme or ssp is null - * @return Uri composed of the given scheme, ssp, and fragment - * - * @see Builder if you don't want the ssp and fragment to be encoded - */ - public static Uri fromParts(String scheme, String ssp, String fragment) { - return null; - } - - /** - * Returns a set of the unique names of all query parameters. Iterating over the - * set will return the names in order of their first occurrence. - * - * @throws UnsupportedOperationException if this isn't a hierarchical URI - * - * @return a set of decoded names - */ - public Set<String> getQueryParameterNames() { - return null; - } - - /** - * Searches the query string for parameter values with the given key. - * - * @param key which will be encoded - * - * @throws UnsupportedOperationException if this isn't a hierarchical URI - * @throws NullPointerException if key is null - * @return a list of decoded values - */ - public List<String> getQueryParameters(String key) { - return null; - } - - /** - * Searches the query string for the first value with the given key. - * - * <p> - * <strong>Warning:</strong> Prior to Jelly Bean, this decoded the '+' character - * as '+' rather than ' '. - * - * @param key which will be encoded - * @throws UnsupportedOperationException if this isn't a hierarchical URI - * @throws NullPointerException if key is null - * @return the decoded value or null if no parameter is found - */ - public String getQueryParameter(String key) { - return null; - } - - /** - * Searches the query string for the first value with the given key and - * interprets it as a boolean value. "false" and "0" are interpreted as - * <code>false</code>, everything else is interpreted as <code>true</code>. - * - * @param key which will be decoded - * @param defaultValue the default value to return if there is no query - * parameter for key - * @return the boolean interpretation of the query parameter key - */ - public boolean getBooleanQueryParameter(String key, boolean defaultValue) { - return false; - } - - /** - * Return an equivalent URI with a lowercase scheme component. This aligns the - * Uri with Android best practices for intent filtering. - * - * <p> - * For example, "HTTP://www.android.com" becomes "http://www.android.com" - * - * <p> - * All URIs received from outside Android (such as user input, or external - * sources like Bluetooth, NFC, or the Internet) should be normalized before - * they are used to create an Intent. - * - * <p class="note"> - * This method does <em>not</em> validate bad URI's, or 'fix' poorly formatted - * URI's - so do not use it for input validation. A Uri will always be returned, - * even if the Uri is badly formatted to begin with and a scheme component - * cannot be found. - * - * @return normalized Uri (never null) - * @see android.content.Intent#setData - * @see android.content.Intent#setDataAndNormalize - */ - public Uri normalizeScheme() { - return null; - } - - /** - * Writes a Uri to a Parcel. - * - * @param out parcel to write to - * @param uri to write, can be null - */ - public static void writeToParcel(Parcel out, Uri uri) { - } - - /** - * Encodes characters in the given string as '%'-escaped octets using the UTF-8 - * scheme. Leaves letters ("A-Z", "a-z"), numbers ("0-9"), and unreserved - * characters ("_-!.~'()*") intact. Encodes all other characters. - * - * @param s string to encode - * @return an encoded version of s suitable for use as a URI component, or null - * if s is null - */ - public static String encode(String s) { - return null; - } - - /** - * Encodes characters in the given string as '%'-escaped octets using the UTF-8 - * scheme. Leaves letters ("A-Z", "a-z"), numbers ("0-9"), and unreserved - * characters ("_-!.~'()*") intact. Encodes all other characters with the - * exception of those specified in the allow argument. - * - * @param s string to encode - * @param allow set of additional characters to allow in the encoded form, null - * if no characters should be skipped - * @return an encoded version of s suitable for use as a URI component, or null - * if s is null - */ - public static String encode(String s, String allow) { - return null; - } - - /** - * Decodes '%'-escaped octets in the given string using the UTF-8 scheme. - * Replaces invalid octets with the unicode replacement character ("\\uFFFD"). - * - * @param s encoded string to decode - * @return the given string with escaped octets decoded, or null if s is null - */ - public static String decode(String s) { - return null; - } - - /** - * Creates a new Uri by appending an already-encoded path segment to a base Uri. - * - * @param baseUri Uri to append path segment to - * @param pathSegment encoded path segment to append - * @return a new Uri based on baseUri with the given segment appended to the - * path - * @throws NullPointerException if baseUri is null - */ - public static Uri withAppendedPath(Uri baseUri, String pathSegment) { - return null; - } - - /** - * If this {@link Uri} is {@code file://}, then resolve and return its canonical - * path. Also fixes legacy emulated storage paths so they are usable across user - * boundaries. Should always be called from the app process before sending - * elsewhere. - * - * @hide - */ - public Uri getCanonicalUri() { - return null; - } - - /** - * If this is a {@code file://} Uri, it will be reported to {@link StrictMode}. - * - * @hide - */ - public void checkFileUriExposed(String location) { - } - - /** - * If this is a {@code content://} Uri without access flags, it will be reported - * to {@link StrictMode}. - * - * @hide - */ - public void checkContentUriWithoutPermission(String location, int flags) { - } - - /** - * Test if this is a path prefix match against the given Uri. Verifies that - * scheme, authority, and atomic path segments match. - * - * @hide - */ - public boolean isPathPrefixMatch(Uri prefix) { - return false; + public abstract Uri.Builder buildUpon(); + public abstract boolean isHierarchical(); + public abstract boolean isRelative(); + public abstract int getPort(); + public boolean equals(Object p0){ return false; } + public boolean getBooleanQueryParameter(String p0, boolean p1){ return false; } + public boolean isAbsolute(){ return false; } + public boolean isOpaque(){ return false; } + public int compareTo(Uri p0){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<Uri> CREATOR = null; + public static String decode(String p0){ return null; } + public static String encode(String p0){ return null; } + public static String encode(String p0, String p1){ return null; } + public static Uri EMPTY = null; + public static Uri fromFile(File p0){ return null; } + public static Uri fromParts(String p0, String p1, String p2){ return null; } + public static Uri parse(String p0){ return null; } + public static Uri withAppendedPath(Uri p0, String p1){ return null; } + public static void writeToParcel(Parcel p0, Uri p1){} + static public class Builder + { + public Builder(){} + public String toString(){ return null; } + public Uri build(){ return null; } + public Uri.Builder appendEncodedPath(String p0){ return null; } + public Uri.Builder appendPath(String p0){ return null; } + public Uri.Builder appendQueryParameter(String p0, String p1){ return null; } + public Uri.Builder authority(String p0){ return null; } + public Uri.Builder clearQuery(){ return null; } + public Uri.Builder encodedAuthority(String p0){ return null; } + public Uri.Builder encodedFragment(String p0){ return null; } + public Uri.Builder encodedOpaquePart(String p0){ return null; } + public Uri.Builder encodedPath(String p0){ return null; } + public Uri.Builder encodedQuery(String p0){ return null; } + public Uri.Builder fragment(String p0){ return null; } + public Uri.Builder opaquePart(String p0){ return null; } + public Uri.Builder path(String p0){ return null; } + public Uri.Builder query(String p0){ return null; } + public Uri.Builder scheme(String p0){ return null; } } public Builder buildUpon() { return null; } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/BaseBundle.java b/java/ql/test/stubs/google-android-9.0.0/android/os/BaseBundle.java index 3ac33642ab4..3cc3c310c38 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/os/BaseBundle.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/BaseBundle.java @@ -1,832 +1,43 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.os.BaseBundle for testing purposes + package android.os; -import java.io.Serializable; -import java.util.ArrayList; +import android.os.PersistableBundle; import java.util.Set; -/** - * A mapping from String keys to values of various types. In most cases, you - * should work directly with either the {@link Bundle} or - * {@link PersistableBundle} subclass. - */ -public class BaseBundle { - /** - * Constructs a new, empty Bundle that uses a specific ClassLoader for - * instantiating Parcelable and Serializable objects. - * - * @param loader An explicit ClassLoader to use when instantiating objects - * inside of the Bundle. - * @param capacity Initial size of the ArrayMap. - */ - BaseBundle(ClassLoader loader, int capacity) { - } - - /** - * Constructs a new, empty Bundle. - */ - BaseBundle() { - } - - /** - * Constructs a Bundle whose data is stored as a Parcel. The data will be - * unparcelled on first contact, using the assigned ClassLoader. - * - * @param parcelledData a Parcel containing a Bundle - */ - BaseBundle(Parcel parcelledData) { - } - - BaseBundle(Parcel parcelledData, int length) { - } - - /** - * Constructs a new, empty Bundle that uses a specific ClassLoader for - * instantiating Parcelable and Serializable objects. - * - * @param loader An explicit ClassLoader to use when instantiating objects - * inside of the Bundle. - */ - BaseBundle(ClassLoader loader) { - } - - /** - * Constructs a new, empty Bundle sized to hold the given number of elements. - * The Bundle will grow as needed. - * - * @param capacity the initial capacity of the Bundle - */ - BaseBundle(int capacity) { - } - - /** - * Constructs a Bundle containing a copy of the mappings from the given Bundle. - * - * @param b a Bundle to be copied. - */ - BaseBundle(BaseBundle b) { - } - - /** - * Special constructor that does not initialize the bundle. - */ - BaseBundle(boolean doInit) { - } - - /** - * TODO: optimize this later (getting just the value part of a Bundle with a - * single pair) once Bundle.forPair() above is implemented with a special - * single-value Map implementation/serialization. - * - * Note: value in single-pair Bundle may be null. - * - * @hide - */ - public String getPairValue() { - return null; - } - - /** - * Changes the ClassLoader this Bundle uses when instantiating objects. - * - * @param loader An explicit ClassLoader to use when instantiating objects - * inside of the Bundle. - */ - void setClassLoader(ClassLoader loader) { - } - - /** - * Return the ClassLoader currently associated with this Bundle. - */ - ClassLoader getClassLoader() { - return null; - } - - /** - * @hide - */ - public boolean isParcelled() { - return false; - } - - /** - * @hide - */ - public boolean isEmptyParcel() { - return false; - } - - /** - * Returns true if the given key is contained in the mapping - * of this Bundle. - * - * @param key a String key - * @return true if the key is part of the mapping, false otherwise - */ - public boolean containsKey(String key) { - return false; - } - - /** - * Returns the entry with the given key as an object. - * - * @param key a String key - * @return an Object, or null - */ - public Object get(String key) { - return null; - } - - /** - * Removes any entry with the given key from the mapping of this Bundle. - * - * @param key a String key - */ - public void remove(String key) { - } - - /** {@hide} */ - public void putObject(String key, Object value) { - } - - /** - * Inserts a Boolean value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a boolean - */ - public void putBoolean(String key, boolean value) { - } - - /** - * Inserts a byte value into the mapping of this Bundle, replacing - * any existing value for the given key. - * - * @param key a String, or null - * @param value a byte - */ - void putByte(String key, byte value) { - } - - /** - * Inserts a char value into the mapping of this Bundle, replacing - * any existing value for the given key. - * - * @param key a String, or null - * @param value a char - */ - void putChar(String key, char value) { - } - - /** - * Inserts a short value into the mapping of this Bundle, replacing - * any existing value for the given key. - * - * @param key a String, or null - * @param value a short - */ - void putShort(String key, short value) { - } - - /** - * Inserts an int value into the mapping of this Bundle, replacing - * any existing value for the given key. - * - * @param key a String, or null - * @param value an int - */ - public void putInt(String key, int value) { - } - - /** - * Inserts a long value into the mapping of this Bundle, replacing - * any existing value for the given key. - * - * @param key a String, or null - * @param value a long - */ - public void putLong(String key, long value) { - } - - /** - * Inserts a float value into the mapping of this Bundle, replacing - * any existing value for the given key. - * - * @param key a String, or null - * @param value a float - */ - void putFloat(String key, float value) { - } - - /** - * Inserts a double value into the mapping of this Bundle, replacing - * any existing value for the given key. - * - * @param key a String, or null - * @param value a double - */ - public void putDouble(String key, double value) { - } - - /** - * Inserts a String value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a String, or null - */ - public void putString(String key, String value) { - } - - /** - * Inserts a CharSequence value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a CharSequence, or null - */ - void putCharSequence(String key, CharSequence value) { - } - - /** - * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value an ArrayList<Integer> object, or null - */ - void putIntegerArrayList(String key, ArrayList<Integer> value) { - } - - /** - * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value an ArrayList<String> object, or null - */ - void putStringArrayList(String key, ArrayList<String> value) { - } - - - /** - * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, - * replacing any existing value for the given key. Either key or value may be - * null. - * - * @param key a String, or null - * @param value an ArrayList<CharSequence> object, or null - */ - void putCharSequenceArrayList(String key, ArrayList<CharSequence> value) { - } - - /** - * Inserts a Serializable value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a Serializable object, or null - */ - void putSerializable(String key, Serializable value) { - } - - /** - * Inserts a boolean array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a boolean array object, or null - */ - public void putBooleanArray(String key, boolean[] value) { - } - - /** - * Inserts a byte array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a byte array object, or null - */ - void putByteArray(String key, byte[] value) { - } - - /** - * Inserts a short array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a short array object, or null - */ - void putShortArray(String key, short[] value) { - } - - /** - * Inserts a char array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a char array object, or null - */ - void putCharArray(String key, char[] value) { - } - - /** - * Inserts an int array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value an int array object, or null - */ - public void putIntArray(String key, int[] value) { - } - - /** - * Inserts a long array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a long array object, or null - */ - public void putLongArray(String key, long[] value) { - } - - /** - * Inserts a float array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a float array object, or null - */ - void putFloatArray(String key, float[] value) { - } - - /** - * Inserts a double array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a double array object, or null - */ - public void putDoubleArray(String key, double[] value) { - } - - /** - * Inserts a String array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a String array object, or null - */ - public void putStringArray(String key, String[] value) { - } - - /** - * Inserts a CharSequence array value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a CharSequence array object, or null - */ - void putCharSequenceArray(String key, CharSequence[] value) { - } - - /** - * Returns the value associated with the given key, or false if no mapping of - * the desired type exists for the given key. - * - * @param key a String - * @return a boolean value - */ - public boolean getBoolean(String key) { - return false; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a boolean value - */ - public boolean getBoolean(String key, boolean defaultValue) { - return false; - } - - /** - * Returns the value associated with the given key, or (byte) 0 if no mapping of - * the desired type exists for the given key. - * - * @param key a String - * @return a byte value - */ - byte getByte(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a byte value - */ - Byte getByte(String key, byte defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or (char) 0 if no mapping of - * the desired type exists for the given key. - * - * @param key a String - * @return a char value - */ - char getChar(String key) { - return 'a'; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a char value - */ - char getChar(String key, char defaultValue) { - return 'a'; - } - - /** - * Returns the value associated with the given key, or (short) 0 if no mapping - * of the desired type exists for the given key. - * - * @param key a String - * @return a short value - */ - short getShort(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a short value - */ - short getShort(String key, short defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or 0 if no mapping of the - * desired type exists for the given key. - * - * @param key a String - * @return an int value - */ - public int getInt(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return an int value - */ - public int getInt(String key, int defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or 0L if no mapping of the - * desired type exists for the given key. - * - * @param key a String - * @return a long value - */ - public long getLong(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a long value - */ - public long getLong(String key, long defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or 0.0f if no mapping of the - * desired type exists for the given key. - * - * @param key a String - * @return a float value - */ - float getFloat(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a float value - */ - float getFloat(String key, float defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or 0.0 if no mapping of the - * desired type exists for the given key. - * - * @param key a String - * @return a double value - */ - public double getDouble(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a double value - */ - public double getDouble(String key, double defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a String value, or null - */ - public String getString(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key or if a null value is - * explicitly associated with the given key. - * - * @param key a String, or null - * @param defaultValue Value to return if key does not exist or if a null value - * is associated with the given key. - * @return the String value associated with the given key, or defaultValue if no - * valid String object is currently mapped to that key. - */ - public String getString(String key, String defaultValue) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a CharSequence value, or null - */ - CharSequence getCharSequence(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key or if a null value is - * explicitly associated with the given key. - * - * @param key a String, or null - * @param defaultValue Value to return if key does not exist or if a null value - * is associated with the given key. - * @return the CharSequence value associated with the given key, or defaultValue - * if no valid CharSequence object is currently mapped to that key. - */ - CharSequence getCharSequence(String key, CharSequence defaultValue) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a Serializable value, or null - */ - Serializable getSerializable(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return an ArrayList<String> value, or null - */ - ArrayList<Integer> getIntegerArrayList(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return an ArrayList<String> value, or null - */ - ArrayList<String> getStringArrayList(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return an ArrayList<CharSequence> value, or null - */ - ArrayList<CharSequence> getCharSequenceArrayList(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a boolean[] value, or null - */ - public boolean[] getBooleanArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a byte[] value, or null - */ - byte[] getByteArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a short[] value, or null - */ - short[] getShortArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a char[] value, or null - */ - char[] getCharArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return an int[] value, or null - */ - public int[] getIntArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a long[] value, or null - */ - public long[] getLongArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a float[] value, or null - */ - float[] getFloatArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a double[] value, or null - */ - public double[] getDoubleArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a String[] value, or null - */ - public String[] getStringArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a CharSequence[] value, or null - */ - CharSequence[] getCharSequenceArray(String key) { - return null; - } - - /** - * Writes the Bundle contents to a Parcel, typically in order for it to be - * passed through an IBinder connection. - * - * @param parcel The parcel to copy this bundle to. - */ - void writeToParcelInner(Parcel parcel, int flags) { - } - - /** - * Reads the Parcel contents into this Bundle, typically in order for it to be - * passed through an IBinder connection. - * - * @param parcel The parcel to overwrite this bundle from. - */ - void readFromParcelInner(Parcel parcel) { - } - +public class BaseBundle +{ + public Object get(String p0){ return null; } + public Set<String> keySet(){ return null; } + public String getString(String p0){ return null; } + public String getString(String p0, String p1){ return null; } + public String[] getStringArray(String p0){ return null; } + public boolean containsKey(String p0){ return false; } + public boolean getBoolean(String p0){ return false; } + public boolean getBoolean(String p0, boolean p1){ return false; } + public boolean isEmpty(){ return false; } + public boolean[] getBooleanArray(String p0){ return null; } + public double getDouble(String p0){ return 0; } + public double getDouble(String p0, double p1){ return 0; } + public double[] getDoubleArray(String p0){ return null; } + public int getInt(String p0){ return 0; } + public int getInt(String p0, int p1){ return 0; } + public int size(){ return 0; } + public int[] getIntArray(String p0){ return null; } + public long getLong(String p0){ return 0; } + public long getLong(String p0, long p1){ return 0; } + public long[] getLongArray(String p0){ return null; } + public void clear(){} + public void putAll(PersistableBundle p0){} + public void putBoolean(String p0, boolean p1){} + public void putBooleanArray(String p0, boolean[] p1){} + public void putDouble(String p0, double p1){} + public void putDoubleArray(String p0, double[] p1){} + public void putInt(String p0, int p1){} + public void putIntArray(String p0, int[] p1){} + public void putLong(String p0, long p1){} + public void putLongArray(String p0, long[] p1){} + public void putString(String p0, String p1){} + public void putStringArray(String p0, String[] p1){} + public void remove(String p0){} } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Bundle.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Bundle.java index d109f766c77..4beb1cf5dee 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/os/Bundle.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Bundle.java @@ -1,511 +1,86 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.os.Bundle for testing purposes + package android.os; +import android.os.BaseBundle; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; +import android.util.Size; +import android.util.SizeF; +import android.util.SparseArray; import java.io.Serializable; import java.util.ArrayList; -import java.util.List; -/** - * A mapping from String keys to various {@link Parcelable} values. - * - * @see PersistableBundle - */ -public final class Bundle extends BaseBundle implements Cloneable, Parcelable { - - /** - * Constructs a new, empty Bundle. - */ - public Bundle() { - super(); - } - - /** - * Removes all elements from the mapping of this Bundle. - */ - public void clear() { - } - - /** - * Removes any entry with the given key from the mapping of this Bundle. - * - * @param key a String key - */ - public void remove(String key) { - } - - /** - * Inserts all mappings from the given Bundle into this Bundle. - * - * @param bundle a Bundle - */ - public void putAll(Bundle bundle) { - } - - /** - * Return the size of {@link #mParcelledData} in bytes if available, otherwise - * {@code 0}. - * - * @hide - */ - public int getSize() { - return -1; - } - - /** - * Inserts a byte value into the mapping of this Bundle, replacing any existing - * value for the given key. - * - * @param key a String, or null - * @param value a byte - */ - public void putByte(String key, byte value) { - } - - /** - * Inserts a char value into the mapping of this Bundle, replacing any existing - * value for the given key. - * - * @param key a String, or null - * @param value a char - */ - public void putChar(String key, char value) { - } - - /** - * Inserts a short value into the mapping of this Bundle, replacing any existing - * value for the given key. - * - * @param key a String, or null - * @param value a short - */ - public void putShort(String key, short value) { - } - - /** - * Inserts a float value into the mapping of this Bundle, replacing any existing - * value for the given key. - * - * @param key a String, or null - * @param value a float - */ - public void putFloat(String key, float value) { - } - - /** - * Inserts a CharSequence value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a CharSequence, or null - */ - public void putCharSequence(String key, CharSequence value) { - } - - /** - * Inserts an ArrayList<Integer> value into the mapping of this Bundle, - * replacing any existing value for the given key. Either key or value may be - * null. - * - * @param key a String, or null - * @param value an ArrayList<Integer> object, or null - */ - public void putIntegerArrayList(String key, ArrayList<Integer> value) { - } - - /** - * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value an ArrayList<String> object, or null - */ - public void putStringArrayList(String key, ArrayList<String> value) { - } - - /** - * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, - * replacing any existing value for the given key. Either key or value may be - * null. - * - * @param key a String, or null - * @param value an ArrayList<CharSequence> object, or null - */ - public void putCharSequenceArrayList(String key, ArrayList<CharSequence> value) { - } - - /** - * Inserts a Serializable value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a Serializable object, or null - */ - public void putSerializable(String key, Serializable value) { - } - - /** - * Inserts a byte array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a byte array object, or null - */ - public void putByteArray(String key, byte[] value) { - } - - /** - * Inserts a short array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a short array object, or null - */ - public void putShortArray(String key, short[] value) { - } - - /** - * Inserts a char array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a char array object, or null - */ - public void putCharArray(String key, char[] value) { - } - - /** - * Inserts a float array value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a float array object, or null - */ - public void putFloatArray(String key, float[] value) { - } - - /** - * Inserts a CharSequence array value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a CharSequence array object, or null - */ - public void putCharSequenceArray(String key, CharSequence[] value) { - } - - /** - * Inserts a Bundle value into the mapping of this Bundle, replacing any - * existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a Bundle object, or null - */ - public void putBundle(String key, Bundle value) { - } - - /** - * Returns the value associated with the given key, or (byte) 0 if no mapping of - * the desired type exists for the given key. - * - * @param key a String - * @return a byte value - */ - public byte getByte(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a byte value - */ - public Byte getByte(String key, byte defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or (char) 0 if no mapping of - * the desired type exists for the given key. - * - * @param key a String - * @return a char value - */ - public char getChar(String key) { - return 'a'; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a char value - */ - public char getChar(String key, char defaultValue) { - return 'a'; - } - - /** - * Returns the value associated with the given key, or (short) 0 if no mapping - * of the desired type exists for the given key. - * - * @param key a String - * @return a short value - */ - public short getShort(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a short value - */ - public short getShort(String key, short defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or 0.0f if no mapping of the - * desired type exists for the given key. - * - * @param key a String - * @return a float value - */ - public float getFloat(String key) { - return -1; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a float value - */ - public float getFloat(String key, float defaultValue) { - return -1; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a CharSequence value, or null - */ - public CharSequence getCharSequence(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or defaultValue if no - * mapping of the desired type exists for the given key or if a null value is - * explicitly associatd with the given key. - * - * @param key a String, or null - * @param defaultValue Value to return if key does not exist or if a null value - * is associated with the given key. - * @return the CharSequence value associated with the given key, or defaultValue - * if no valid CharSequence object is currently mapped to that key. - */ - public CharSequence getCharSequence(String key, CharSequence defaultValue) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a Bundle value, or null - */ - public Bundle getBundle(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if - * no mapping of the desired type exists for the given key or a null - * value is explicitly associated with the key. - * - * @param key a String, or null - * @return a Parcelable value, or null - */ - public <T extends Parcelable> T getParcelable(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return an ArrayList<T> value, or null - */ - public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a Serializable value, or null - */ - public Serializable getSerializable(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return an ArrayList<String> value, or null - */ - public ArrayList<Integer> getIntegerArrayList(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return an ArrayList<String> value, or null - */ - public ArrayList<String> getStringArrayList(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return an ArrayList<CharSequence> value, or null - */ - public ArrayList<CharSequence> getCharSequenceArrayList(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a byte[] value, or null - */ - public byte[] getByteArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a short[] value, or null - */ - public short[] getShortArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a char[] value, or null - */ - public char[] getCharArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a float[] value, or null - */ - public float[] getFloatArray(String key) { - return null; - } - - /** - * Returns the value associated with the given key, or null if no mapping of the - * desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key a String, or null - * @return a CharSequence[] value, or null - */ - public CharSequence[] getCharSequenceArray(String key) { - return null; - } - - /** - * Writes the Bundle contents to a Parcel, typically in order for it to be - * passed through an IBinder connection. - * - * @param parcel The parcel to copy this bundle to. - */ - public void writeToParcel(Parcel parcel, int flags) { - } - - /** - * Reads the Parcel contents into this Bundle, typically in order for it to be - * passed through an IBinder connection. - * - * @param parcel The parcel to overwrite this bundle from. - */ - public void readFromParcel(Parcel parcel) { - } - - public synchronized String toString() { - return null; - } - - /** - * @hide - */ - public synchronized String toShortString() { - return null; - } -} \ No newline at end of file +public class Bundle extends BaseBundle implements Cloneable, Parcelable +{ + public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String p0){ return null; } + public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(String p0){ return null; } + public <T extends Parcelable> T getParcelable(String p0){ return null; } + public ArrayList<CharSequence> getCharSequenceArrayList(String p0){ return null; } + public ArrayList<Integer> getIntegerArrayList(String p0){ return null; } + public ArrayList<String> getStringArrayList(String p0){ return null; } + public Bundle deepCopy(){ return null; } + public Bundle getBundle(String p0){ return null; } + public Bundle(){} + public Bundle(Bundle p0){} + public Bundle(ClassLoader p0){} + public Bundle(PersistableBundle p0){} + public Bundle(int p0){} + public Byte getByte(String p0, byte p1){ return null; } + public CharSequence getCharSequence(String p0){ return null; } + public CharSequence getCharSequence(String p0, CharSequence p1){ return null; } + public CharSequence[] getCharSequenceArray(String p0){ return null; } + public ClassLoader getClassLoader(){ return null; } + public IBinder getBinder(String p0){ return null; } + public Object clone(){ return null; } + public Parcelable[] getParcelableArray(String p0){ return null; } + public Serializable getSerializable(String p0){ return null; } + public Size getSize(String p0){ return null; } + public SizeF getSizeF(String p0){ return null; } + public String toString(){ return null; } + public boolean hasFileDescriptors(){ return false; } + public byte getByte(String p0){ return 0; } + public byte[] getByteArray(String p0){ return null; } + public char getChar(String p0){ return '0'; } + public char getChar(String p0, char p1){ return '0'; } + public char[] getCharArray(String p0){ return null; } + public float getFloat(String p0){ return 0; } + public float getFloat(String p0, float p1){ return 0; } + public float[] getFloatArray(String p0){ return null; } + public int describeContents(){ return 0; } + public short getShort(String p0){ return 0; } + public short getShort(String p0, short p1){ return 0; } + public short[] getShortArray(String p0){ return null; } + public static Bundle EMPTY = null; + public static Parcelable.Creator<Bundle> CREATOR = null; + public void clear(){} + public void putAll(Bundle p0){} + public void putBinder(String p0, IBinder p1){} + public void putBundle(String p0, Bundle p1){} + public void putByte(String p0, byte p1){} + public void putByteArray(String p0, byte[] p1){} + public void putChar(String p0, char p1){} + public void putCharArray(String p0, char[] p1){} + public void putCharSequence(String p0, CharSequence p1){} + public void putCharSequenceArray(String p0, CharSequence[] p1){} + public void putCharSequenceArrayList(String p0, ArrayList<CharSequence> p1){} + public void putFloat(String p0, float p1){} + public void putFloatArray(String p0, float[] p1){} + public void putIntegerArrayList(String p0, ArrayList<Integer> p1){} + public void putParcelable(String p0, Parcelable p1){} + public void putParcelableArray(String p0, Parcelable[] p1){} + public void putParcelableArrayList(String p0, ArrayList<? extends Parcelable> p1){} + public void putSerializable(String p0, Serializable p1){} + public void putShort(String p0, short p1){} + public void putShortArray(String p0, short[] p1){} + public void putSize(String p0, Size p1){} + public void putSizeF(String p0, SizeF p1){} + public void putSparseParcelableArray(String p0, SparseArray<? extends Parcelable> p1){} + public void putStringArrayList(String p0, ArrayList<String> p1){} + public void readFromParcel(Parcel p0){} + public void remove(String p0){} + public void setClassLoader(ClassLoader p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Handler.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Handler.java new file mode 100644 index 00000000000..5d1ae91db88 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Handler.java @@ -0,0 +1,53 @@ +// Generated automatically from android.os.Handler for testing purposes + +package android.os; + +import android.os.Looper; +import android.os.Message; +import android.util.Printer; + +public class Handler +{ + public Handler(){} + public Handler(Handler.Callback p0){} + public Handler(Looper p0){} + public Handler(Looper p0, Handler.Callback p1){} + public String getMessageName(Message p0){ return null; } + public String toString(){ return null; } + public boolean sendMessageAtTime(Message p0, long p1){ return false; } + public final Looper getLooper(){ return null; } + public final Message obtainMessage(){ return null; } + public final Message obtainMessage(int p0){ return null; } + public final Message obtainMessage(int p0, Object p1){ return null; } + public final Message obtainMessage(int p0, int p1, int p2){ return null; } + public final Message obtainMessage(int p0, int p1, int p2, Object p3){ return null; } + public final boolean hasCallbacks(Runnable p0){ return false; } + public final boolean hasMessages(int p0){ return false; } + public final boolean hasMessages(int p0, Object p1){ return false; } + public final boolean post(Runnable p0){ return false; } + public final boolean postAtFrontOfQueue(Runnable p0){ return false; } + public final boolean postAtTime(Runnable p0, Object p1, long p2){ return false; } + public final boolean postAtTime(Runnable p0, long p1){ return false; } + public final boolean postDelayed(Runnable p0, Object p1, long p2){ return false; } + public final boolean postDelayed(Runnable p0, long p1){ return false; } + public final boolean sendEmptyMessage(int p0){ return false; } + public final boolean sendEmptyMessageAtTime(int p0, long p1){ return false; } + public final boolean sendEmptyMessageDelayed(int p0, long p1){ return false; } + public final boolean sendMessage(Message p0){ return false; } + public final boolean sendMessageAtFrontOfQueue(Message p0){ return false; } + public final boolean sendMessageDelayed(Message p0, long p1){ return false; } + public final void dump(Printer p0, String p1){} + public final void removeCallbacks(Runnable p0){} + public final void removeCallbacks(Runnable p0, Object p1){} + public final void removeCallbacksAndMessages(Object p0){} + public final void removeMessages(int p0){} + public final void removeMessages(int p0, Object p1){} + public static Handler createAsync(Looper p0){ return null; } + public static Handler createAsync(Looper p0, Handler.Callback p1){ return null; } + public void dispatchMessage(Message p0){} + public void handleMessage(Message p0){} + static public interface Callback + { + boolean handleMessage(Message p0); + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/IBinder.java b/java/ql/test/stubs/google-android-9.0.0/android/os/IBinder.java new file mode 100644 index 00000000000..c12d5cf179b --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/IBinder.java @@ -0,0 +1,32 @@ +// Generated automatically from android.os.IBinder for testing purposes + +package android.os; + +import android.os.IInterface; +import android.os.Parcel; +import java.io.FileDescriptor; + +public interface IBinder +{ + IInterface queryLocalInterface(String p0); + String getInterfaceDescriptor(); + boolean isBinderAlive(); + boolean pingBinder(); + boolean transact(int p0, Parcel p1, Parcel p2, int p3); + boolean unlinkToDeath(IBinder.DeathRecipient p0, int p1); + static int DUMP_TRANSACTION = 0; + static int FIRST_CALL_TRANSACTION = 0; + static int FLAG_ONEWAY = 0; + static int INTERFACE_TRANSACTION = 0; + static int LAST_CALL_TRANSACTION = 0; + static int LIKE_TRANSACTION = 0; + static int PING_TRANSACTION = 0; + static int TWEET_TRANSACTION = 0; + static public interface DeathRecipient + { + void binderDied(); + } + void dump(FileDescriptor p0, String[] p1); + void dumpAsync(FileDescriptor p0, String[] p1); + void linkToDeath(IBinder.DeathRecipient p0, int p1); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/IInterface.java b/java/ql/test/stubs/google-android-9.0.0/android/os/IInterface.java new file mode 100644 index 00000000000..ccc3ae0a62d --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/IInterface.java @@ -0,0 +1,10 @@ +// Generated automatically from android.os.IInterface for testing purposes + +package android.os; + +import android.os.IBinder; + +public interface IInterface +{ + IBinder asBinder(); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/LocaleList.java b/java/ql/test/stubs/google-android-9.0.0/android/os/LocaleList.java new file mode 100644 index 00000000000..113f5910a49 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/LocaleList.java @@ -0,0 +1,32 @@ +// Generated automatically from android.os.LocaleList for testing purposes + +package android.os; + +import android.icu.util.ULocale; +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Locale; + +public class LocaleList implements Parcelable +{ + protected LocaleList() {} + public Locale get(int p0){ return null; } + public Locale getFirstMatch(String[] p0){ return null; } + public LocaleList(Locale... p0){} + public String toLanguageTags(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int indexOf(Locale p0){ return 0; } + public int size(){ return 0; } + public static LocaleList forLanguageTags(String p0){ return null; } + public static LocaleList getAdjustedDefault(){ return null; } + public static LocaleList getDefault(){ return null; } + public static LocaleList getEmptyLocaleList(){ return null; } + public static Parcelable.Creator<LocaleList> CREATOR = null; + public static boolean isPseudoLocale(ULocale p0){ return false; } + public static void setDefault(LocaleList p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Looper.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Looper.java new file mode 100644 index 00000000000..bc7076c2125 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Looper.java @@ -0,0 +1,25 @@ +// Generated automatically from android.os.Looper for testing purposes + +package android.os; + +import android.os.MessageQueue; +import android.util.Printer; + +public class Looper +{ + protected Looper() {} + public MessageQueue getQueue(){ return null; } + public String toString(){ return null; } + public Thread getThread(){ return null; } + public boolean isCurrentThread(){ return false; } + public static Looper getMainLooper(){ return null; } + public static Looper myLooper(){ return null; } + public static MessageQueue myQueue(){ return null; } + public static void loop(){} + public static void prepare(){} + public static void prepareMainLooper(){} + public void dump(Printer p0, String p1){} + public void quit(){} + public void quitSafely(){} + public void setMessageLogging(Printer p0){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Message.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Message.java new file mode 100644 index 00000000000..b6f98d43430 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Message.java @@ -0,0 +1,44 @@ +// Generated automatically from android.os.Message for testing purposes + +package android.os; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Messenger; +import android.os.Parcel; +import android.os.Parcelable; + +public class Message implements Parcelable +{ + public Bundle getData(){ return null; } + public Bundle peekData(){ return null; } + public Handler getTarget(){ return null; } + public Message(){} + public Messenger replyTo = null; + public Object obj = null; + public Runnable getCallback(){ return null; } + public String toString(){ return null; } + public boolean isAsynchronous(){ return false; } + public int arg1 = 0; + public int arg2 = 0; + public int describeContents(){ return 0; } + public int sendingUid = 0; + public int what = 0; + public long getWhen(){ return 0; } + public static Message obtain(){ return null; } + public static Message obtain(Handler p0){ return null; } + public static Message obtain(Handler p0, Runnable p1){ return null; } + public static Message obtain(Handler p0, int p1){ return null; } + public static Message obtain(Handler p0, int p1, Object p2){ return null; } + public static Message obtain(Handler p0, int p1, int p2, int p3){ return null; } + public static Message obtain(Handler p0, int p1, int p2, int p3, Object p4){ return null; } + public static Message obtain(Message p0){ return null; } + public static Parcelable.Creator<Message> CREATOR = null; + public void copyFrom(Message p0){} + public void recycle(){} + public void sendToTarget(){} + public void setAsynchronous(boolean p0){} + public void setData(Bundle p0){} + public void setTarget(Handler p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/MessageQueue.java b/java/ql/test/stubs/google-android-9.0.0/android/os/MessageQueue.java new file mode 100644 index 00000000000..d49871ccdf9 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/MessageQueue.java @@ -0,0 +1,27 @@ +// Generated automatically from android.os.MessageQueue for testing purposes + +package android.os; + +import java.io.FileDescriptor; + +public class MessageQueue +{ + protected MessageQueue() {} + protected void finalize(){} + public boolean isIdle(){ return false; } + public void addIdleHandler(MessageQueue.IdleHandler p0){} + public void addOnFileDescriptorEventListener(FileDescriptor p0, int p1, MessageQueue.OnFileDescriptorEventListener p2){} + public void removeIdleHandler(MessageQueue.IdleHandler p0){} + public void removeOnFileDescriptorEventListener(FileDescriptor p0){} + static public interface IdleHandler + { + boolean queueIdle(); + } + static public interface OnFileDescriptorEventListener + { + int onFileDescriptorEvents(FileDescriptor p0, int p1); + static int EVENT_ERROR = 0; + static int EVENT_INPUT = 0; + static int EVENT_OUTPUT = 0; + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Messenger.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Messenger.java new file mode 100644 index 00000000000..08d2a975153 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Messenger.java @@ -0,0 +1,25 @@ +// Generated automatically from android.os.Messenger for testing purposes + +package android.os; + +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; + +public class Messenger implements Parcelable +{ + protected Messenger() {} + public IBinder getBinder(){ return null; } + public Messenger(Handler p0){} + public Messenger(IBinder p0){} + public boolean equals(Object p0){ return false; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Messenger readMessengerOrNullFromParcel(Parcel p0){ return null; } + public static Parcelable.Creator<Messenger> CREATOR = null; + public static void writeMessengerOrNullToParcel(Messenger p0, Parcel p1){} + public void send(Message p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Parcel.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Parcel.java index 077da662edb..7e8608e24c6 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/os/Parcel.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Parcel.java @@ -1,670 +1,144 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.os.Parcel for testing purposes + package android.os; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; +import android.os.Bundle; +import android.os.IBinder; +import android.os.IInterface; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; +import android.os.PersistableBundle; +import android.util.ArrayMap; +import android.util.Size; +import android.util.SizeF; +import android.util.SparseArray; +import android.util.SparseBooleanArray; import java.io.FileDescriptor; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamClass; import java.io.Serializable; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; -public final class Parcel { - - /** - * Retrieve a new Parcel object from the pool. - */ - public static Parcel obtain() { - return null; - } - - /** - * Write a byte array into the parcel at the current {@link #dataPosition}, - * growing {@link #dataCapacity} if needed. - * - * @param b Bytes to place into the parcel. - */ - public final void writeByteArray(byte[] b) { - } - - /** - * Write a byte array into the parcel at the current {@link #dataPosition}, - * growing {@link #dataCapacity} if needed. - * - * @param b Bytes to place into the parcel. - * @param offset Index of first byte to be written. - * @param len Number of bytes to write. - */ - public final void writeByteArray(byte[] b, int offset, int len) { - } - - /** - * Write a blob of data into the parcel at the current {@link #dataPosition}, - * growing {@link #dataCapacity} if needed. - * - * @param b Bytes to place into the parcel. {@hide} {@SystemApi} - */ - public final void writeBlob(byte[] b) { - } - - /** - * Write a blob of data into the parcel at the current {@link #dataPosition}, - * growing {@link #dataCapacity} if needed. - * - * @param b Bytes to place into the parcel. - * @param offset Index of first byte to be written. - * @param len Number of bytes to write. {@hide} {@SystemApi} - */ - public final void writeBlob(byte[] b, int offset, int len) { - } - - /** - * Write an integer value into the parcel at the current dataPosition(), growing - * dataCapacity() if needed. - */ - public final void writeInt(int val) { - } - - /** - * Write a long integer value into the parcel at the current dataPosition(), - * growing dataCapacity() if needed. - */ - public final void writeLong(long val) { - } - - /** - * Write a floating point value into the parcel at the current dataPosition(), - * growing dataCapacity() if needed. - */ - public final void writeFloat(float val) { - } - - /** - * Write a double precision floating point value into the parcel at the current - * dataPosition(), growing dataCapacity() if needed. - */ - public final void writeDouble(double val) { - } - - /** - * Write a string value into the parcel at the current dataPosition(), growing - * dataCapacity() if needed. - */ - public final void writeString(String val) { - } - - /** - * Write a string without going though a {@link ReadWriteHelper}. Subclasses of - * {@link ReadWriteHelper} must use this method instead of {@link #writeString} - * to avoid infinity recursive calls. - * - * @hide - */ - public void writeStringNoHelper(String val) { - } - - /** @hide */ - public final void writeBoolean(boolean val) { - } - - /** - * Write a CharSequence value into the parcel at the current dataPosition(), - * growing dataCapacity() if needed. - * - * @hide - */ - public final void writeCharSequence(CharSequence val) { - } - - /** - * Write a byte value into the parcel at the current dataPosition(), growing - * dataCapacity() if needed. - */ - public final void writeByte(byte val) { - } - - /** - * Please use {@link #writeBundle} instead. Flattens a Map into the parcel at - * the current dataPosition(), growing dataCapacity() if needed. The Map keys - * must be String objects. The Map values are written using {@link #writeValue} - * and must follow the specification there. - * - * <p> - * It is strongly recommended to use {@link #writeBundle} instead of this - * method, since the Bundle class provides a type-safe API that allows you to - * avoid mysterious type errors at the point of marshalling. - */ - public final void writeMap(Map val) { - } - - /** - * Flatten a Bundle into the parcel at the current dataPosition(), growing - * dataCapacity() if needed. - */ - public final void writeBundle(Bundle val) { - } - - /** - * Flatten a List into the parcel at the current dataPosition(), growing - * dataCapacity() if needed. The List values are written using - * {@link #writeValue} and must follow the specification there. - */ - public final void writeList(List val) { - } - - /** - * Flatten an Object array into the parcel at the current dataPosition(), - * growing dataCapacity() if needed. The array values are written using - * {@link #writeValue} and must follow the specification there. - */ - public final void writeArray(Object[] val) { - } - - public final void writeBooleanArray(boolean[] val) { - } - - public final boolean[] createBooleanArray() { - return null; - } - - public final void readBooleanArray(boolean[] val) { - } - - public final void writeCharArray(char[] val) { - } - - public final char[] createCharArray() { - return null; - } - - public final void readCharArray(char[] val) { - } - - public final void writeIntArray(int[] val) { - } - - public final int[] createIntArray() { - return null; - } - - public final void readIntArray(int[] val) { - } - - public final void writeLongArray(long[] val) { - } - - public final long[] createLongArray() { - return null; - } - - public final void readLongArray(long[] val) { - } - - public final void writeFloatArray(float[] val) { - } - - public final float[] createFloatArray() { - return null; - } - - public final void readFloatArray(float[] val) { - } - - public final void writeDoubleArray(double[] val) { - } - - public final double[] createDoubleArray() { - return null; - } - - public final void readDoubleArray(double[] val) { - } - - public final void writeStringArray(String[] val) { - } - - public final String[] createStringArray() { - return null; - } - - public final void readStringArray(String[] val) { - } - - /** - * @hide - */ - public final void writeCharSequenceArray(CharSequence[] val) { - } - - /** - * @hide - */ - public final void writeCharSequenceList(ArrayList<CharSequence> val) { - } - - /** - * Flatten a List containing String objects into the parcel, at the current - * dataPosition() and growing dataCapacity() if needed. They can later be - * retrieved with {@link #createStringArrayList} or {@link #readStringList}. - * - * @param val The list of strings to be written. - * - * @see #createStringArrayList - * @see #readStringList - */ - public final void writeStringList(List<String> val) { - } - - /** - * Flatten a generic object in to a parcel. The given Object value may currently - * be one of the following types: - * - * <ul> - * <li>null - * <li>String - * <li>Byte - * <li>Short - * <li>Integer - * <li>Long - * <li>Float - * <li>Double - * <li>Boolean - * <li>String[] - * <li>boolean[] - * <li>byte[] - * <li>int[] - * <li>long[] - * <li>Object[] (supporting objects of the same type defined here). - * <li>{@link Bundle} - * <li>Map (as supported by {@link #writeMap}). - * <li>Any object that implements the {@link Parcelable} protocol. - * <li>Parcelable[] - * <li>CharSequence (as supported by {@link TextUtils#writeToParcel}). - * <li>List (as supported by {@link #writeList}). - * <li>{@link SparseArray} (as supported by - * {@link #writeSparseArray(SparseArray)}). - * <li>{@link IBinder} - * <li>Any object that implements Serializable (but see - * {@link #writeSerializable} for caveats). Note that all of the previous types - * have relatively efficient implementations for writing to a Parcel; having to - * rely on the generic serialization approach is much less efficient and should - * be avoided whenever possible. - * </ul> - * - * <p class="caution"> - * {@link Parcelable} objects are written with {@link Parcelable#writeToParcel} - * using contextual flags of 0. When serializing objects containing - * {@link ParcelFileDescriptor}s, this may result in file descriptor leaks when - * they are returned from Binder calls (where - * {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} should be used). - * </p> - */ - public final void writeValue(Object v) { - } - - /** - * Flatten the name of the class of the Parcelable and its contents into the - * parcel. - * - * @param p The Parcelable object to be written. - * @param parcelableFlags Contextual flags as per - * {@link Parcelable#writeToParcel(Parcel, int) - * Parcelable.writeToParcel()}. - */ - public final void writeParcelable(Parcelable p, int parcelableFlags) { - } - - /** @hide */ - public final void writeParcelableCreator(Parcelable p) { - } - - /** - * Write a generic serializable object in to a Parcel. It is strongly - * recommended that this method be avoided, since the serialization overhead is - * extremely large, and this approach will be much slower than using the other - * approaches to writing data in to a Parcel. - */ - public final void writeSerializable(Serializable s) { - } - - /** - * Special function for writing an exception result at the header of a parcel, - * to be used when returning an exception from a transaction. Note that this - * currently only supports a few exception types; any other exception will be - * re-thrown by this function as a RuntimeException (to be caught by the - * system's last-resort exception handling when dispatching a transaction). - * - * <p> - * The supported exception types are: - * <ul> - * <li>{@link BadParcelableException} - * <li>{@link IllegalArgumentException} - * <li>{@link IllegalStateException} - * <li>{@link NullPointerException} - * <li>{@link SecurityException} - * <li>{@link UnsupportedOperationException} - * <li>{@link NetworkOnMainThreadException} - * </ul> - * - * @param e The Exception to be written. - * - * @see #writeNoException - * @see #readException - */ - public final void writeException(Exception e) { - } - - /** - * Special function for writing information at the front of the Parcel - * indicating that no exception occurred. - * - * @see #writeException - * @see #readException - */ - public final void writeNoException() { - } - - /** - * Special function for reading an exception result from the header of a parcel, - * to be used after receiving the result of a transaction. This will throw the - * exception for you if it had been written to the Parcel, otherwise return and - * let you read the normal result data from the Parcel. - * - * @see #writeException - * @see #writeNoException - */ - public final void readException() { - } - - /** - * Parses the header of a Binder call's response Parcel and returns the - * exception code. Deals with lite or fat headers. In the common successful - * case, this header is generally zero. In less common cases, it's a small - * negative number and will be followed by an error string. - * - * This exists purely for android.database.DatabaseUtils and insulating it from - * having to handle fat headers as returned by e.g. StrictMode-induced RPC - * responses. - * - * @hide - */ - public final int readExceptionCode() { - return -1; - } - - /** - * Throw an exception with the given message. Not intended for use outside the - * Parcel class. - * - * @param code Used to determine which exception class to throw. - * @param msg The exception message. - */ - public final void readException(int code, String msg) { - } - - /** - * Read an integer value from the parcel at the current dataPosition(). - */ - public final int readInt() { - return -1; - } - - /** - * Read a long integer value from the parcel at the current dataPosition(). - */ - public final long readLong() { - return -1; - } - - /** - * Read a floating point value from the parcel at the current dataPosition(). - */ - public final float readFloat() { - return -1; - } - - /** - * Read a double precision floating point value from the parcel at the current - * dataPosition(). - */ - public final double readDouble() { - return -1; - } - - /** - * Read a string value from the parcel at the current dataPosition(). - */ - public final String readString() { - return null; - } - - /** @hide */ - public final boolean readBoolean() { - return false; - } - - /** - * Read a CharSequence value from the parcel at the current dataPosition(). - * - * @hide - */ - public final CharSequence readCharSequence() { - return null; - } - - /** - * Read a byte value from the parcel at the current dataPosition(). - */ - public final byte readByte() { - return -1; - } - - /** - * Please use {@link #readBundle(ClassLoader)} instead (whose data must have - * been written with {@link #writeBundle}. Read into an existing Map object from - * the parcel at the current dataPosition(). - */ - public final void readMap(Map outVal, ClassLoader loader) { - } - - /** - * Read into an existing List object from the parcel at the current - * dataPosition(), using the given class loader to load any enclosed - * Parcelables. If it is null, the default class loader is used. - */ - public final void readList(List outVal, ClassLoader loader) { - } - - /** - * Please use {@link #readBundle(ClassLoader)} instead (whose data must have - * been written with {@link #writeBundle}. Read and return a new HashMap object - * from the parcel at the current dataPosition(), using the given class loader - * to load any enclosed Parcelables. Returns null if the previously written map - * object was null. - */ - public final HashMap readHashMap(ClassLoader loader) { - return null; - } - - /** - * Read and return a new Bundle object from the parcel at the current - * dataPosition(). Returns null if the previously written Bundle object was - * null. - */ - public final Bundle readBundle() { - return null; - } - - /** - * Read and return a new Bundle object from the parcel at the current - * dataPosition(), using the given class loader to initialize the class loader - * of the Bundle for later retrieval of Parcelable objects. Returns null if the - * previously written Bundle object was null. - */ - public final Bundle readBundle(ClassLoader loader) { - return null; - } - - /** - * Read and return a byte[] object from the parcel. - */ - public final byte[] createByteArray() { - return null; - } - - /** - * Read a byte[] object from the parcel and copy it into the given byte array. - */ - public final void readByteArray(byte[] val) { - } - - /** - * Read a blob of data from the parcel and return it as a byte array. - * {@hide} {@SystemApi} - */ - public final byte[] readBlob() { - return null; - } - - /** - * Read and return a String[] object from the parcel. {@hide} - */ - public final String[] readStringArray() { - return null; - } - - /** - * Read and return a CharSequence[] object from the parcel. {@hide} - */ - public final CharSequence[] readCharSequenceArray() { - return null; - } - - /** - * Read and return an ArrayList<CharSequence> object from the parcel. - * {@hide} - */ - public final ArrayList<CharSequence> readCharSequenceList() { - return null; - } - - /** - * Read and return a new ArrayList object from the parcel at the current - * dataPosition(). Returns null if the previously written list object was null. - * The given class loader will be used to load any enclosed Parcelables. - */ - public final ArrayList readArrayList(ClassLoader loader) { - return null; - } - - /** - * Read and return a new Object array from the parcel at the current - * dataPosition(). Returns null if the previously written array was null. The - * given class loader will be used to load any enclosed Parcelables. - */ - public final Object[] readArray(ClassLoader loader) { - return null; - } - - /** - * Read and return a new ArrayList containing String objects from the parcel - * that was written with {@link #writeStringList} at the current dataPosition(). - * Returns null if the previously written list object was null. - * - * @return A newly created ArrayList containing strings with the same data as - * those that were previously written. - * - * @see #writeStringList - */ - public final ArrayList<String> createStringArrayList() { - return null; - } - - /** - * Read into the given List items String objects that were written with - * {@link #writeStringList} at the current dataPosition(). - * - * @see #writeStringList - */ - public final void readStringList(List<String> list) { - } - - /** - * Read a typed object from a parcel. The given class loader will be used to - * load any enclosed Parcelables. If it is null, the default class loader will - * be used. - */ - public final Object readValue(ClassLoader loader) { - return null; - } - - /** - * Read and return a new Parcelable from the parcel. The given class loader will - * be used to load any enclosed Parcelables. If it is null, the default class - * loader will be used. - * - * @param loader A ClassLoader from which to instantiate the Parcelable object, - * or null for the default class loader. - * @return Returns the newly created Parcelable, or null if a null object has - * been written. - * @throws BadParcelableException Throws BadParcelableException if there was an - * error trying to instantiate the Parcelable. - */ - public final <T extends Parcelable> T readParcelable(ClassLoader loader) { - return null; - } - - /** - * Read and return a new Parcelable array from the parcel. The given class - * loader will be used to load any enclosed Parcelables. - * - * @return the Parcelable array, or null if the array is null - */ - public final Parcelable[] readParcelableArray(ClassLoader loader) { - return null; - } - - /** @hide */ - public final <T extends Parcelable> T[] readParcelableArray(ClassLoader loader, Class<T> clazz) { - return null; - } - - /** - * Read and return a new Serializable object from the parcel. - * - * @return the Serializable object, or null if the Serializable name wasn't - * found in the parcel. - */ - public final Serializable readSerializable() { - return null; - } - - private final Serializable readSerializable(final ClassLoader loader) { - return null; - } +public class Parcel +{ + protected Parcel() {} + protected void finalize(){} + public <T extends Parcelable> ArrayMap<String, T> createTypedArrayMap(Parcelable.Creator<T> p0){ return null; } + public <T extends Parcelable> List<T> readParcelableList(List<T> p0, ClassLoader p1){ return null; } + public <T extends Parcelable> SparseArray<T> createTypedSparseArray(Parcelable.Creator<T> p0){ return null; } + public <T extends Parcelable> T readParcelable(ClassLoader p0){ return null; } + public <T extends Parcelable> void writeParcelableArray(T[] p0, int p1){} + public <T extends Parcelable> void writeParcelableList(List<T> p0, int p1){} + public <T extends Parcelable> void writeTypedArray(T[] p0, int p1){} + public <T extends Parcelable> void writeTypedArrayMap(ArrayMap<String, T> p0, int p1){} + public <T extends Parcelable> void writeTypedList(List<T> p0){} + public <T extends Parcelable> void writeTypedObject(T p0, int p1){} + public <T extends Parcelable> void writeTypedSparseArray(SparseArray<T> p0, int p1){} + public <T> ArrayList<T> createTypedArrayList(Parcelable.Creator<T> p0){ return null; } + public <T> SparseArray<T> readSparseArray(ClassLoader p0){ return null; } + public <T> T readTypedObject(Parcelable.Creator<T> p0){ return null; } + public <T> T[] createTypedArray(Parcelable.Creator<T> p0){ return null; } + public <T> void readTypedArray(T[] p0, Parcelable.Creator<T> p1){} + public <T> void readTypedList(List<T> p0, Parcelable.Creator<T> p1){} + public <T> void writeSparseArray(SparseArray<T> p0){} + public ArrayList readArrayList(ClassLoader p0){ return null; } + public ArrayList<IBinder> createBinderArrayList(){ return null; } + public ArrayList<String> createStringArrayList(){ return null; } + public Bundle readBundle(){ return null; } + public Bundle readBundle(ClassLoader p0){ return null; } + public HashMap readHashMap(ClassLoader p0){ return null; } + public IBinder readStrongBinder(){ return null; } + public IBinder[] createBinderArray(){ return null; } + public Object readValue(ClassLoader p0){ return null; } + public Object[] readArray(ClassLoader p0){ return null; } + public ParcelFileDescriptor readFileDescriptor(){ return null; } + public Parcelable[] readParcelableArray(ClassLoader p0){ return null; } + public PersistableBundle readPersistableBundle(){ return null; } + public PersistableBundle readPersistableBundle(ClassLoader p0){ return null; } + public Serializable readSerializable(){ return null; } + public Size readSize(){ return null; } + public SizeF readSizeF(){ return null; } + public SparseBooleanArray readSparseBooleanArray(){ return null; } + public String readString(){ return null; } + public String[] createStringArray(){ return null; } + public boolean hasFileDescriptors(){ return false; } + public boolean readBoolean(){ return false; } + public boolean[] createBooleanArray(){ return null; } + public byte readByte(){ return 0; } + public byte[] createByteArray(){ return null; } + public byte[] marshall(){ return null; } + public char[] createCharArray(){ return null; } + public double readDouble(){ return 0; } + public double[] createDoubleArray(){ return null; } + public float readFloat(){ return 0; } + public float[] createFloatArray(){ return null; } + public int dataAvail(){ return 0; } + public int dataCapacity(){ return 0; } + public int dataPosition(){ return 0; } + public int dataSize(){ return 0; } + public int readInt(){ return 0; } + public int[] createIntArray(){ return null; } + public long readLong(){ return 0; } + public long[] createLongArray(){ return null; } + public static Parcel obtain(){ return null; } + public static Parcelable.Creator<String> STRING_CREATOR = null; + public void appendFrom(Parcel p0, int p1, int p2){} + public void enforceInterface(String p0){} + public void readBinderArray(IBinder[] p0){} + public void readBinderList(List<IBinder> p0){} + public void readBooleanArray(boolean[] p0){} + public void readByteArray(byte[] p0){} + public void readCharArray(char[] p0){} + public void readDoubleArray(double[] p0){} + public void readException(){} + public void readException(int p0, String p1){} + public void readFloatArray(float[] p0){} + public void readIntArray(int[] p0){} + public void readList(List p0, ClassLoader p1){} + public void readLongArray(long[] p0){} + public void readMap(Map p0, ClassLoader p1){} + public void readStringArray(String[] p0){} + public void readStringList(List<String> p0){} + public void recycle(){} + public void setDataCapacity(int p0){} + public void setDataPosition(int p0){} + public void setDataSize(int p0){} + public void unmarshall(byte[] p0, int p1, int p2){} + public void writeArray(Object[] p0){} + public void writeBinderArray(IBinder[] p0){} + public void writeBinderList(List<IBinder> p0){} + public void writeBoolean(boolean p0){} + public void writeBooleanArray(boolean[] p0){} + public void writeBundle(Bundle p0){} + public void writeByte(byte p0){} + public void writeByteArray(byte[] p0){} + public void writeByteArray(byte[] p0, int p1, int p2){} + public void writeCharArray(char[] p0){} + public void writeDouble(double p0){} + public void writeDoubleArray(double[] p0){} + public void writeException(Exception p0){} + public void writeFileDescriptor(FileDescriptor p0){} + public void writeFloat(float p0){} + public void writeFloatArray(float[] p0){} + public void writeInt(int p0){} + public void writeIntArray(int[] p0){} + public void writeInterfaceToken(String p0){} + public void writeList(List p0){} + public void writeLong(long p0){} + public void writeLongArray(long[] p0){} + public void writeMap(Map p0){} + public void writeNoException(){} + public void writeParcelable(Parcelable p0, int p1){} + public void writePersistableBundle(PersistableBundle p0){} + public void writeSerializable(Serializable p0){} + public void writeSize(Size p0){} + public void writeSizeF(SizeF p0){} + public void writeSparseBooleanArray(SparseBooleanArray p0){} + public void writeString(String p0){} + public void writeStringArray(String[] p0){} + public void writeStringList(List<String> p0){} + public void writeStrongBinder(IBinder p0){} + public void writeStrongInterface(IInterface p0){} + public void writeValue(Object p0){} } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Parcelable.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Parcelable.java index e3c46053a7e..626061a6799 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/os/Parcelable.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Parcelable.java @@ -1,111 +1,18 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.os.Parcelable for testing purposes + package android.os; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; +import android.os.Parcel; -/** - * Interface for classes whose instances can be written to and restored from a - * {@link Parcel}. Classes implementing the Parcelable interface must also have - * a non-null static field called <code>CREATOR</code> of a type that implements - * the {@link Parcelable.Creator} interface. - * - * <p> - * A typical implementation of Parcelable is: - * </p> - * - * <pre> - * public class MyParcelable implements Parcelable { - * private int mData; - * - * public int describeContents() { - * return 0; - * } - * - * public void writeToParcel(Parcel out, int flags) { - * out.writeInt(mData); - * } - * - * public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() { - * public MyParcelable createFromParcel(Parcel in) { - * return new MyParcelable(in); - * } - * - * public MyParcelable[] newArray(int size) { - * return new MyParcelable[size]; - * } - * }; - * - * private MyParcelable(Parcel in) { - * mData = in.readInt(); - * } - * } - * </pre> - */ -public interface Parcelable { - /** - * Flatten this object in to a Parcel. - * - * @param dest The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written. May be - * 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. - */ - public void writeToParcel(Parcel dest, int flags); - - /** - * Interface that must be implemented and provided as a public CREATOR - * field that generates instances of your Parcelable class from a Parcel. - */ - public interface Creator<T> { - /** - * Create a new instance of the Parcelable class, instantiating it - * from the given Parcel whose data had previously been written by - * {@link Parcelable#writeToParcel Parcelable.writeToParcel()}. - * - * @param source The Parcel to read the object's data from. - * @return Returns a new instance of the Parcelable class. - */ - public T createFromParcel(Parcel source); - - /** - * Create a new array of the Parcelable class. - * - * @param size Size of the array. - * @return Returns an array of the Parcelable class, with every entry - * initialized to null. - */ - public T[] newArray(int size); +public interface Parcelable +{ + int describeContents(); + static int CONTENTS_FILE_DESCRIPTOR = 0; + static int PARCELABLE_WRITE_RETURN_VALUE = 0; + static public interface Creator<T> + { + T createFromParcel(Parcel p0); + T[] newArray(int p0); } - - /** - * Specialization of {@link Creator} that allows you to receive the ClassLoader - * the object is being created in. - */ - public interface ClassLoaderCreator<T> { - /** - * Create a new instance of the Parcelable class, instantiating it from the - * given Parcel whose data had previously been written by - * {@link Parcelable#writeToParcel Parcelable.writeToParcel()} and using the - * given ClassLoader. - * - * @param source The Parcel to read the object's data from. - * @param loader The ClassLoader that this object is being created in. - * @return Returns a new instance of the Parcelable class. - */ - public T createFromParcel(Parcel source, ClassLoader loader); - } -} \ No newline at end of file + void writeToParcel(Parcel p0, int p1); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/PersistableBundle.java b/java/ql/test/stubs/google-android-9.0.0/android/os/PersistableBundle.java new file mode 100644 index 00000000000..1aa4768bc89 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/PersistableBundle.java @@ -0,0 +1,23 @@ +// Generated automatically from android.os.PersistableBundle for testing purposes + +package android.os; + +import android.os.BaseBundle; +import android.os.Parcel; +import android.os.Parcelable; + +public class PersistableBundle extends BaseBundle implements Cloneable, Parcelable +{ + public Object clone(){ return null; } + public PersistableBundle deepCopy(){ return null; } + public PersistableBundle getPersistableBundle(String p0){ return null; } + public PersistableBundle(){} + public PersistableBundle(PersistableBundle p0){} + public PersistableBundle(int p0){} + public String toString(){ return null; } + public int describeContents(){ return 0; } + public static Parcelable.Creator<PersistableBundle> CREATOR = null; + public static PersistableBundle EMPTY = null; + public void putPersistableBundle(String p0, PersistableBundle p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/UserHandle.java b/java/ql/test/stubs/google-android-9.0.0/android/os/UserHandle.java new file mode 100644 index 00000000000..a2e4d596054 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/UserHandle.java @@ -0,0 +1,21 @@ +// Generated automatically from android.os.UserHandle for testing purposes + +package android.os; + +import android.os.Parcel; +import android.os.Parcelable; + +public class UserHandle implements Parcelable +{ + protected UserHandle() {} + public String toString(){ return null; } + public UserHandle(Parcel p0){} + public boolean equals(Object p0){ return false; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<UserHandle> CREATOR = null; + public static UserHandle getUserHandleForUid(int p0){ return null; } + public static UserHandle readFromParcel(Parcel p0){ return null; } + public static void writeToParcel(UserHandle p0, Parcel p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/util/AttributeSet.java b/java/ql/test/stubs/google-android-9.0.0/android/util/AttributeSet.java new file mode 100644 index 00000000000..04bdbe6b8d2 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/util/AttributeSet.java @@ -0,0 +1,31 @@ +// Generated automatically from android.util.AttributeSet for testing purposes + +package android.util; + + +public interface AttributeSet +{ + String getAttributeName(int p0); + String getAttributeValue(String p0, String p1); + String getAttributeValue(int p0); + String getClassAttribute(); + String getIdAttribute(); + String getPositionDescription(); + boolean getAttributeBooleanValue(String p0, String p1, boolean p2); + boolean getAttributeBooleanValue(int p0, boolean p1); + default String getAttributeNamespace(int p0){ return null; } + float getAttributeFloatValue(String p0, String p1, float p2); + float getAttributeFloatValue(int p0, float p1); + int getAttributeCount(); + int getAttributeIntValue(String p0, String p1, int p2); + int getAttributeIntValue(int p0, int p1); + int getAttributeListValue(String p0, String p1, String[] p2, int p3); + int getAttributeListValue(int p0, String[] p1, int p2); + int getAttributeNameResource(int p0); + int getAttributeResourceValue(String p0, String p1, int p2); + int getAttributeResourceValue(int p0, int p1); + int getAttributeUnsignedIntValue(String p0, String p1, int p2); + int getAttributeUnsignedIntValue(int p0, int p1); + int getIdAttributeResourceValue(int p0); + int getStyleAttribute(); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/util/DisplayMetrics.java b/java/ql/test/stubs/google-android-9.0.0/android/util/DisplayMetrics.java new file mode 100644 index 00000000000..fe64b670921 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/util/DisplayMetrics.java @@ -0,0 +1,46 @@ +// Generated automatically from android.util.DisplayMetrics for testing purposes + +package android.util; + + +public class DisplayMetrics +{ + public DisplayMetrics(){} + public String toString(){ return null; } + public boolean equals(DisplayMetrics p0){ return false; } + public boolean equals(Object p0){ return false; } + public float density = 0; + public float scaledDensity = 0; + public float xdpi = 0; + public float ydpi = 0; + public int densityDpi = 0; + public int hashCode(){ return 0; } + public int heightPixels = 0; + public int widthPixels = 0; + public static int DENSITY_140 = 0; + public static int DENSITY_180 = 0; + public static int DENSITY_200 = 0; + public static int DENSITY_220 = 0; + public static int DENSITY_260 = 0; + public static int DENSITY_280 = 0; + public static int DENSITY_300 = 0; + public static int DENSITY_340 = 0; + public static int DENSITY_360 = 0; + public static int DENSITY_400 = 0; + public static int DENSITY_420 = 0; + public static int DENSITY_440 = 0; + public static int DENSITY_450 = 0; + public static int DENSITY_560 = 0; + public static int DENSITY_600 = 0; + public static int DENSITY_DEFAULT = 0; + public static int DENSITY_DEVICE_STABLE = 0; + public static int DENSITY_HIGH = 0; + public static int DENSITY_LOW = 0; + public static int DENSITY_MEDIUM = 0; + public static int DENSITY_TV = 0; + public static int DENSITY_XHIGH = 0; + public static int DENSITY_XXHIGH = 0; + public static int DENSITY_XXXHIGH = 0; + public void setTo(DisplayMetrics p0){} + public void setToDefaults(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/util/Printer.java b/java/ql/test/stubs/google-android-9.0.0/android/util/Printer.java new file mode 100644 index 00000000000..e6b67a13572 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/util/Printer.java @@ -0,0 +1,9 @@ +// Generated automatically from android.util.Printer for testing purposes + +package android.util; + + +public interface Printer +{ + void println(String p0); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/util/Size.java b/java/ql/test/stubs/google-android-9.0.0/android/util/Size.java new file mode 100644 index 00000000000..9cd6edc8555 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/util/Size.java @@ -0,0 +1,16 @@ +// Generated automatically from android.util.Size for testing purposes + +package android.util; + + +public class Size +{ + protected Size() {} + public Size(int p0, int p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int getHeight(){ return 0; } + public int getWidth(){ return 0; } + public int hashCode(){ return 0; } + public static Size parseSize(String p0){ return null; } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/util/SizeF.java b/java/ql/test/stubs/google-android-9.0.0/android/util/SizeF.java new file mode 100644 index 00000000000..16558fd17e6 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/util/SizeF.java @@ -0,0 +1,16 @@ +// Generated automatically from android.util.SizeF for testing purposes + +package android.util; + + +public class SizeF +{ + protected SizeF() {} + public SizeF(float p0, float p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public float getHeight(){ return 0; } + public float getWidth(){ return 0; } + public int hashCode(){ return 0; } + public static SizeF parseSizeF(String p0){ return null; } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/util/SparseArray.java b/java/ql/test/stubs/google-android-9.0.0/android/util/SparseArray.java new file mode 100644 index 00000000000..13c447c9741 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/util/SparseArray.java @@ -0,0 +1,27 @@ +// Generated automatically from android.util.SparseArray for testing purposes + +package android.util; + + +public class SparseArray<E> implements Cloneable +{ + public E get(int p0){ return null; } + public E get(int p0, E p1){ return null; } + public E valueAt(int p0){ return null; } + public SparseArray(){} + public SparseArray(int p0){} + public SparseArray<E> clone(){ return null; } + public String toString(){ return null; } + public int indexOfKey(int p0){ return 0; } + public int indexOfValue(E p0){ return 0; } + public int keyAt(int p0){ return 0; } + public int size(){ return 0; } + public void append(int p0, E p1){} + public void clear(){} + public void delete(int p0){} + public void put(int p0, E p1){} + public void remove(int p0){} + public void removeAt(int p0){} + public void removeAtRange(int p0, int p1){} + public void setValueAt(int p0, E p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/util/SparseBooleanArray.java b/java/ql/test/stubs/google-android-9.0.0/android/util/SparseBooleanArray.java new file mode 100644 index 00000000000..3c84c18e71b --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/util/SparseBooleanArray.java @@ -0,0 +1,27 @@ +// Generated automatically from android.util.SparseBooleanArray for testing purposes + +package android.util; + + +public class SparseBooleanArray implements Cloneable +{ + public SparseBooleanArray clone(){ return null; } + public SparseBooleanArray(){} + public SparseBooleanArray(int p0){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean get(int p0){ return false; } + public boolean get(int p0, boolean p1){ return false; } + public boolean valueAt(int p0){ return false; } + public int hashCode(){ return 0; } + public int indexOfKey(int p0){ return 0; } + public int indexOfValue(boolean p0){ return 0; } + public int keyAt(int p0){ return 0; } + public int size(){ return 0; } + public void append(int p0, boolean p1){} + public void clear(){} + public void delete(int p0){} + public void put(int p0, boolean p1){} + public void removeAt(int p0){} + public void setValueAt(int p0, boolean p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/util/TypedValue.java b/java/ql/test/stubs/google-android-9.0.0/android/util/TypedValue.java new file mode 100644 index 00000000000..269ab8bcf67 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/util/TypedValue.java @@ -0,0 +1,73 @@ +// Generated automatically from android.util.TypedValue for testing purposes + +package android.util; + +import android.util.DisplayMetrics; + +public class TypedValue +{ + public CharSequence string = null; + public String toString(){ return null; } + public TypedValue(){} + public boolean isColorType(){ return false; } + public final CharSequence coerceToString(){ return null; } + public final float getFloat(){ return 0; } + public float getDimension(DisplayMetrics p0){ return 0; } + public float getFraction(float p0, float p1){ return 0; } + public int assetCookie = 0; + public int changingConfigurations = 0; + public int data = 0; + public int density = 0; + public int getComplexUnit(){ return 0; } + public int resourceId = 0; + public int sourceResourceId = 0; + public int type = 0; + public static String coerceToString(int p0, int p1){ return null; } + public static float applyDimension(int p0, float p1, DisplayMetrics p2){ return 0; } + public static float complexToDimension(int p0, DisplayMetrics p1){ return 0; } + public static float complexToFloat(int p0){ return 0; } + public static float complexToFraction(int p0, float p1, float p2){ return 0; } + public static int COMPLEX_MANTISSA_MASK = 0; + public static int COMPLEX_MANTISSA_SHIFT = 0; + public static int COMPLEX_RADIX_0p23 = 0; + public static int COMPLEX_RADIX_16p7 = 0; + public static int COMPLEX_RADIX_23p0 = 0; + public static int COMPLEX_RADIX_8p15 = 0; + public static int COMPLEX_RADIX_MASK = 0; + public static int COMPLEX_RADIX_SHIFT = 0; + public static int COMPLEX_UNIT_DIP = 0; + public static int COMPLEX_UNIT_FRACTION = 0; + public static int COMPLEX_UNIT_FRACTION_PARENT = 0; + public static int COMPLEX_UNIT_IN = 0; + public static int COMPLEX_UNIT_MASK = 0; + public static int COMPLEX_UNIT_MM = 0; + public static int COMPLEX_UNIT_PT = 0; + public static int COMPLEX_UNIT_PX = 0; + public static int COMPLEX_UNIT_SHIFT = 0; + public static int COMPLEX_UNIT_SP = 0; + public static int DATA_NULL_EMPTY = 0; + public static int DATA_NULL_UNDEFINED = 0; + public static int DENSITY_DEFAULT = 0; + public static int DENSITY_NONE = 0; + public static int TYPE_ATTRIBUTE = 0; + public static int TYPE_DIMENSION = 0; + public static int TYPE_FIRST_COLOR_INT = 0; + public static int TYPE_FIRST_INT = 0; + public static int TYPE_FLOAT = 0; + public static int TYPE_FRACTION = 0; + public static int TYPE_INT_BOOLEAN = 0; + public static int TYPE_INT_COLOR_ARGB4 = 0; + public static int TYPE_INT_COLOR_ARGB8 = 0; + public static int TYPE_INT_COLOR_RGB4 = 0; + public static int TYPE_INT_COLOR_RGB8 = 0; + public static int TYPE_INT_DEC = 0; + public static int TYPE_INT_HEX = 0; + public static int TYPE_LAST_COLOR_INT = 0; + public static int TYPE_LAST_INT = 0; + public static int TYPE_NULL = 0; + public static int TYPE_REFERENCE = 0; + public static int TYPE_STRING = 0; + public static int complexToDimensionPixelOffset(int p0, DisplayMetrics p1){ return 0; } + public static int complexToDimensionPixelSize(int p0, DisplayMetrics p1){ return 0; } + public void setTo(TypedValue p0){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/view/Display.java b/java/ql/test/stubs/google-android-9.0.0/android/view/Display.java new file mode 100644 index 00000000000..d4832a80460 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/view/Display.java @@ -0,0 +1,88 @@ +// Generated automatically from android.view.Display for testing purposes + +package android.view; + +import android.graphics.ColorSpace; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DisplayMetrics; +import android.view.DisplayCutout; + +public class Display +{ + public ColorSpace getPreferredWideGamutColorSpace(){ return null; } + public Display.HdrCapabilities getHdrCapabilities(){ return null; } + public Display.Mode getMode(){ return null; } + public Display.Mode[] getSupportedModes(){ return null; } + public DisplayCutout getCutout(){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public boolean isHdr(){ return false; } + public boolean isValid(){ return false; } + public boolean isWideColorGamut(){ return false; } + public float getRefreshRate(){ return 0; } + public float[] getSupportedRefreshRates(){ return null; } + public int getDisplayId(){ return 0; } + public int getFlags(){ return 0; } + public int getHeight(){ return 0; } + public int getOrientation(){ return 0; } + public int getPixelFormat(){ return 0; } + public int getRotation(){ return 0; } + public int getState(){ return 0; } + public int getWidth(){ return 0; } + public long getAppVsyncOffsetNanos(){ return 0; } + public long getPresentationDeadlineNanos(){ return 0; } + public static int DEFAULT_DISPLAY = 0; + public static int FLAG_PRESENTATION = 0; + public static int FLAG_PRIVATE = 0; + public static int FLAG_ROUND = 0; + public static int FLAG_SECURE = 0; + public static int FLAG_SUPPORTS_PROTECTED_BUFFERS = 0; + public static int INVALID_DISPLAY = 0; + public static int STATE_DOZE = 0; + public static int STATE_DOZE_SUSPEND = 0; + public static int STATE_OFF = 0; + public static int STATE_ON = 0; + public static int STATE_ON_SUSPEND = 0; + public static int STATE_UNKNOWN = 0; + public static int STATE_VR = 0; + public void getCurrentSizeRange(Point p0, Point p1){} + public void getMetrics(DisplayMetrics p0){} + public void getRealMetrics(DisplayMetrics p0){} + public void getRealSize(Point p0){} + public void getRectSize(Rect p0){} + public void getSize(Point p0){} + static public class HdrCapabilities implements Parcelable + { + public boolean equals(Object p0){ return false; } + public float getDesiredMaxAverageLuminance(){ return 0; } + public float getDesiredMaxLuminance(){ return 0; } + public float getDesiredMinLuminance(){ return 0; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public int[] getSupportedHdrTypes(){ return null; } + public static Parcelable.Creator<Display.HdrCapabilities> CREATOR = null; + public static float INVALID_LUMINANCE = 0; + public static int HDR_TYPE_DOLBY_VISION = 0; + public static int HDR_TYPE_HDR10 = 0; + public static int HDR_TYPE_HDR10_PLUS = 0; + public static int HDR_TYPE_HLG = 0; + public void writeToParcel(Parcel p0, int p1){} + } + static public class Mode implements Parcelable + { + protected Mode() {} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public float getRefreshRate(){ return 0; } + public int describeContents(){ return 0; } + public int getModeId(){ return 0; } + public int getPhysicalHeight(){ return 0; } + public int getPhysicalWidth(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<Display.Mode> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/view/DisplayCutout.java b/java/ql/test/stubs/google-android-9.0.0/android/view/DisplayCutout.java new file mode 100644 index 00000000000..ad045b47acb --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/view/DisplayCutout.java @@ -0,0 +1,26 @@ +// Generated automatically from android.view.DisplayCutout for testing purposes + +package android.view; + +import android.graphics.Insets; +import android.graphics.Rect; +import java.util.List; + +public class DisplayCutout +{ + protected DisplayCutout() {} + public DisplayCutout(Insets p0, Rect p1, Rect p2, Rect p3, Rect p4){} + public DisplayCutout(Rect p0, List<Rect> p1){} + public List<Rect> getBoundingRects(){ return null; } + public Rect getBoundingRectBottom(){ return null; } + public Rect getBoundingRectLeft(){ return null; } + public Rect getBoundingRectRight(){ return null; } + public Rect getBoundingRectTop(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int getSafeInsetBottom(){ return 0; } + public int getSafeInsetLeft(){ return 0; } + public int getSafeInsetRight(){ return 0; } + public int getSafeInsetTop(){ return 0; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/org/xmlpull/v1/XmlPullParser.java b/java/ql/test/stubs/google-android-9.0.0/org/xmlpull/v1/XmlPullParser.java new file mode 100644 index 00000000000..c693a5f6289 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/org/xmlpull/v1/XmlPullParser.java @@ -0,0 +1,64 @@ +// Generated automatically from org.xmlpull.v1.XmlPullParser for testing purposes + +package org.xmlpull.v1; + +import java.io.InputStream; +import java.io.Reader; + +public interface XmlPullParser +{ + Object getProperty(String p0); + String getAttributeName(int p0); + String getAttributeNamespace(int p0); + String getAttributePrefix(int p0); + String getAttributeType(int p0); + String getAttributeValue(String p0, String p1); + String getAttributeValue(int p0); + String getInputEncoding(); + String getName(); + String getNamespace(); + String getNamespace(String p0); + String getNamespacePrefix(int p0); + String getNamespaceUri(int p0); + String getPositionDescription(); + String getPrefix(); + String getText(); + String nextText(); + boolean getFeature(String p0); + boolean isAttributeDefault(int p0); + boolean isEmptyElementTag(); + boolean isWhitespace(); + char[] getTextCharacters(int[] p0); + int getAttributeCount(); + int getColumnNumber(); + int getDepth(); + int getEventType(); + int getLineNumber(); + int getNamespaceCount(int p0); + int next(); + int nextTag(); + int nextToken(); + static String FEATURE_PROCESS_DOCDECL = null; + static String FEATURE_PROCESS_NAMESPACES = null; + static String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = null; + static String FEATURE_VALIDATION = null; + static String NO_NAMESPACE = null; + static String[] TYPES = null; + static int CDSECT = 0; + static int COMMENT = 0; + static int DOCDECL = 0; + static int END_DOCUMENT = 0; + static int END_TAG = 0; + static int ENTITY_REF = 0; + static int IGNORABLE_WHITESPACE = 0; + static int PROCESSING_INSTRUCTION = 0; + static int START_DOCUMENT = 0; + static int START_TAG = 0; + static int TEXT = 0; + void defineEntityReplacementText(String p0, String p1); + void require(int p0, String p1, String p2); + void setFeature(String p0, boolean p1); + void setInput(InputStream p0, String p1); + void setInput(Reader p0); + void setProperty(String p0, Object p1); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/org/xmlpull/v1/XmlSerializer.java b/java/ql/test/stubs/google-android-9.0.0/org/xmlpull/v1/XmlSerializer.java new file mode 100644 index 00000000000..f0a985adebe --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/org/xmlpull/v1/XmlSerializer.java @@ -0,0 +1,35 @@ +// Generated automatically from org.xmlpull.v1.XmlSerializer for testing purposes + +package org.xmlpull.v1; + +import java.io.OutputStream; +import java.io.Writer; + +public interface XmlSerializer +{ + Object getProperty(String p0); + String getName(); + String getNamespace(); + String getPrefix(String p0, boolean p1); + XmlSerializer attribute(String p0, String p1, String p2); + XmlSerializer endTag(String p0, String p1); + XmlSerializer startTag(String p0, String p1); + XmlSerializer text(String p0); + XmlSerializer text(char[] p0, int p1, int p2); + boolean getFeature(String p0); + int getDepth(); + void cdsect(String p0); + void comment(String p0); + void docdecl(String p0); + void endDocument(); + void entityRef(String p0); + void flush(); + void ignorableWhitespace(String p0); + void processingInstruction(String p0); + void setFeature(String p0, boolean p1); + void setOutput(OutputStream p0, String p1); + void setOutput(Writer p0); + void setPrefix(String p0, String p1); + void setProperty(String p0, Object p1); + void startDocument(String p0, Boolean p1); +} From 81c0e66b1de2f7e769a1c6a26974cfd4362b91ad Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 10 Aug 2021 17:50:14 +0100 Subject: [PATCH 232/361] Add change note and update qhelp --- java/change-notes/2021-08-10-gson-unsafe-deserialization.md | 2 ++ .../ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 java/change-notes/2021-08-10-gson-unsafe-deserialization.md diff --git a/java/change-notes/2021-08-10-gson-unsafe-deserialization.md b/java/change-notes/2021-08-10-gson-unsafe-deserialization.md new file mode 100644 index 00000000000..5e0c3f13966 --- /dev/null +++ b/java/change-notes/2021-08-10-gson-unsafe-deserialization.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The "Deserialization of user-controlled data" (`java/unsafe-deserialization`) query now recognizes deserialization using the `Gson` library. diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp index e3c1d8df033..d1933ad4ac2 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp @@ -15,7 +15,7 @@ may have unforeseen effects, such as the execution of arbitrary code. <p> There are many different serialization frameworks. This query currently supports Kryo, XmlDecoder, XStream, SnakeYaml, JYaml, JsonIO, YAMLBeans, HessianBurlap, Castor, Burlap, -Jackson, Jabsorb, Jodd JSON, Flexjson and Java IO serialization through +Jackson, Jabsorb, Jodd JSON, Flexjson, Gson and Java IO serialization through <code>ObjectInputStream</code>/<code>ObjectOutputStream</code>. </p> </overview> @@ -113,6 +113,10 @@ Jodd JSON documentation on deserialization: RCE in Flexjson: <a href="https://codewhitesec.blogspot.com/2020/03/liferay-portal-json-vulns.html">Flexjson deserialization</a>. </li> +<li> +Android Intent deserialization vulnerabilities with GSON parser: +<a href="https://blog.oversecured.com/Exploiting-memory-corruption-vulnerabilities-on-Android/#insecure-use-of-json-parsers">Insecure use of JSON parsers</a>. +</li> </references> </qhelp> From 1dffbcd0bd67e906994b5df917f1146e08a8637f Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Wed, 11 Aug 2021 09:51:47 +0100 Subject: [PATCH 233/361] Fix tests disrupted by re-modelling and stubbing Android 9: * Account for changed dataflow graph shape using external flow * Account for BaseBundle only existing as of Android 5 * Properly implement Parcelable, which we previously got away with due to a partial stub * Restore an Android 11 function that had been added to the Android 9 Context class (I won't get into enforcing the difference in this PR) --- .../code/java/frameworks/android/Android.qll | 8 +- .../security/CWE-502/ParcelableEntity.java | 3 + .../android/content/ClipData.java | 51 +++ .../android/content/ClipDescription.java | 31 ++ .../android/content/ComponentCallbacks.java | 11 + .../android/content/ComponentCallbacks2.java | 17 + .../content/ContentProviderClient.java | 46 +++ .../content/ContentProviderOperation.java | 47 +++ .../content/ContentProviderResult.java | 21 ++ .../android/content/ContentResolver.java | 148 +++++++++ .../android/content/IntentFilter.java | 104 ++++++ .../android/content/IntentSender.java | 41 +++ .../android/content/PeriodicSync.java | 23 ++ .../android/content/ServiceConnection.java | 14 + .../android/content/SyncAdapterType.java | 3 + .../android/content/SyncInfo.java | 17 + .../android/content/SyncRequest.java | 14 + .../android/content/SyncStatusObserver.java | 9 + .../android/content/UriPermission.java | 21 ++ .../android/content/pm/ActivityInfo.java | 111 +++++++ .../android/content/pm/ApplicationInfo.java | 97 ++++++ .../android/content/pm/ChangedPackages.java | 18 + .../android/content/pm/ComponentInfo.java | 29 ++ .../android/content/pm/ConfigurationInfo.java | 3 + .../android/content/pm/FeatureGroupInfo.java | 3 + .../android/content/pm/FeatureInfo.java | 4 + .../content/pm/InstrumentationInfo.java | 27 ++ .../android/content/pm/ModuleInfo.java | 19 ++ .../android/content/pm/PackageInfo.java | 59 ++++ .../android/content/pm/PackageInstaller.java | 146 ++++++++ .../android/content/pm/PackageItemInfo.java | 34 ++ .../android/content/pm/PackageManager.java | 314 ++++++++++++++++++ .../content/pm/PermissionGroupInfo.java | 24 ++ .../android/content/pm/PermissionInfo.java | 48 +++ .../android/content/pm/ProviderInfo.java | 33 ++ .../android/content/pm/ResolveInfo.java | 41 +++ .../android/content/pm/ServiceInfo.java | 35 ++ .../android/content/pm/SharedLibraryInfo.java | 27 ++ .../android/content/pm/Signature.java | 3 + .../android/content/pm/SigningInfo.java | 20 ++ .../android/content/pm/VersionedPackage.java | 20 ++ .../android/content/res/AssetManager.java | 26 ++ .../android/content/res/ColorStateList.java | 27 ++ .../android/content/res/Configuration.java | 129 +++++++ .../android/content/res/Resources.java | 101 ++++++ .../android/content/res/TypedArray.java | 47 +++ .../content/res/XmlResourceParser.java | 12 + 47 files changed, 2083 insertions(+), 3 deletions(-) create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ClipData.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ClipDescription.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ComponentCallbacks.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ComponentCallbacks2.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderClient.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderOperation.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderResult.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ContentResolver.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/IntentFilter.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/IntentSender.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/PeriodicSync.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/ServiceConnection.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/SyncAdapterType.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/SyncInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/SyncRequest.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/SyncStatusObserver.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/UriPermission.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ActivityInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ApplicationInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ChangedPackages.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ComponentInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ConfigurationInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/FeatureGroupInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/FeatureInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/InstrumentationInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ModuleInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageInstaller.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageItemInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageManager.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/PermissionGroupInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/PermissionInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ProviderInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ResolveInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/ServiceInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/SharedLibraryInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/Signature.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/SigningInfo.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/pm/VersionedPackage.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/res/AssetManager.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/res/ColorStateList.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/res/Configuration.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/res/Resources.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/res/TypedArray.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/res/XmlResourceParser.java diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index a7f0a875a22..15bdb1fb95e 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -221,10 +221,12 @@ class CreateFromParcelMethod extends Method { private class TaintPropagationModels extends SummaryModelCsv { override predicate row(string s) { - // BaseBundle getters + // BaseBundle getters. These are also modelled on Bundle because BaseBundle was factored out of Bundle + // in Android 5.0; before that these methods were declared directly on Bundle. s = - "android.os;BaseBundle;true;get" + ["Boolean", "Double", "Int", "Long", "String"] + - ["", "Array"] + ";;;Argument[-1];ReturnValue;taint" + "android.os;" + ["BaseBundle", "Bundle"] + ";true;get" + + ["Boolean", "Double", "Int", "Long", "String"] + ["", "Array"] + + ";;;Argument[-1];ReturnValue;taint" or // Bundle getters s = diff --git a/java/ql/test/query-tests/security/CWE-502/ParcelableEntity.java b/java/ql/test/query-tests/security/CWE-502/ParcelableEntity.java index e151af4a88a..a9cbcabd9d3 100644 --- a/java/ql/test/query-tests/security/CWE-502/ParcelableEntity.java +++ b/java/ql/test/query-tests/security/CWE-502/ParcelableEntity.java @@ -21,6 +21,9 @@ public class ParcelableEntity implements Parcelable { parcel.writeString(GSON.toJson(obj)); } + @Override + public int describeContents() { return 0; } + public static final Parcelable.Creator CREATOR = new Creator<ParcelableEntity>() { @Override public ParcelableEntity createFromParcel(Parcel parcel) { diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ClipData.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ClipData.java new file mode 100644 index 00000000000..490aff3323a --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ClipData.java @@ -0,0 +1,51 @@ +// Generated automatically from android.content.ClipData for testing purposes + +package android.content; + +import android.content.ClipDescription; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +public class ClipData implements Parcelable +{ + protected ClipData() {} + public ClipData(CharSequence p0, String[] p1, ClipData.Item p2){} + public ClipData(ClipData p0){} + public ClipData(ClipDescription p0, ClipData.Item p1){} + public ClipData.Item getItemAt(int p0){ return null; } + public ClipDescription getDescription(){ return null; } + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int getItemCount(){ return 0; } + public static ClipData newHtmlText(CharSequence p0, CharSequence p1, String p2){ return null; } + public static ClipData newIntent(CharSequence p0, Intent p1){ return null; } + public static ClipData newPlainText(CharSequence p0, CharSequence p1){ return null; } + public static ClipData newRawUri(CharSequence p0, Uri p1){ return null; } + public static ClipData newUri(ContentResolver p0, CharSequence p1, Uri p2){ return null; } + public static Parcelable.Creator<ClipData> CREATOR = null; + public void addItem(ClipData.Item p0){} + public void addItem(ContentResolver p0, ClipData.Item p1){} + public void writeToParcel(Parcel p0, int p1){} + static public class Item + { + protected Item() {} + public CharSequence coerceToStyledText(Context p0){ return null; } + public CharSequence coerceToText(Context p0){ return null; } + public CharSequence getText(){ return null; } + public Intent getIntent(){ return null; } + public Item(CharSequence p0){} + public Item(CharSequence p0, Intent p1, Uri p2){} + public Item(CharSequence p0, String p1){} + public Item(CharSequence p0, String p1, Intent p2, Uri p3){} + public Item(Intent p0){} + public Item(Uri p0){} + public String coerceToHtmlText(Context p0){ return null; } + public String getHtmlText(){ return null; } + public String toString(){ return null; } + public Uri getUri(){ return null; } + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ClipDescription.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ClipDescription.java new file mode 100644 index 00000000000..95598cc40cd --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ClipDescription.java @@ -0,0 +1,31 @@ +// Generated automatically from android.content.ClipDescription for testing purposes + +package android.content; + +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; + +public class ClipDescription implements Parcelable +{ + protected ClipDescription() {} + public CharSequence getLabel(){ return null; } + public ClipDescription(CharSequence p0, String[] p1){} + public ClipDescription(ClipDescription p0){} + public PersistableBundle getExtras(){ return null; } + public String getMimeType(int p0){ return null; } + public String toString(){ return null; } + public String[] filterMimeTypes(String p0){ return null; } + public boolean hasMimeType(String p0){ return false; } + public int describeContents(){ return 0; } + public int getMimeTypeCount(){ return 0; } + public long getTimestamp(){ return 0; } + public static Parcelable.Creator<ClipDescription> CREATOR = null; + public static String MIMETYPE_TEXT_HTML = null; + public static String MIMETYPE_TEXT_INTENT = null; + public static String MIMETYPE_TEXT_PLAIN = null; + public static String MIMETYPE_TEXT_URILIST = null; + public static boolean compareMimeTypes(String p0, String p1){ return false; } + public void setExtras(PersistableBundle p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentCallbacks.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentCallbacks.java new file mode 100644 index 00000000000..51726693d00 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentCallbacks.java @@ -0,0 +1,11 @@ +// Generated automatically from android.content.ComponentCallbacks for testing purposes + +package android.content; + +import android.content.res.Configuration; + +public interface ComponentCallbacks +{ + void onConfigurationChanged(Configuration p0); + void onLowMemory(); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentCallbacks2.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentCallbacks2.java new file mode 100644 index 00000000000..f8c83ab104d --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentCallbacks2.java @@ -0,0 +1,17 @@ +// Generated automatically from android.content.ComponentCallbacks2 for testing purposes + +package android.content; + +import android.content.ComponentCallbacks; + +public interface ComponentCallbacks2 extends ComponentCallbacks +{ + static int TRIM_MEMORY_BACKGROUND = 0; + static int TRIM_MEMORY_COMPLETE = 0; + static int TRIM_MEMORY_MODERATE = 0; + static int TRIM_MEMORY_RUNNING_CRITICAL = 0; + static int TRIM_MEMORY_RUNNING_LOW = 0; + static int TRIM_MEMORY_RUNNING_MODERATE = 0; + static int TRIM_MEMORY_UI_HIDDEN = 0; + void onTrimMemory(int p0); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderClient.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderClient.java new file mode 100644 index 00000000000..b1b171f7649 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderClient.java @@ -0,0 +1,46 @@ +// Generated automatically from android.content.ContentProviderClient for testing purposes + +package android.content; + +import android.content.ContentProvider; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentValues; +import android.content.res.AssetFileDescriptor; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.os.CancellationSignal; +import android.os.ParcelFileDescriptor; +import java.util.ArrayList; + +public class ContentProviderClient implements AutoCloseable +{ + protected void finalize(){} + public AssetFileDescriptor openAssetFile(Uri p0, String p1){ return null; } + public AssetFileDescriptor openAssetFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public Bundle call(String p0, String p1, Bundle p2){ return null; } + public Bundle call(String p0, String p1, String p2, Bundle p3){ return null; } + public ContentProvider getLocalContentProvider(){ return null; } + public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> p0){ return null; } + public ContentProviderResult[] applyBatch(String p0, ArrayList<ContentProviderOperation> p1){ return null; } + public Cursor query(Uri p0, String[] p1, Bundle p2, CancellationSignal p3){ return null; } + public Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4){ return null; } + public Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4, CancellationSignal p5){ return null; } + public ParcelFileDescriptor openFile(Uri p0, String p1){ return null; } + public ParcelFileDescriptor openFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public String getType(Uri p0){ return null; } + public String[] getStreamTypes(Uri p0, String p1){ return null; } + public Uri insert(Uri p0, ContentValues p1){ return null; } + public boolean refresh(Uri p0, Bundle p1, CancellationSignal p2){ return false; } + public boolean release(){ return false; } + public final AssetFileDescriptor openTypedAssetFile(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri p0, String p1, Bundle p2){ return null; } + public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public final Uri canonicalize(Uri p0){ return null; } + public final Uri uncanonicalize(Uri p0){ return null; } + public int bulkInsert(Uri p0, ContentValues[] p1){ return 0; } + public int delete(Uri p0, String p1, String[] p2){ return 0; } + public int update(Uri p0, ContentValues p1, String p2, String[] p3){ return 0; } + public void close(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderOperation.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderOperation.java new file mode 100644 index 00000000000..168b33fd7d6 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderOperation.java @@ -0,0 +1,47 @@ +// Generated automatically from android.content.ContentProviderOperation for testing purposes + +package android.content; + +import android.content.ContentProvider; +import android.content.ContentProviderResult; +import android.content.ContentValues; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +public class ContentProviderOperation implements Parcelable +{ + protected ContentProviderOperation() {} + public ContentProviderResult apply(ContentProvider p0, ContentProviderResult[] p1, int p2){ return null; } + public ContentValues resolveValueBackReferences(ContentProviderResult[] p0, int p1){ return null; } + public String toString(){ return null; } + public String[] resolveSelectionArgsBackReferences(ContentProviderResult[] p0, int p1){ return null; } + public Uri getUri(){ return null; } + public boolean isAssertQuery(){ return false; } + public boolean isDelete(){ return false; } + public boolean isInsert(){ return false; } + public boolean isReadOperation(){ return false; } + public boolean isUpdate(){ return false; } + public boolean isWriteOperation(){ return false; } + public boolean isYieldAllowed(){ return false; } + public int describeContents(){ return 0; } + public static ContentProviderOperation.Builder newAssertQuery(Uri p0){ return null; } + public static ContentProviderOperation.Builder newDelete(Uri p0){ return null; } + public static ContentProviderOperation.Builder newInsert(Uri p0){ return null; } + public static ContentProviderOperation.Builder newUpdate(Uri p0){ return null; } + public static Parcelable.Creator<ContentProviderOperation> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} + static public class Builder + { + protected Builder() {} + public ContentProviderOperation build(){ return null; } + public ContentProviderOperation.Builder withExpectedCount(int p0){ return null; } + public ContentProviderOperation.Builder withSelection(String p0, String[] p1){ return null; } + public ContentProviderOperation.Builder withSelectionBackReference(int p0, int p1){ return null; } + public ContentProviderOperation.Builder withValue(String p0, Object p1){ return null; } + public ContentProviderOperation.Builder withValueBackReference(String p0, int p1){ return null; } + public ContentProviderOperation.Builder withValueBackReferences(ContentValues p0){ return null; } + public ContentProviderOperation.Builder withValues(ContentValues p0){ return null; } + public ContentProviderOperation.Builder withYieldAllowed(boolean p0){ return null; } + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderResult.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderResult.java new file mode 100644 index 00000000000..e29865ee4c1 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ContentProviderResult.java @@ -0,0 +1,21 @@ +// Generated automatically from android.content.ContentProviderResult for testing purposes + +package android.content; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +public class ContentProviderResult implements Parcelable +{ + protected ContentProviderResult() {} + public ContentProviderResult(Parcel p0){} + public ContentProviderResult(Uri p0){} + public ContentProviderResult(int p0){} + public String toString(){ return null; } + public final Integer count = null; + public final Uri uri = null; + public int describeContents(){ return 0; } + public static Parcelable.Creator<ContentProviderResult> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ContentResolver.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ContentResolver.java new file mode 100644 index 00000000000..a5b7f1b0b46 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ContentResolver.java @@ -0,0 +1,148 @@ +// Generated automatically from android.content.ContentResolver for testing purposes + +package android.content; + +import android.accounts.Account; +import android.content.ContentProvider; +import android.content.ContentProviderClient; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentValues; +import android.content.Context; +import android.content.PeriodicSync; +import android.content.SyncAdapterType; +import android.content.SyncInfo; +import android.content.SyncRequest; +import android.content.SyncStatusObserver; +import android.content.UriPermission; +import android.content.res.AssetFileDescriptor; +import android.database.ContentObserver; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.drawable.Icon; +import android.net.Uri; +import android.os.Bundle; +import android.os.CancellationSignal; +import android.os.ParcelFileDescriptor; +import android.util.Size; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +abstract public class ContentResolver +{ + protected ContentResolver() {} + public Bitmap loadThumbnail(Uri p0, Size p1, CancellationSignal p2){ return null; } + public ContentProviderResult[] applyBatch(String p0, ArrayList<ContentProviderOperation> p1){ return null; } + public ContentResolver(Context p0){} + public List<UriPermission> getOutgoingPersistedUriPermissions(){ return null; } + public List<UriPermission> getPersistedUriPermissions(){ return null; } + public String[] getStreamTypes(Uri p0, String p1){ return null; } + public final AssetFileDescriptor openAssetFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public final AssetFileDescriptor openAssetFileDescriptor(Uri p0, String p1){ return null; } + public final AssetFileDescriptor openAssetFileDescriptor(Uri p0, String p1, CancellationSignal p2){ return null; } + public final AssetFileDescriptor openTypedAssetFile(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri p0, String p1, Bundle p2){ return null; } + public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri p0, String p1, Bundle p2, CancellationSignal p3){ return null; } + public final Bundle call(String p0, String p1, String p2, Bundle p3){ return null; } + public final Bundle call(Uri p0, String p1, String p2, Bundle p3){ return null; } + public final ContentProviderClient acquireContentProviderClient(String p0){ return null; } + public final ContentProviderClient acquireContentProviderClient(Uri p0){ return null; } + public final ContentProviderClient acquireUnstableContentProviderClient(String p0){ return null; } + public final ContentProviderClient acquireUnstableContentProviderClient(Uri p0){ return null; } + public final ContentResolver.MimeTypeInfo getTypeInfo(String p0){ return null; } + public final Cursor query(Uri p0, String[] p1, Bundle p2, CancellationSignal p3){ return null; } + public final Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4){ return null; } + public final Cursor query(Uri p0, String[] p1, String p2, String[] p3, String p4, CancellationSignal p5){ return null; } + public final InputStream openInputStream(Uri p0){ return null; } + public final OutputStream openOutputStream(Uri p0){ return null; } + public final OutputStream openOutputStream(Uri p0, String p1){ return null; } + public final ParcelFileDescriptor openFile(Uri p0, String p1, CancellationSignal p2){ return null; } + public final ParcelFileDescriptor openFileDescriptor(Uri p0, String p1){ return null; } + public final ParcelFileDescriptor openFileDescriptor(Uri p0, String p1, CancellationSignal p2){ return null; } + public final String getType(Uri p0){ return null; } + public final Uri canonicalize(Uri p0){ return null; } + public final Uri insert(Uri p0, ContentValues p1){ return null; } + public final Uri uncanonicalize(Uri p0){ return null; } + public final boolean refresh(Uri p0, Bundle p1, CancellationSignal p2){ return false; } + public final int bulkInsert(Uri p0, ContentValues[] p1){ return 0; } + public final int delete(Uri p0, String p1, String[] p2){ return 0; } + public final int update(Uri p0, ContentValues p1, String p2, String[] p3){ return 0; } + public final void registerContentObserver(Uri p0, boolean p1, ContentObserver p2){} + public final void unregisterContentObserver(ContentObserver p0){} + public static ContentResolver wrap(ContentProvider p0){ return null; } + public static ContentResolver wrap(ContentProviderClient p0){ return null; } + public static List<PeriodicSync> getPeriodicSyncs(Account p0, String p1){ return null; } + public static List<SyncInfo> getCurrentSyncs(){ return null; } + public static Object addStatusChangeListener(int p0, SyncStatusObserver p1){ return null; } + public static String ANY_CURSOR_ITEM_TYPE = null; + public static String CURSOR_DIR_BASE_TYPE = null; + public static String CURSOR_ITEM_BASE_TYPE = null; + public static String EXTRA_HONORED_ARGS = null; + public static String EXTRA_REFRESH_SUPPORTED = null; + public static String EXTRA_SIZE = null; + public static String EXTRA_TOTAL_COUNT = null; + public static String QUERY_ARG_LIMIT = null; + public static String QUERY_ARG_OFFSET = null; + public static String QUERY_ARG_SORT_COLLATION = null; + public static String QUERY_ARG_SORT_COLUMNS = null; + public static String QUERY_ARG_SORT_DIRECTION = null; + public static String QUERY_ARG_SQL_SELECTION = null; + public static String QUERY_ARG_SQL_SELECTION_ARGS = null; + public static String QUERY_ARG_SQL_SORT_ORDER = null; + public static String SCHEME_ANDROID_RESOURCE = null; + public static String SCHEME_CONTENT = null; + public static String SCHEME_FILE = null; + public static String SYNC_EXTRAS_ACCOUNT = null; + public static String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = null; + public static String SYNC_EXTRAS_DO_NOT_RETRY = null; + public static String SYNC_EXTRAS_EXPEDITED = null; + public static String SYNC_EXTRAS_FORCE = null; + public static String SYNC_EXTRAS_IGNORE_BACKOFF = null; + public static String SYNC_EXTRAS_IGNORE_SETTINGS = null; + public static String SYNC_EXTRAS_INITIALIZE = null; + public static String SYNC_EXTRAS_MANUAL = null; + public static String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = null; + public static String SYNC_EXTRAS_REQUIRE_CHARGING = null; + public static String SYNC_EXTRAS_UPLOAD = null; + public static SyncAdapterType[] getSyncAdapterTypes(){ return null; } + public static SyncInfo getCurrentSync(){ return null; } + public static boolean getMasterSyncAutomatically(){ return false; } + public static boolean getSyncAutomatically(Account p0, String p1){ return false; } + public static boolean isSyncActive(Account p0, String p1){ return false; } + public static boolean isSyncPending(Account p0, String p1){ return false; } + public static int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 0; + public static int NOTIFY_SYNC_TO_NETWORK = 0; + public static int QUERY_SORT_DIRECTION_ASCENDING = 0; + public static int QUERY_SORT_DIRECTION_DESCENDING = 0; + public static int SYNC_OBSERVER_TYPE_ACTIVE = 0; + public static int SYNC_OBSERVER_TYPE_PENDING = 0; + public static int SYNC_OBSERVER_TYPE_SETTINGS = 0; + public static int getIsSyncable(Account p0, String p1){ return 0; } + public static void addPeriodicSync(Account p0, String p1, Bundle p2, long p3){} + public static void cancelSync(Account p0, String p1){} + public static void cancelSync(SyncRequest p0){} + public static void removePeriodicSync(Account p0, String p1, Bundle p2){} + public static void removeStatusChangeListener(Object p0){} + public static void requestSync(Account p0, String p1, Bundle p2){} + public static void requestSync(SyncRequest p0){} + public static void setIsSyncable(Account p0, String p1, int p2){} + public static void setMasterSyncAutomatically(boolean p0){} + public static void setSyncAutomatically(Account p0, String p1, boolean p2){} + public static void validateSyncExtrasBundle(Bundle p0){} + public void cancelSync(Uri p0){} + public void notifyChange(Uri p0, ContentObserver p1){} + public void notifyChange(Uri p0, ContentObserver p1, boolean p2){} + public void notifyChange(Uri p0, ContentObserver p1, int p2){} + public void releasePersistableUriPermission(Uri p0, int p1){} + public void startSync(Uri p0, Bundle p1){} + public void takePersistableUriPermission(Uri p0, int p1){} + static public class MimeTypeInfo + { + protected MimeTypeInfo() {} + public CharSequence getContentDescription(){ return null; } + public CharSequence getLabel(){ return null; } + public Icon getIcon(){ return null; } + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/IntentFilter.java b/java/ql/test/stubs/google-android-9.0.0/android/content/IntentFilter.java new file mode 100644 index 00000000000..99de8481e14 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/IntentFilter.java @@ -0,0 +1,104 @@ +// Generated automatically from android.content.IntentFilter for testing purposes + +package android.content; + +import android.content.ContentResolver; +import android.content.Intent; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; +import android.util.AndroidException; +import android.util.Printer; +import java.util.Iterator; +import java.util.Set; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlSerializer; + +public class IntentFilter implements Parcelable +{ + public IntentFilter(){} + public IntentFilter(IntentFilter p0){} + public IntentFilter(String p0){} + public IntentFilter(String p0, String p1){} + public final IntentFilter.AuthorityEntry getDataAuthority(int p0){ return null; } + public final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator(){ return null; } + public final Iterator<PatternMatcher> pathsIterator(){ return null; } + public final Iterator<PatternMatcher> schemeSpecificPartsIterator(){ return null; } + public final Iterator<String> actionsIterator(){ return null; } + public final Iterator<String> categoriesIterator(){ return null; } + public final Iterator<String> schemesIterator(){ return null; } + public final Iterator<String> typesIterator(){ return null; } + public final PatternMatcher getDataPath(int p0){ return null; } + public final PatternMatcher getDataSchemeSpecificPart(int p0){ return null; } + public final String getAction(int p0){ return null; } + public final String getCategory(int p0){ return null; } + public final String getDataScheme(int p0){ return null; } + public final String getDataType(int p0){ return null; } + public final String matchCategories(Set<String> p0){ return null; } + public final boolean hasAction(String p0){ return false; } + public final boolean hasCategory(String p0){ return false; } + public final boolean hasDataAuthority(Uri p0){ return false; } + public final boolean hasDataPath(String p0){ return false; } + public final boolean hasDataScheme(String p0){ return false; } + public final boolean hasDataSchemeSpecificPart(String p0){ return false; } + public final boolean hasDataType(String p0){ return false; } + public final boolean matchAction(String p0){ return false; } + public final int countActions(){ return 0; } + public final int countCategories(){ return 0; } + public final int countDataAuthorities(){ return 0; } + public final int countDataPaths(){ return 0; } + public final int countDataSchemeSpecificParts(){ return 0; } + public final int countDataSchemes(){ return 0; } + public final int countDataTypes(){ return 0; } + public final int describeContents(){ return 0; } + public final int getPriority(){ return 0; } + public final int match(ContentResolver p0, Intent p1, boolean p2, String p3){ return 0; } + public final int match(String p0, String p1, String p2, Uri p3, Set<String> p4, String p5){ return 0; } + public final int matchData(String p0, String p1, Uri p2){ return 0; } + public final int matchDataAuthority(Uri p0){ return 0; } + public final void addAction(String p0){} + public final void addCategory(String p0){} + public final void addDataAuthority(String p0, String p1){} + public final void addDataPath(String p0, int p1){} + public final void addDataScheme(String p0){} + public final void addDataSchemeSpecificPart(String p0, int p1){} + public final void addDataType(String p0){} + public final void setPriority(int p0){} + public final void writeToParcel(Parcel p0, int p1){} + public static IntentFilter create(String p0, String p1){ return null; } + public static Parcelable.Creator<IntentFilter> CREATOR = null; + public static int MATCH_ADJUSTMENT_MASK = 0; + public static int MATCH_ADJUSTMENT_NORMAL = 0; + public static int MATCH_CATEGORY_EMPTY = 0; + public static int MATCH_CATEGORY_HOST = 0; + public static int MATCH_CATEGORY_MASK = 0; + public static int MATCH_CATEGORY_PATH = 0; + public static int MATCH_CATEGORY_PORT = 0; + public static int MATCH_CATEGORY_SCHEME = 0; + public static int MATCH_CATEGORY_SCHEME_SPECIFIC_PART = 0; + public static int MATCH_CATEGORY_TYPE = 0; + public static int NO_MATCH_ACTION = 0; + public static int NO_MATCH_CATEGORY = 0; + public static int NO_MATCH_DATA = 0; + public static int NO_MATCH_TYPE = 0; + public static int SYSTEM_HIGH_PRIORITY = 0; + public static int SYSTEM_LOW_PRIORITY = 0; + public void dump(Printer p0, String p1){} + public void readFromXml(XmlPullParser p0){} + public void writeToXml(XmlSerializer p0){} + static public class AuthorityEntry + { + protected AuthorityEntry() {} + public AuthorityEntry(String p0, String p1){} + public String getHost(){ return null; } + public boolean equals(Object p0){ return false; } + public int getPort(){ return 0; } + public int match(Uri p0){ return 0; } + } + static public class MalformedMimeTypeException extends AndroidException + { + public MalformedMimeTypeException(){} + public MalformedMimeTypeException(String p0){} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/IntentSender.java b/java/ql/test/stubs/google-android-9.0.0/android/content/IntentSender.java new file mode 100644 index 00000000000..378c92e0d0b --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/IntentSender.java @@ -0,0 +1,41 @@ +// Generated automatically from android.content.IntentSender for testing purposes + +package android.content; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; +import android.util.AndroidException; + +public class IntentSender implements Parcelable +{ + protected IntentSender() {} + public String getCreatorPackage(){ return null; } + public String getTargetPackage(){ return null; } + public String toString(){ return null; } + public UserHandle getCreatorUserHandle(){ return null; } + public boolean equals(Object p0){ return false; } + public int describeContents(){ return 0; } + public int getCreatorUid(){ return 0; } + public int hashCode(){ return 0; } + public static IntentSender readIntentSenderOrNullFromParcel(Parcel p0){ return null; } + public static Parcelable.Creator<IntentSender> CREATOR = null; + public static void writeIntentSenderOrNullToParcel(IntentSender p0, Parcel p1){} + public void sendIntent(Context p0, int p1, Intent p2, IntentSender.OnFinished p3, Handler p4){} + public void sendIntent(Context p0, int p1, Intent p2, IntentSender.OnFinished p3, Handler p4, String p5){} + public void writeToParcel(Parcel p0, int p1){} + static public class SendIntentException extends AndroidException + { + public SendIntentException(){} + public SendIntentException(Exception p0){} + public SendIntentException(String p0){} + } + static public interface OnFinished + { + void onSendFinished(IntentSender p0, Intent p1, int p2, String p3, Bundle p4); + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/PeriodicSync.java b/java/ql/test/stubs/google-android-9.0.0/android/content/PeriodicSync.java new file mode 100644 index 00000000000..6842c06d22f --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/PeriodicSync.java @@ -0,0 +1,23 @@ +// Generated automatically from android.content.PeriodicSync for testing purposes + +package android.content; + +import android.accounts.Account; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +public class PeriodicSync implements Parcelable +{ + protected PeriodicSync() {} + public PeriodicSync(Account p0, String p1, Bundle p2, long p3){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final Account account = null; + public final Bundle extras = null; + public final String authority = null; + public final long period = 0; + public int describeContents(){ return 0; } + public static Parcelable.Creator<PeriodicSync> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ServiceConnection.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ServiceConnection.java new file mode 100644 index 00000000000..1b8534539c4 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ServiceConnection.java @@ -0,0 +1,14 @@ +// Generated automatically from android.content.ServiceConnection for testing purposes + +package android.content; + +import android.content.ComponentName; +import android.os.IBinder; + +public interface ServiceConnection +{ + default void onBindingDied(ComponentName p0){} + default void onNullBinding(ComponentName p0){} + void onServiceConnected(ComponentName p0, IBinder p1); + void onServiceDisconnected(ComponentName p0); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/SyncAdapterType.java b/java/ql/test/stubs/google-android-9.0.0/android/content/SyncAdapterType.java new file mode 100644 index 00000000000..bc450b6c353 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/SyncAdapterType.java @@ -0,0 +1,3 @@ +package android.content; + +interface SyncAdapterType { } \ No newline at end of file diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/SyncInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/SyncInfo.java new file mode 100644 index 00000000000..e7e1da41477 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/SyncInfo.java @@ -0,0 +1,17 @@ +// Generated automatically from android.content.SyncInfo for testing purposes + +package android.content; + +import android.accounts.Account; +import android.os.Parcel; +import android.os.Parcelable; + +public class SyncInfo implements Parcelable +{ + protected SyncInfo() {} + public final Account account = null; + public final String authority = null; + public final long startTime = 0; + public int describeContents(){ return 0; } + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/SyncRequest.java b/java/ql/test/stubs/google-android-9.0.0/android/content/SyncRequest.java new file mode 100644 index 00000000000..2340b67b1cf --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/SyncRequest.java @@ -0,0 +1,14 @@ +// Generated automatically from android.content.SyncRequest for testing purposes + +package android.content; + +import android.os.Parcel; +import android.os.Parcelable; + +public class SyncRequest implements Parcelable +{ + protected SyncRequest() {} + public int describeContents(){ return 0; } + public static Parcelable.Creator<SyncRequest> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/SyncStatusObserver.java b/java/ql/test/stubs/google-android-9.0.0/android/content/SyncStatusObserver.java new file mode 100644 index 00000000000..534cd549be0 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/SyncStatusObserver.java @@ -0,0 +1,9 @@ +// Generated automatically from android.content.SyncStatusObserver for testing purposes + +package android.content; + + +public interface SyncStatusObserver +{ + void onStatusChanged(int p0); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/UriPermission.java b/java/ql/test/stubs/google-android-9.0.0/android/content/UriPermission.java new file mode 100644 index 00000000000..600a483a589 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/UriPermission.java @@ -0,0 +1,21 @@ +// Generated automatically from android.content.UriPermission for testing purposes + +package android.content; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +public class UriPermission implements Parcelable +{ + protected UriPermission() {} + public String toString(){ return null; } + public Uri getUri(){ return null; } + public boolean isReadPermission(){ return false; } + public boolean isWritePermission(){ return false; } + public int describeContents(){ return 0; } + public long getPersistedTime(){ return 0; } + public static Parcelable.Creator<UriPermission> CREATOR = null; + public static long INVALID_TIME = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ActivityInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ActivityInfo.java new file mode 100644 index 00000000000..2fea1ef0771 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ActivityInfo.java @@ -0,0 +1,111 @@ +// Generated automatically from android.content.pm.ActivityInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ComponentInfo; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +public class ActivityInfo extends ComponentInfo implements Parcelable +{ + public ActivityInfo(){} + public ActivityInfo(ActivityInfo p0){} + public ActivityInfo.WindowLayout windowLayout = null; + public String parentActivityName = null; + public String permission = null; + public String targetActivity = null; + public String taskAffinity = null; + public String toString(){ return null; } + public final int getThemeResource(){ return 0; } + public int colorMode = 0; + public int configChanges = 0; + public int describeContents(){ return 0; } + public int documentLaunchMode = 0; + public int flags = 0; + public int launchMode = 0; + public int maxRecents = 0; + public int persistableMode = 0; + public int screenOrientation = 0; + public int softInputMode = 0; + public int theme = 0; + public int uiOptions = 0; + public static Parcelable.Creator<ActivityInfo> CREATOR = null; + public static int COLOR_MODE_DEFAULT = 0; + public static int COLOR_MODE_HDR = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT = 0; + public static int CONFIG_COLOR_MODE = 0; + public static int CONFIG_DENSITY = 0; + public static int CONFIG_FONT_SCALE = 0; + public static int CONFIG_KEYBOARD = 0; + public static int CONFIG_KEYBOARD_HIDDEN = 0; + public static int CONFIG_LAYOUT_DIRECTION = 0; + public static int CONFIG_LOCALE = 0; + public static int CONFIG_MCC = 0; + public static int CONFIG_MNC = 0; + public static int CONFIG_NAVIGATION = 0; + public static int CONFIG_ORIENTATION = 0; + public static int CONFIG_SCREEN_LAYOUT = 0; + public static int CONFIG_SCREEN_SIZE = 0; + public static int CONFIG_SMALLEST_SCREEN_SIZE = 0; + public static int CONFIG_TOUCHSCREEN = 0; + public static int CONFIG_UI_MODE = 0; + public static int DOCUMENT_LAUNCH_ALWAYS = 0; + public static int DOCUMENT_LAUNCH_INTO_EXISTING = 0; + public static int DOCUMENT_LAUNCH_NEVER = 0; + public static int DOCUMENT_LAUNCH_NONE = 0; + public static int FLAG_ALLOW_TASK_REPARENTING = 0; + public static int FLAG_ALWAYS_RETAIN_TASK_STATE = 0; + public static int FLAG_AUTO_REMOVE_FROM_RECENTS = 0; + public static int FLAG_CLEAR_TASK_ON_LAUNCH = 0; + public static int FLAG_ENABLE_VR_MODE = 0; + public static int FLAG_EXCLUDE_FROM_RECENTS = 0; + public static int FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS = 0; + public static int FLAG_FINISH_ON_TASK_LAUNCH = 0; + public static int FLAG_HARDWARE_ACCELERATED = 0; + public static int FLAG_IMMERSIVE = 0; + public static int FLAG_MULTIPROCESS = 0; + public static int FLAG_NO_HISTORY = 0; + public static int FLAG_RELINQUISH_TASK_IDENTITY = 0; + public static int FLAG_RESUME_WHILE_PAUSING = 0; + public static int FLAG_SINGLE_USER = 0; + public static int FLAG_STATE_NOT_NEEDED = 0; + public static int LAUNCH_MULTIPLE = 0; + public static int LAUNCH_SINGLE_INSTANCE = 0; + public static int LAUNCH_SINGLE_TASK = 0; + public static int LAUNCH_SINGLE_TOP = 0; + public static int PERSIST_ACROSS_REBOOTS = 0; + public static int PERSIST_NEVER = 0; + public static int PERSIST_ROOT_ONLY = 0; + public static int SCREEN_ORIENTATION_BEHIND = 0; + public static int SCREEN_ORIENTATION_FULL_SENSOR = 0; + public static int SCREEN_ORIENTATION_FULL_USER = 0; + public static int SCREEN_ORIENTATION_LANDSCAPE = 0; + public static int SCREEN_ORIENTATION_LOCKED = 0; + public static int SCREEN_ORIENTATION_NOSENSOR = 0; + public static int SCREEN_ORIENTATION_PORTRAIT = 0; + public static int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 0; + public static int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 0; + public static int SCREEN_ORIENTATION_SENSOR = 0; + public static int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 0; + public static int SCREEN_ORIENTATION_SENSOR_PORTRAIT = 0; + public static int SCREEN_ORIENTATION_UNSPECIFIED = 0; + public static int SCREEN_ORIENTATION_USER = 0; + public static int SCREEN_ORIENTATION_USER_LANDSCAPE = 0; + public static int SCREEN_ORIENTATION_USER_PORTRAIT = 0; + public static int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 0; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} + static public class WindowLayout + { + protected WindowLayout() {} + public WindowLayout(int p0, float p1, int p2, float p3, int p4, int p5, int p6){} + public final float heightFraction = 0; + public final float widthFraction = 0; + public final int gravity = 0; + public final int height = 0; + public final int minHeight = 0; + public final int minWidth = 0; + public final int width = 0; + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ApplicationInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ApplicationInfo.java new file mode 100644 index 00000000000..7212b09588b --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ApplicationInfo.java @@ -0,0 +1,97 @@ +// Generated automatically from android.content.pm.ApplicationInfo for testing purposes + +package android.content.pm; + +import android.content.Context; +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; +import java.util.UUID; + +public class ApplicationInfo extends PackageItemInfo implements Parcelable +{ + public ApplicationInfo(){} + public ApplicationInfo(ApplicationInfo p0){} + public CharSequence loadDescription(PackageManager p0){ return null; } + public String appComponentFactory = null; + public String backupAgentName = null; + public String className = null; + public String dataDir = null; + public String deviceProtectedDataDir = null; + public String manageSpaceActivityName = null; + public String nativeLibraryDir = null; + public String permission = null; + public String processName = null; + public String publicSourceDir = null; + public String sourceDir = null; + public String taskAffinity = null; + public String toString(){ return null; } + public String[] sharedLibraryFiles = null; + public String[] splitNames = null; + public String[] splitPublicSourceDirs = null; + public String[] splitSourceDirs = null; + public UUID storageUuid = null; + public boolean enabled = false; + public boolean isProfileableByShell(){ return false; } + public boolean isResourceOverlay(){ return false; } + public boolean isVirtualPreload(){ return false; } + public int category = 0; + public int compatibleWidthLimitDp = 0; + public int describeContents(){ return 0; } + public int descriptionRes = 0; + public int flags = 0; + public int largestWidthLimitDp = 0; + public int minSdkVersion = 0; + public int requiresSmallestWidthDp = 0; + public int targetSdkVersion = 0; + public int theme = 0; + public int uiOptions = 0; + public int uid = 0; + public static CharSequence getCategoryTitle(Context p0, int p1){ return null; } + public static Parcelable.Creator<ApplicationInfo> CREATOR = null; + public static int CATEGORY_AUDIO = 0; + public static int CATEGORY_GAME = 0; + public static int CATEGORY_IMAGE = 0; + public static int CATEGORY_MAPS = 0; + public static int CATEGORY_NEWS = 0; + public static int CATEGORY_PRODUCTIVITY = 0; + public static int CATEGORY_SOCIAL = 0; + public static int CATEGORY_UNDEFINED = 0; + public static int CATEGORY_VIDEO = 0; + public static int FLAG_ALLOW_BACKUP = 0; + public static int FLAG_ALLOW_CLEAR_USER_DATA = 0; + public static int FLAG_ALLOW_TASK_REPARENTING = 0; + public static int FLAG_DEBUGGABLE = 0; + public static int FLAG_EXTERNAL_STORAGE = 0; + public static int FLAG_EXTRACT_NATIVE_LIBS = 0; + public static int FLAG_FACTORY_TEST = 0; + public static int FLAG_FULL_BACKUP_ONLY = 0; + public static int FLAG_HARDWARE_ACCELERATED = 0; + public static int FLAG_HAS_CODE = 0; + public static int FLAG_INSTALLED = 0; + public static int FLAG_IS_DATA_ONLY = 0; + public static int FLAG_IS_GAME = 0; + public static int FLAG_KILL_AFTER_RESTORE = 0; + public static int FLAG_LARGE_HEAP = 0; + public static int FLAG_MULTIARCH = 0; + public static int FLAG_PERSISTENT = 0; + public static int FLAG_RESIZEABLE_FOR_SCREENS = 0; + public static int FLAG_RESTORE_ANY_VERSION = 0; + public static int FLAG_STOPPED = 0; + public static int FLAG_SUPPORTS_LARGE_SCREENS = 0; + public static int FLAG_SUPPORTS_NORMAL_SCREENS = 0; + public static int FLAG_SUPPORTS_RTL = 0; + public static int FLAG_SUPPORTS_SCREEN_DENSITIES = 0; + public static int FLAG_SUPPORTS_SMALL_SCREENS = 0; + public static int FLAG_SUPPORTS_XLARGE_SCREENS = 0; + public static int FLAG_SUSPENDED = 0; + public static int FLAG_SYSTEM = 0; + public static int FLAG_TEST_ONLY = 0; + public static int FLAG_UPDATED_SYSTEM_APP = 0; + public static int FLAG_USES_CLEARTEXT_TRAFFIC = 0; + public static int FLAG_VM_SAFE_MODE = 0; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ChangedPackages.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ChangedPackages.java new file mode 100644 index 00000000000..08c10b13f3c --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ChangedPackages.java @@ -0,0 +1,18 @@ +// Generated automatically from android.content.pm.ChangedPackages for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import java.util.List; + +public class ChangedPackages implements Parcelable +{ + protected ChangedPackages() {} + public ChangedPackages(int p0, List<String> p1){} + public List<String> getPackageNames(){ return null; } + public int describeContents(){ return 0; } + public int getSequenceNumber(){ return 0; } + public static Parcelable.Creator<ChangedPackages> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ComponentInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ComponentInfo.java new file mode 100644 index 00000000000..fb92a43adbe --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ComponentInfo.java @@ -0,0 +1,29 @@ +// Generated automatically from android.content.pm.ComponentInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageItemInfo; +import android.os.Parcel; +import android.util.Printer; + +public class ComponentInfo extends PackageItemInfo +{ + protected ComponentInfo(Parcel p0){} + protected void dumpBack(Printer p0, String p1){} + protected void dumpFront(Printer p0, String p1){} + public ApplicationInfo applicationInfo = null; + public ComponentInfo(){} + public ComponentInfo(ComponentInfo p0){} + public String processName = null; + public String splitName = null; + public boolean directBootAware = false; + public boolean enabled = false; + public boolean exported = false; + public boolean isEnabled(){ return false; } + public final int getBannerResource(){ return 0; } + public final int getIconResource(){ return 0; } + public final int getLogoResource(){ return 0; } + public int descriptionRes = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ConfigurationInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ConfigurationInfo.java new file mode 100644 index 00000000000..43fc1954d8c --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ConfigurationInfo.java @@ -0,0 +1,3 @@ +package android.content.pm; + +interface ConfigurationInfo { } \ No newline at end of file diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/FeatureGroupInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/FeatureGroupInfo.java new file mode 100644 index 00000000000..402fdc55391 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/FeatureGroupInfo.java @@ -0,0 +1,3 @@ +package android.content.pm; + +interface FeatureGroupInfo { } \ No newline at end of file diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/FeatureInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/FeatureInfo.java new file mode 100644 index 00000000000..05c2028d40e --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/FeatureInfo.java @@ -0,0 +1,4 @@ + +package android.content.pm; + +interface FeatureInfo { } \ No newline at end of file diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/InstrumentationInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/InstrumentationInfo.java new file mode 100644 index 00000000000..70063a09744 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/InstrumentationInfo.java @@ -0,0 +1,27 @@ +// Generated automatically from android.content.pm.InstrumentationInfo for testing purposes + +package android.content.pm; + +import android.content.pm.PackageItemInfo; +import android.os.Parcel; +import android.os.Parcelable; + +public class InstrumentationInfo extends PackageItemInfo implements Parcelable +{ + public InstrumentationInfo(){} + public InstrumentationInfo(InstrumentationInfo p0){} + public String dataDir = null; + public String publicSourceDir = null; + public String sourceDir = null; + public String targetPackage = null; + public String targetProcesses = null; + public String toString(){ return null; } + public String[] splitNames = null; + public String[] splitPublicSourceDirs = null; + public String[] splitSourceDirs = null; + public boolean functionalTest = false; + public boolean handleProfiling = false; + public int describeContents(){ return 0; } + public static Parcelable.Creator<InstrumentationInfo> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ModuleInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ModuleInfo.java new file mode 100644 index 00000000000..c7aef5f7ac7 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ModuleInfo.java @@ -0,0 +1,19 @@ +// Generated automatically from android.content.pm.ModuleInfo for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +public class ModuleInfo implements Parcelable +{ + public CharSequence getName(){ return null; } + public String getPackageName(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isHidden(){ return false; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static Parcelable.Creator<ModuleInfo> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageInfo.java new file mode 100644 index 00000000000..566e8e73fbf --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageInfo.java @@ -0,0 +1,59 @@ +// Generated automatically from android.content.pm.PackageInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ConfigurationInfo; +import android.content.pm.FeatureGroupInfo; +import android.content.pm.FeatureInfo; +import android.content.pm.InstrumentationInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ServiceInfo; +import android.content.pm.Signature; +import android.content.pm.SigningInfo; +import android.os.Parcel; +import android.os.Parcelable; + +public class PackageInfo implements Parcelable +{ + public ActivityInfo[] activities = null; + public ActivityInfo[] receivers = null; + public ApplicationInfo applicationInfo = null; + public ConfigurationInfo[] configPreferences = null; + public FeatureGroupInfo[] featureGroups = null; + public FeatureInfo[] reqFeatures = null; + public InstrumentationInfo[] instrumentation = null; + public PackageInfo(){} + public PermissionInfo[] permissions = null; + public ProviderInfo[] providers = null; + public ServiceInfo[] services = null; + public Signature[] signatures = null; + public SigningInfo signingInfo = null; + public String packageName = null; + public String sharedUserId = null; + public String toString(){ return null; } + public String versionName = null; + public String[] requestedPermissions = null; + public String[] splitNames = null; + public boolean isApex = false; + public int baseRevisionCode = 0; + public int describeContents(){ return 0; } + public int installLocation = 0; + public int sharedUserLabel = 0; + public int versionCode = 0; + public int[] gids = null; + public int[] requestedPermissionsFlags = null; + public int[] splitRevisionCodes = null; + public long firstInstallTime = 0; + public long getLongVersionCode(){ return 0; } + public long lastUpdateTime = 0; + public static Parcelable.Creator<PackageInfo> CREATOR = null; + public static int INSTALL_LOCATION_AUTO = 0; + public static int INSTALL_LOCATION_INTERNAL_ONLY = 0; + public static int INSTALL_LOCATION_PREFER_EXTERNAL = 0; + public static int REQUESTED_PERMISSION_GRANTED = 0; + public void setLongVersionCode(long p0){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageInstaller.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageInstaller.java new file mode 100644 index 00000000000..c836a4bfab9 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageInstaller.java @@ -0,0 +1,146 @@ +// Generated automatically from android.content.pm.PackageInstaller for testing purposes + +package android.content.pm; + +import android.content.Intent; +import android.content.IntentSender; +import android.content.pm.VersionedPackage; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; +import java.io.Closeable; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.Set; + +public class PackageInstaller +{ + abstract static public class SessionCallback + { + public SessionCallback(){} + public abstract void onActiveChanged(int p0, boolean p1); + public abstract void onBadgingChanged(int p0); + public abstract void onCreated(int p0); + public abstract void onFinished(int p0, boolean p1); + public abstract void onProgressChanged(int p0, float p1); + } + public List<PackageInstaller.SessionInfo> getAllSessions(){ return null; } + public List<PackageInstaller.SessionInfo> getMySessions(){ return null; } + public List<PackageInstaller.SessionInfo> getStagedSessions(){ return null; } + public PackageInstaller.Session openSession(int p0){ return null; } + public PackageInstaller.SessionInfo getActiveStagedSession(){ return null; } + public PackageInstaller.SessionInfo getSessionInfo(int p0){ return null; } + public int createSession(PackageInstaller.SessionParams p0){ return 0; } + public static String ACTION_SESSION_COMMITTED = null; + public static String ACTION_SESSION_DETAILS = null; + public static String ACTION_SESSION_UPDATED = null; + public static String EXTRA_OTHER_PACKAGE_NAME = null; + public static String EXTRA_PACKAGE_NAME = null; + public static String EXTRA_SESSION = null; + public static String EXTRA_SESSION_ID = null; + public static String EXTRA_STATUS = null; + public static String EXTRA_STATUS_MESSAGE = null; + public static String EXTRA_STORAGE_PATH = null; + public static int STATUS_FAILURE = 0; + public static int STATUS_FAILURE_ABORTED = 0; + public static int STATUS_FAILURE_BLOCKED = 0; + public static int STATUS_FAILURE_CONFLICT = 0; + public static int STATUS_FAILURE_INCOMPATIBLE = 0; + public static int STATUS_FAILURE_INVALID = 0; + public static int STATUS_FAILURE_STORAGE = 0; + public static int STATUS_PENDING_USER_ACTION = 0; + public static int STATUS_SUCCESS = 0; + public void abandonSession(int p0){} + public void installExistingPackage(String p0, int p1, IntentSender p2){} + public void registerSessionCallback(PackageInstaller.SessionCallback p0){} + public void registerSessionCallback(PackageInstaller.SessionCallback p0, Handler p1){} + public void uninstall(String p0, IntentSender p1){} + public void uninstall(VersionedPackage p0, IntentSender p1){} + public void unregisterSessionCallback(PackageInstaller.SessionCallback p0){} + public void updateSessionAppIcon(int p0, Bitmap p1){} + public void updateSessionAppLabel(int p0, CharSequence p1){} + static public class Session implements Closeable + { + public InputStream openRead(String p0){ return null; } + public OutputStream openWrite(String p0, long p1, long p2){ return null; } + public String[] getNames(){ return null; } + public boolean isMultiPackage(){ return false; } + public boolean isStaged(){ return false; } + public int getParentSessionId(){ return 0; } + public int[] getChildSessionIds(){ return null; } + public void abandon(){} + public void addChildSessionId(int p0){} + public void close(){} + public void commit(IntentSender p0){} + public void fsync(OutputStream p0){} + public void removeChildSessionId(int p0){} + public void removeSplit(String p0){} + public void setStagingProgress(float p0){} + public void transfer(String p0){} + } + static public class SessionInfo implements Parcelable + { + public Bitmap getAppIcon(){ return null; } + public CharSequence getAppLabel(){ return null; } + public Intent createDetailsIntent(){ return null; } + public String getAppPackageName(){ return null; } + public String getInstallerPackageName(){ return null; } + public String getStagedSessionErrorMessage(){ return null; } + public Uri getOriginatingUri(){ return null; } + public Uri getReferrerUri(){ return null; } + public UserHandle getUser(){ return null; } + public boolean isActive(){ return false; } + public boolean isCommitted(){ return false; } + public boolean isMultiPackage(){ return false; } + public boolean isSealed(){ return false; } + public boolean isStaged(){ return false; } + public boolean isStagedSessionApplied(){ return false; } + public boolean isStagedSessionFailed(){ return false; } + public boolean isStagedSessionReady(){ return false; } + public float getProgress(){ return 0; } + public int describeContents(){ return 0; } + public int getInstallLocation(){ return 0; } + public int getInstallReason(){ return 0; } + public int getMode(){ return 0; } + public int getOriginatingUid(){ return 0; } + public int getParentSessionId(){ return 0; } + public int getSessionId(){ return 0; } + public int getStagedSessionErrorCode(){ return 0; } + public int[] getChildSessionIds(){ return null; } + public long getSize(){ return 0; } + public long getUpdatedMillis(){ return 0; } + public static Parcelable.Creator<PackageInstaller.SessionInfo> CREATOR = null; + public static int INVALID_ID = 0; + public static int STAGED_SESSION_ACTIVATION_FAILED = 0; + public static int STAGED_SESSION_NO_ERROR = 0; + public static int STAGED_SESSION_UNKNOWN = 0; + public static int STAGED_SESSION_VERIFICATION_FAILED = 0; + public void writeToParcel(Parcel p0, int p1){} + } + static public class SessionParams implements Parcelable + { + protected SessionParams() {} + public SessionParams(int p0){} + public int describeContents(){ return 0; } + public static Parcelable.Creator<PackageInstaller.SessionParams> CREATOR = null; + public static Set<String> RESTRICTED_PERMISSIONS_ALL = null; + public static int MODE_FULL_INSTALL = 0; + public static int MODE_INHERIT_EXISTING = 0; + public void setAppIcon(Bitmap p0){} + public void setAppLabel(CharSequence p0){} + public void setAppPackageName(String p0){} + public void setInstallLocation(int p0){} + public void setInstallReason(int p0){} + public void setMultiPackage(){} + public void setOriginatingUid(int p0){} + public void setOriginatingUri(Uri p0){} + public void setReferrerUri(Uri p0){} + public void setSize(long p0){} + public void setWhitelistedRestrictedPermissions(Set<String> p0){} + public void writeToParcel(Parcel p0, int p1){} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageItemInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageItemInfo.java new file mode 100644 index 00000000000..1d35a31f52b --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageItemInfo.java @@ -0,0 +1,34 @@ +// Generated automatically from android.content.pm.PackageItemInfo for testing purposes + +package android.content.pm; + +import android.content.pm.PackageManager; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Parcel; +import android.util.Printer; + +public class PackageItemInfo +{ + protected PackageItemInfo(Parcel p0){} + protected void dumpBack(Printer p0, String p1){} + protected void dumpFront(Printer p0, String p1){} + public Bundle metaData = null; + public CharSequence loadLabel(PackageManager p0){ return null; } + public CharSequence nonLocalizedLabel = null; + public Drawable loadBanner(PackageManager p0){ return null; } + public Drawable loadIcon(PackageManager p0){ return null; } + public Drawable loadLogo(PackageManager p0){ return null; } + public Drawable loadUnbadgedIcon(PackageManager p0){ return null; } + public PackageItemInfo(){} + public PackageItemInfo(PackageItemInfo p0){} + public String name = null; + public String packageName = null; + public XmlResourceParser loadXmlMetaData(PackageManager p0, String p1){ return null; } + public int banner = 0; + public int icon = 0; + public int labelRes = 0; + public int logo = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageManager.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageManager.java new file mode 100644 index 00000000000..e3116359cbb --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PackageManager.java @@ -0,0 +1,314 @@ +// Generated automatically from android.content.pm.PackageManager for testing purposes + +package android.content.pm; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ChangedPackages; +import android.content.pm.FeatureInfo; +import android.content.pm.InstrumentationInfo; +import android.content.pm.ModuleInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.pm.SharedLibraryInfo; +import android.content.pm.VersionedPackage; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.UserHandle; +import android.util.AndroidException; +import java.util.List; +import java.util.Set; + +abstract public class PackageManager +{ + public Bundle getSuspendedPackageAppExtras(){ return null; } + public List<ModuleInfo> getInstalledModules(int p0){ return null; } + public ModuleInfo getModuleInfo(String p0, int p1){ return null; } + public PackageInfo getPackageArchiveInfo(String p0, int p1){ return null; } + public PackageManager(){} + public Set<String> getWhitelistedRestrictedPermissions(String p0, int p1){ return null; } + public abstract ActivityInfo getActivityInfo(ComponentName p0, int p1); + public abstract ActivityInfo getReceiverInfo(ComponentName p0, int p1); + public abstract ApplicationInfo getApplicationInfo(String p0, int p1); + public abstract ChangedPackages getChangedPackages(int p0); + public abstract CharSequence getApplicationLabel(ApplicationInfo p0); + public abstract CharSequence getText(String p0, int p1, ApplicationInfo p2); + public abstract CharSequence getUserBadgedLabel(CharSequence p0, UserHandle p1); + public abstract Drawable getActivityBanner(ComponentName p0); + public abstract Drawable getActivityBanner(Intent p0); + public abstract Drawable getActivityIcon(ComponentName p0); + public abstract Drawable getActivityIcon(Intent p0); + public abstract Drawable getActivityLogo(ComponentName p0); + public abstract Drawable getActivityLogo(Intent p0); + public abstract Drawable getApplicationBanner(ApplicationInfo p0); + public abstract Drawable getApplicationBanner(String p0); + public abstract Drawable getApplicationIcon(ApplicationInfo p0); + public abstract Drawable getApplicationIcon(String p0); + public abstract Drawable getApplicationLogo(ApplicationInfo p0); + public abstract Drawable getApplicationLogo(String p0); + public abstract Drawable getDefaultActivityIcon(); + public abstract Drawable getDrawable(String p0, int p1, ApplicationInfo p2); + public abstract Drawable getUserBadgedDrawableForDensity(Drawable p0, UserHandle p1, Rect p2, int p3); + public abstract Drawable getUserBadgedIcon(Drawable p0, UserHandle p1); + public abstract FeatureInfo[] getSystemAvailableFeatures(); + public abstract InstrumentationInfo getInstrumentationInfo(ComponentName p0, int p1); + public abstract Intent getLaunchIntentForPackage(String p0); + public abstract Intent getLeanbackLaunchIntentForPackage(String p0); + public abstract List<ApplicationInfo> getInstalledApplications(int p0); + public abstract List<InstrumentationInfo> queryInstrumentation(String p0, int p1); + public abstract List<PackageInfo> getInstalledPackages(int p0); + public abstract List<PackageInfo> getPackagesHoldingPermissions(String[] p0, int p1); + public abstract List<PackageInfo> getPreferredPackages(int p0); + public abstract List<PermissionGroupInfo> getAllPermissionGroups(int p0); + public abstract List<PermissionInfo> queryPermissionsByGroup(String p0, int p1); + public abstract List<ProviderInfo> queryContentProviders(String p0, int p1, int p2); + public abstract List<ResolveInfo> queryBroadcastReceivers(Intent p0, int p1); + public abstract List<ResolveInfo> queryIntentActivities(Intent p0, int p1); + public abstract List<ResolveInfo> queryIntentActivityOptions(ComponentName p0, Intent[] p1, Intent p2, int p3); + public abstract List<ResolveInfo> queryIntentContentProviders(Intent p0, int p1); + public abstract List<ResolveInfo> queryIntentServices(Intent p0, int p1); + public abstract List<SharedLibraryInfo> getSharedLibraries(int p0); + public abstract PackageInfo getPackageInfo(String p0, int p1); + public abstract PackageInfo getPackageInfo(VersionedPackage p0, int p1); + public abstract PackageInstaller getPackageInstaller(); + public abstract PermissionGroupInfo getPermissionGroupInfo(String p0, int p1); + public abstract PermissionInfo getPermissionInfo(String p0, int p1); + public abstract ProviderInfo getProviderInfo(ComponentName p0, int p1); + public abstract ProviderInfo resolveContentProvider(String p0, int p1); + public abstract ResolveInfo resolveActivity(Intent p0, int p1); + public abstract ResolveInfo resolveService(Intent p0, int p1); + public abstract Resources getResourcesForActivity(ComponentName p0); + public abstract Resources getResourcesForApplication(ApplicationInfo p0); + public abstract Resources getResourcesForApplication(String p0); + public abstract ServiceInfo getServiceInfo(ComponentName p0, int p1); + public abstract String getInstallerPackageName(String p0); + public abstract String getNameForUid(int p0); + public abstract String[] canonicalToCurrentPackageNames(String[] p0); + public abstract String[] currentToCanonicalPackageNames(String[] p0); + public abstract String[] getPackagesForUid(int p0); + public abstract String[] getSystemSharedLibraryNames(); + public abstract XmlResourceParser getXml(String p0, int p1, ApplicationInfo p2); + public abstract boolean addPermission(PermissionInfo p0); + public abstract boolean addPermissionAsync(PermissionInfo p0); + public abstract boolean canRequestPackageInstalls(); + public abstract boolean hasSystemFeature(String p0); + public abstract boolean hasSystemFeature(String p0, int p1); + public abstract boolean isInstantApp(); + public abstract boolean isInstantApp(String p0); + public abstract boolean isPermissionRevokedByPolicy(String p0, String p1); + public abstract boolean isSafeMode(); + public abstract byte[] getInstantAppCookie(); + public abstract int checkPermission(String p0, String p1); + public abstract int checkSignatures(String p0, String p1); + public abstract int checkSignatures(int p0, int p1); + public abstract int getApplicationEnabledSetting(String p0); + public abstract int getComponentEnabledSetting(ComponentName p0); + public abstract int getInstantAppCookieMaxBytes(); + public abstract int getPackageUid(String p0, int p1); + public abstract int getPreferredActivities(List<IntentFilter> p0, List<ComponentName> p1, String p2); + public abstract int[] getPackageGids(String p0); + public abstract int[] getPackageGids(String p0, int p1); + public abstract void addPackageToPreferred(String p0); + public abstract void addPreferredActivity(IntentFilter p0, int p1, ComponentName[] p2, ComponentName p3); + public abstract void clearInstantAppCookie(); + public abstract void clearPackagePreferredActivities(String p0); + public abstract void extendVerificationTimeout(int p0, int p1, long p2); + public abstract void removePackageFromPreferred(String p0); + public abstract void removePermission(String p0); + public abstract void setApplicationCategoryHint(String p0, int p1); + public abstract void setApplicationEnabledSetting(String p0, int p1, int p2); + public abstract void setComponentEnabledSetting(ComponentName p0, int p1, int p2); + public abstract void setInstallerPackageName(String p0, String p1); + public abstract void updateInstantAppCookie(byte[] p0); + public abstract void verifyPendingInstall(int p0, int p1); + public boolean addWhitelistedRestrictedPermission(String p0, String p1, int p2){ return false; } + public boolean getSyntheticAppDetailsActivityEnabled(String p0){ return false; } + public boolean hasSigningCertificate(String p0, byte[] p1, int p2){ return false; } + public boolean hasSigningCertificate(int p0, byte[] p1, int p2){ return false; } + public boolean isDeviceUpgrading(){ return false; } + public boolean isPackageSuspended(){ return false; } + public boolean isPackageSuspended(String p0){ return false; } + public boolean removeWhitelistedRestrictedPermission(String p0, String p1, int p2){ return false; } + public static String EXTRA_VERIFICATION_ID = null; + public static String EXTRA_VERIFICATION_RESULT = null; + public static String FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS = null; + public static String FEATURE_APP_WIDGETS = null; + public static String FEATURE_AUDIO_LOW_LATENCY = null; + public static String FEATURE_AUDIO_OUTPUT = null; + public static String FEATURE_AUDIO_PRO = null; + public static String FEATURE_AUTOFILL = null; + public static String FEATURE_AUTOMOTIVE = null; + public static String FEATURE_BACKUP = null; + public static String FEATURE_BLUETOOTH = null; + public static String FEATURE_BLUETOOTH_LE = null; + public static String FEATURE_CAMERA = null; + public static String FEATURE_CAMERA_ANY = null; + public static String FEATURE_CAMERA_AR = null; + public static String FEATURE_CAMERA_AUTOFOCUS = null; + public static String FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING = null; + public static String FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR = null; + public static String FEATURE_CAMERA_CAPABILITY_RAW = null; + public static String FEATURE_CAMERA_EXTERNAL = null; + public static String FEATURE_CAMERA_FLASH = null; + public static String FEATURE_CAMERA_FRONT = null; + public static String FEATURE_CAMERA_LEVEL_FULL = null; + public static String FEATURE_CANT_SAVE_STATE = null; + public static String FEATURE_COMPANION_DEVICE_SETUP = null; + public static String FEATURE_CONNECTION_SERVICE = null; + public static String FEATURE_CONSUMER_IR = null; + public static String FEATURE_DEVICE_ADMIN = null; + public static String FEATURE_EMBEDDED = null; + public static String FEATURE_ETHERNET = null; + public static String FEATURE_FACE = null; + public static String FEATURE_FAKETOUCH = null; + public static String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = null; + public static String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = null; + public static String FEATURE_FINGERPRINT = null; + public static String FEATURE_FREEFORM_WINDOW_MANAGEMENT = null; + public static String FEATURE_GAMEPAD = null; + public static String FEATURE_HIFI_SENSORS = null; + public static String FEATURE_HOME_SCREEN = null; + public static String FEATURE_INPUT_METHODS = null; + public static String FEATURE_IPSEC_TUNNELS = null; + public static String FEATURE_IRIS = null; + public static String FEATURE_LEANBACK = null; + public static String FEATURE_LEANBACK_ONLY = null; + public static String FEATURE_LIVE_TV = null; + public static String FEATURE_LIVE_WALLPAPER = null; + public static String FEATURE_LOCATION = null; + public static String FEATURE_LOCATION_GPS = null; + public static String FEATURE_LOCATION_NETWORK = null; + public static String FEATURE_MANAGED_USERS = null; + public static String FEATURE_MICROPHONE = null; + public static String FEATURE_MIDI = null; + public static String FEATURE_NFC = null; + public static String FEATURE_NFC_BEAM = null; + public static String FEATURE_NFC_HOST_CARD_EMULATION = null; + public static String FEATURE_NFC_HOST_CARD_EMULATION_NFCF = null; + public static String FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE = null; + public static String FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC = null; + public static String FEATURE_OPENGLES_EXTENSION_PACK = null; + public static String FEATURE_PC = null; + public static String FEATURE_PICTURE_IN_PICTURE = null; + public static String FEATURE_PRINTING = null; + public static String FEATURE_RAM_LOW = null; + public static String FEATURE_RAM_NORMAL = null; + public static String FEATURE_SCREEN_LANDSCAPE = null; + public static String FEATURE_SCREEN_PORTRAIT = null; + public static String FEATURE_SECURELY_REMOVES_USERS = null; + public static String FEATURE_SECURE_LOCK_SCREEN = null; + public static String FEATURE_SENSOR_ACCELEROMETER = null; + public static String FEATURE_SENSOR_AMBIENT_TEMPERATURE = null; + public static String FEATURE_SENSOR_BAROMETER = null; + public static String FEATURE_SENSOR_COMPASS = null; + public static String FEATURE_SENSOR_GYROSCOPE = null; + public static String FEATURE_SENSOR_HEART_RATE = null; + public static String FEATURE_SENSOR_HEART_RATE_ECG = null; + public static String FEATURE_SENSOR_LIGHT = null; + public static String FEATURE_SENSOR_PROXIMITY = null; + public static String FEATURE_SENSOR_RELATIVE_HUMIDITY = null; + public static String FEATURE_SENSOR_STEP_COUNTER = null; + public static String FEATURE_SENSOR_STEP_DETECTOR = null; + public static String FEATURE_SIP = null; + public static String FEATURE_SIP_VOIP = null; + public static String FEATURE_STRONGBOX_KEYSTORE = null; + public static String FEATURE_TELEPHONY = null; + public static String FEATURE_TELEPHONY_CDMA = null; + public static String FEATURE_TELEPHONY_EUICC = null; + public static String FEATURE_TELEPHONY_GSM = null; + public static String FEATURE_TELEPHONY_IMS = null; + public static String FEATURE_TELEPHONY_MBMS = null; + public static String FEATURE_TELEVISION = null; + public static String FEATURE_TOUCHSCREEN = null; + public static String FEATURE_TOUCHSCREEN_MULTITOUCH = null; + public static String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = null; + public static String FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND = null; + public static String FEATURE_USB_ACCESSORY = null; + public static String FEATURE_USB_HOST = null; + public static String FEATURE_VERIFIED_BOOT = null; + public static String FEATURE_VR_HEADTRACKING = null; + public static String FEATURE_VR_MODE = null; + public static String FEATURE_VR_MODE_HIGH_PERFORMANCE = null; + public static String FEATURE_VULKAN_HARDWARE_COMPUTE = null; + public static String FEATURE_VULKAN_HARDWARE_LEVEL = null; + public static String FEATURE_VULKAN_HARDWARE_VERSION = null; + public static String FEATURE_WATCH = null; + public static String FEATURE_WEBVIEW = null; + public static String FEATURE_WIFI = null; + public static String FEATURE_WIFI_AWARE = null; + public static String FEATURE_WIFI_DIRECT = null; + public static String FEATURE_WIFI_PASSPOINT = null; + public static String FEATURE_WIFI_RTT = null; + public static int CERT_INPUT_RAW_X509 = 0; + public static int CERT_INPUT_SHA256 = 0; + public static int COMPONENT_ENABLED_STATE_DEFAULT = 0; + public static int COMPONENT_ENABLED_STATE_DISABLED = 0; + public static int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 0; + public static int COMPONENT_ENABLED_STATE_DISABLED_USER = 0; + public static int COMPONENT_ENABLED_STATE_ENABLED = 0; + public static int DONT_KILL_APP = 0; + public static int FLAG_PERMISSION_WHITELIST_INSTALLER = 0; + public static int FLAG_PERMISSION_WHITELIST_SYSTEM = 0; + public static int FLAG_PERMISSION_WHITELIST_UPGRADE = 0; + public static int GET_ACTIVITIES = 0; + public static int GET_CONFIGURATIONS = 0; + public static int GET_DISABLED_COMPONENTS = 0; + public static int GET_DISABLED_UNTIL_USED_COMPONENTS = 0; + public static int GET_GIDS = 0; + public static int GET_INSTRUMENTATION = 0; + public static int GET_INTENT_FILTERS = 0; + public static int GET_META_DATA = 0; + public static int GET_PERMISSIONS = 0; + public static int GET_PROVIDERS = 0; + public static int GET_RECEIVERS = 0; + public static int GET_RESOLVED_FILTER = 0; + public static int GET_SERVICES = 0; + public static int GET_SHARED_LIBRARY_FILES = 0; + public static int GET_SIGNATURES = 0; + public static int GET_SIGNING_CERTIFICATES = 0; + public static int GET_UNINSTALLED_PACKAGES = 0; + public static int GET_URI_PERMISSION_PATTERNS = 0; + public static int INSTALL_REASON_DEVICE_RESTORE = 0; + public static int INSTALL_REASON_DEVICE_SETUP = 0; + public static int INSTALL_REASON_POLICY = 0; + public static int INSTALL_REASON_UNKNOWN = 0; + public static int INSTALL_REASON_USER = 0; + public static int MATCH_ALL = 0; + public static int MATCH_APEX = 0; + public static int MATCH_DEFAULT_ONLY = 0; + public static int MATCH_DIRECT_BOOT_AUTO = 0; + public static int MATCH_DIRECT_BOOT_AWARE = 0; + public static int MATCH_DIRECT_BOOT_UNAWARE = 0; + public static int MATCH_DISABLED_COMPONENTS = 0; + public static int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 0; + public static int MATCH_SYSTEM_ONLY = 0; + public static int MATCH_UNINSTALLED_PACKAGES = 0; + public static int PERMISSION_DENIED = 0; + public static int PERMISSION_GRANTED = 0; + public static int SIGNATURE_FIRST_NOT_SIGNED = 0; + public static int SIGNATURE_MATCH = 0; + public static int SIGNATURE_NEITHER_SIGNED = 0; + public static int SIGNATURE_NO_MATCH = 0; + public static int SIGNATURE_SECOND_NOT_SIGNED = 0; + public static int SIGNATURE_UNKNOWN_PACKAGE = 0; + public static int VERIFICATION_ALLOW = 0; + public static int VERIFICATION_REJECT = 0; + public static int VERSION_CODE_HIGHEST = 0; + public static long MAXIMUM_VERIFICATION_TIMEOUT = 0; + static public class NameNotFoundException extends AndroidException + { + public NameNotFoundException(){} + public NameNotFoundException(String p0){} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PermissionGroupInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PermissionGroupInfo.java new file mode 100644 index 00000000000..a74934de52f --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PermissionGroupInfo.java @@ -0,0 +1,24 @@ +// Generated automatically from android.content.pm.PermissionGroupInfo for testing purposes + +package android.content.pm; + +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.os.Parcel; +import android.os.Parcelable; + +public class PermissionGroupInfo extends PackageItemInfo implements Parcelable +{ + public CharSequence loadDescription(PackageManager p0){ return null; } + public CharSequence nonLocalizedDescription = null; + public PermissionGroupInfo(){} + public PermissionGroupInfo(PermissionGroupInfo p0){} + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int descriptionRes = 0; + public int flags = 0; + public int priority = 0; + public static Parcelable.Creator<PermissionGroupInfo> CREATOR = null; + public static int FLAG_PERSONAL_INFO = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PermissionInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PermissionInfo.java new file mode 100644 index 00000000000..2c95bb9af7a --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/PermissionInfo.java @@ -0,0 +1,48 @@ +// Generated automatically from android.content.pm.PermissionInfo for testing purposes + +package android.content.pm; + +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.os.Parcel; +import android.os.Parcelable; + +public class PermissionInfo extends PackageItemInfo implements Parcelable +{ + public CharSequence loadDescription(PackageManager p0){ return null; } + public CharSequence nonLocalizedDescription = null; + public PermissionInfo(){} + public PermissionInfo(PermissionInfo p0){} + public String group = null; + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int descriptionRes = 0; + public int flags = 0; + public int getProtection(){ return 0; } + public int getProtectionFlags(){ return 0; } + public int protectionLevel = 0; + public static Parcelable.Creator<PermissionInfo> CREATOR = null; + public static int FLAG_COSTS_MONEY = 0; + public static int FLAG_HARD_RESTRICTED = 0; + public static int FLAG_IMMUTABLY_RESTRICTED = 0; + public static int FLAG_INSTALLED = 0; + public static int FLAG_SOFT_RESTRICTED = 0; + public static int PROTECTION_DANGEROUS = 0; + public static int PROTECTION_FLAG_APPOP = 0; + public static int PROTECTION_FLAG_DEVELOPMENT = 0; + public static int PROTECTION_FLAG_INSTALLER = 0; + public static int PROTECTION_FLAG_INSTANT = 0; + public static int PROTECTION_FLAG_PRE23 = 0; + public static int PROTECTION_FLAG_PREINSTALLED = 0; + public static int PROTECTION_FLAG_PRIVILEGED = 0; + public static int PROTECTION_FLAG_RUNTIME_ONLY = 0; + public static int PROTECTION_FLAG_SETUP = 0; + public static int PROTECTION_FLAG_SYSTEM = 0; + public static int PROTECTION_FLAG_VERIFIER = 0; + public static int PROTECTION_MASK_BASE = 0; + public static int PROTECTION_MASK_FLAGS = 0; + public static int PROTECTION_NORMAL = 0; + public static int PROTECTION_SIGNATURE = 0; + public static int PROTECTION_SIGNATURE_OR_SYSTEM = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ProviderInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ProviderInfo.java new file mode 100644 index 00000000000..93b694cae59 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ProviderInfo.java @@ -0,0 +1,33 @@ +// Generated automatically from android.content.pm.ProviderInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ComponentInfo; +import android.content.pm.PathPermission; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; +import android.util.Printer; + +public class ProviderInfo extends ComponentInfo implements Parcelable +{ + public PathPermission[] pathPermissions = null; + public PatternMatcher[] uriPermissionPatterns = null; + public ProviderInfo(){} + public ProviderInfo(ProviderInfo p0){} + public String authority = null; + public String readPermission = null; + public String toString(){ return null; } + public String writePermission = null; + public boolean forceUriPermissions = false; + public boolean grantUriPermissions = false; + public boolean isSyncable = false; + public boolean multiprocess = false; + public int describeContents(){ return 0; } + public int flags = 0; + public int initOrder = 0; + public static Parcelable.Creator<ProviderInfo> CREATOR = null; + public static int FLAG_SINGLE_USER = 0; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ResolveInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ResolveInfo.java new file mode 100644 index 00000000000..a06bcbdccc6 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ResolveInfo.java @@ -0,0 +1,41 @@ +// Generated automatically from android.content.pm.ResolveInfo for testing purposes + +package android.content.pm; + +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; +import android.content.pm.ServiceInfo; +import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +public class ResolveInfo implements Parcelable +{ + public ActivityInfo activityInfo = null; + public CharSequence loadLabel(PackageManager p0){ return null; } + public CharSequence nonLocalizedLabel = null; + public Drawable loadIcon(PackageManager p0){ return null; } + public IntentFilter filter = null; + public ProviderInfo providerInfo = null; + public ResolveInfo(){} + public ResolveInfo(ResolveInfo p0){} + public ServiceInfo serviceInfo = null; + public String resolvePackageName = null; + public String toString(){ return null; } + public boolean isDefault = false; + public boolean isInstantAppAvailable = false; + public final int getIconResource(){ return 0; } + public int describeContents(){ return 0; } + public int icon = 0; + public int labelRes = 0; + public int match = 0; + public int preferredOrder = 0; + public int priority = 0; + public int specificIndex = 0; + public static Parcelable.Creator<ResolveInfo> CREATOR = null; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ServiceInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ServiceInfo.java new file mode 100644 index 00000000000..e7fdb2c49f1 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/ServiceInfo.java @@ -0,0 +1,35 @@ +// Generated automatically from android.content.pm.ServiceInfo for testing purposes + +package android.content.pm; + +import android.content.pm.ComponentInfo; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +public class ServiceInfo extends ComponentInfo implements Parcelable +{ + public ServiceInfo(){} + public ServiceInfo(ServiceInfo p0){} + public String permission = null; + public String toString(){ return null; } + public int describeContents(){ return 0; } + public int flags = 0; + public int getForegroundServiceType(){ return 0; } + public static Parcelable.Creator<ServiceInfo> CREATOR = null; + public static int FLAG_EXTERNAL_SERVICE = 0; + public static int FLAG_ISOLATED_PROCESS = 0; + public static int FLAG_SINGLE_USER = 0; + public static int FLAG_STOP_WITH_TASK = 0; + public static int FLAG_USE_APP_ZYGOTE = 0; + public static int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 0; + public static int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 0; + public static int FOREGROUND_SERVICE_TYPE_LOCATION = 0; + public static int FOREGROUND_SERVICE_TYPE_MANIFEST = 0; + public static int FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK = 0; + public static int FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION = 0; + public static int FOREGROUND_SERVICE_TYPE_NONE = 0; + public static int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 0; + public void dump(Printer p0, String p1){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/SharedLibraryInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/SharedLibraryInfo.java new file mode 100644 index 00000000000..33c1173420d --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/SharedLibraryInfo.java @@ -0,0 +1,27 @@ +// Generated automatically from android.content.pm.SharedLibraryInfo for testing purposes + +package android.content.pm; + +import android.content.pm.VersionedPackage; +import android.os.Parcel; +import android.os.Parcelable; +import java.util.List; + +public class SharedLibraryInfo implements Parcelable +{ + protected SharedLibraryInfo() {} + public List<VersionedPackage> getDependentPackages(){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public VersionedPackage getDeclaringPackage(){ return null; } + public int describeContents(){ return 0; } + public int getType(){ return 0; } + public int getVersion(){ return 0; } + public long getLongVersion(){ return 0; } + public static Parcelable.Creator<SharedLibraryInfo> CREATOR = null; + public static int TYPE_BUILTIN = 0; + public static int TYPE_DYNAMIC = 0; + public static int TYPE_STATIC = 0; + public static int VERSION_UNDEFINED = 0; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/Signature.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/Signature.java new file mode 100644 index 00000000000..c7d3a4dd055 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/Signature.java @@ -0,0 +1,3 @@ +package android.content.pm; + +interface Signature { } \ No newline at end of file diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/SigningInfo.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/SigningInfo.java new file mode 100644 index 00000000000..56aadea159a --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/SigningInfo.java @@ -0,0 +1,20 @@ +// Generated automatically from android.content.pm.SigningInfo for testing purposes + +package android.content.pm; + +import android.content.pm.Signature; +import android.os.Parcel; +import android.os.Parcelable; + +public class SigningInfo implements Parcelable +{ + public Signature[] getApkContentsSigners(){ return null; } + public Signature[] getSigningCertificateHistory(){ return null; } + public SigningInfo(){} + public SigningInfo(SigningInfo p0){} + public boolean hasMultipleSigners(){ return false; } + public boolean hasPastSigningCertificates(){ return false; } + public int describeContents(){ return 0; } + public static Parcelable.Creator<SigningInfo> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/pm/VersionedPackage.java b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/VersionedPackage.java new file mode 100644 index 00000000000..d20014d0fcc --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/pm/VersionedPackage.java @@ -0,0 +1,20 @@ +// Generated automatically from android.content.pm.VersionedPackage for testing purposes + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +public class VersionedPackage implements Parcelable +{ + protected VersionedPackage() {} + public String getPackageName(){ return null; } + public String toString(){ return null; } + public VersionedPackage(String p0, int p1){} + public VersionedPackage(String p0, long p1){} + public int describeContents(){ return 0; } + public int getVersionCode(){ return 0; } + public long getLongVersionCode(){ return 0; } + public static Parcelable.Creator<VersionedPackage> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/res/AssetManager.java b/java/ql/test/stubs/google-android-9.0.0/android/content/res/AssetManager.java new file mode 100644 index 00000000000..37926aa5c61 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/res/AssetManager.java @@ -0,0 +1,26 @@ +// Generated automatically from android.content.res.AssetManager for testing purposes + +package android.content.res; + +import android.content.res.AssetFileDescriptor; +import android.content.res.XmlResourceParser; +import java.io.InputStream; + +public class AssetManager implements AutoCloseable +{ + protected void finalize(){} + public AssetFileDescriptor openFd(String p0){ return null; } + public AssetFileDescriptor openNonAssetFd(String p0){ return null; } + public AssetFileDescriptor openNonAssetFd(int p0, String p1){ return null; } + public InputStream open(String p0){ return null; } + public InputStream open(String p0, int p1){ return null; } + public String[] getLocales(){ return null; } + public String[] list(String p0){ return null; } + public XmlResourceParser openXmlResourceParser(String p0){ return null; } + public XmlResourceParser openXmlResourceParser(int p0, String p1){ return null; } + public static int ACCESS_BUFFER = 0; + public static int ACCESS_RANDOM = 0; + public static int ACCESS_STREAMING = 0; + public static int ACCESS_UNKNOWN = 0; + public void close(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/res/ColorStateList.java b/java/ql/test/stubs/google-android-9.0.0/android/content/res/ColorStateList.java new file mode 100644 index 00000000000..cc6a1851767 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/res/ColorStateList.java @@ -0,0 +1,27 @@ +// Generated automatically from android.content.res.ColorStateList for testing purposes + +package android.content.res; + +import android.content.res.Resources; +import android.os.Parcel; +import android.os.Parcelable; +import org.xmlpull.v1.XmlPullParser; + +public class ColorStateList implements Parcelable +{ + protected ColorStateList() {} + public ColorStateList withAlpha(int p0){ return null; } + public ColorStateList(int[][] p0, int[] p1){} + public String toString(){ return null; } + public boolean isOpaque(){ return false; } + public boolean isStateful(){ return false; } + public int describeContents(){ return 0; } + public int getChangingConfigurations(){ return 0; } + public int getColorForState(int[] p0, int p1){ return 0; } + public int getDefaultColor(){ return 0; } + public static ColorStateList createFromXml(Resources p0, XmlPullParser p1){ return null; } + public static ColorStateList createFromXml(Resources p0, XmlPullParser p1, Resources.Theme p2){ return null; } + public static ColorStateList valueOf(int p0){ return null; } + public static Parcelable.Creator<ColorStateList> CREATOR = null; + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/res/Configuration.java b/java/ql/test/stubs/google-android-9.0.0/android/content/res/Configuration.java new file mode 100644 index 00000000000..2215536a74e --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/res/Configuration.java @@ -0,0 +1,129 @@ +// Generated automatically from android.content.res.Configuration for testing purposes + +package android.content.res; + +import android.os.LocaleList; +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Locale; + +public class Configuration implements Comparable<Configuration>, Parcelable +{ + public Configuration(){} + public Configuration(Configuration p0){} + public Locale locale = null; + public LocaleList getLocales(){ return null; } + public String toString(){ return null; } + public boolean equals(Configuration p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isLayoutSizeAtLeast(int p0){ return false; } + public boolean isScreenHdr(){ return false; } + public boolean isScreenRound(){ return false; } + public boolean isScreenWideColorGamut(){ return false; } + public float fontScale = 0; + public int colorMode = 0; + public int compareTo(Configuration p0){ return 0; } + public int densityDpi = 0; + public int describeContents(){ return 0; } + public int diff(Configuration p0){ return 0; } + public int getLayoutDirection(){ return 0; } + public int hardKeyboardHidden = 0; + public int hashCode(){ return 0; } + public int keyboard = 0; + public int keyboardHidden = 0; + public int mcc = 0; + public int mnc = 0; + public int navigation = 0; + public int navigationHidden = 0; + public int orientation = 0; + public int screenHeightDp = 0; + public int screenLayout = 0; + public int screenWidthDp = 0; + public int smallestScreenWidthDp = 0; + public int touchscreen = 0; + public int uiMode = 0; + public int updateFrom(Configuration p0){ return 0; } + public static Parcelable.Creator<Configuration> CREATOR = null; + public static boolean needNewResources(int p0, int p1){ return false; } + public static int COLOR_MODE_HDR_MASK = 0; + public static int COLOR_MODE_HDR_NO = 0; + public static int COLOR_MODE_HDR_SHIFT = 0; + public static int COLOR_MODE_HDR_UNDEFINED = 0; + public static int COLOR_MODE_HDR_YES = 0; + public static int COLOR_MODE_UNDEFINED = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0; + public static int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0; + public static int DENSITY_DPI_UNDEFINED = 0; + public static int HARDKEYBOARDHIDDEN_NO = 0; + public static int HARDKEYBOARDHIDDEN_UNDEFINED = 0; + public static int HARDKEYBOARDHIDDEN_YES = 0; + public static int KEYBOARDHIDDEN_NO = 0; + public static int KEYBOARDHIDDEN_UNDEFINED = 0; + public static int KEYBOARDHIDDEN_YES = 0; + public static int KEYBOARD_12KEY = 0; + public static int KEYBOARD_NOKEYS = 0; + public static int KEYBOARD_QWERTY = 0; + public static int KEYBOARD_UNDEFINED = 0; + public static int MNC_ZERO = 0; + public static int NAVIGATIONHIDDEN_NO = 0; + public static int NAVIGATIONHIDDEN_UNDEFINED = 0; + public static int NAVIGATIONHIDDEN_YES = 0; + public static int NAVIGATION_DPAD = 0; + public static int NAVIGATION_NONAV = 0; + public static int NAVIGATION_TRACKBALL = 0; + public static int NAVIGATION_UNDEFINED = 0; + public static int NAVIGATION_WHEEL = 0; + public static int ORIENTATION_LANDSCAPE = 0; + public static int ORIENTATION_PORTRAIT = 0; + public static int ORIENTATION_SQUARE = 0; + public static int ORIENTATION_UNDEFINED = 0; + public static int SCREENLAYOUT_LAYOUTDIR_LTR = 0; + public static int SCREENLAYOUT_LAYOUTDIR_MASK = 0; + public static int SCREENLAYOUT_LAYOUTDIR_RTL = 0; + public static int SCREENLAYOUT_LAYOUTDIR_SHIFT = 0; + public static int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0; + public static int SCREENLAYOUT_LONG_MASK = 0; + public static int SCREENLAYOUT_LONG_NO = 0; + public static int SCREENLAYOUT_LONG_UNDEFINED = 0; + public static int SCREENLAYOUT_LONG_YES = 0; + public static int SCREENLAYOUT_ROUND_MASK = 0; + public static int SCREENLAYOUT_ROUND_NO = 0; + public static int SCREENLAYOUT_ROUND_UNDEFINED = 0; + public static int SCREENLAYOUT_ROUND_YES = 0; + public static int SCREENLAYOUT_SIZE_LARGE = 0; + public static int SCREENLAYOUT_SIZE_MASK = 0; + public static int SCREENLAYOUT_SIZE_NORMAL = 0; + public static int SCREENLAYOUT_SIZE_SMALL = 0; + public static int SCREENLAYOUT_SIZE_UNDEFINED = 0; + public static int SCREENLAYOUT_SIZE_XLARGE = 0; + public static int SCREENLAYOUT_UNDEFINED = 0; + public static int SCREEN_HEIGHT_DP_UNDEFINED = 0; + public static int SCREEN_WIDTH_DP_UNDEFINED = 0; + public static int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0; + public static int TOUCHSCREEN_FINGER = 0; + public static int TOUCHSCREEN_NOTOUCH = 0; + public static int TOUCHSCREEN_STYLUS = 0; + public static int TOUCHSCREEN_UNDEFINED = 0; + public static int UI_MODE_NIGHT_MASK = 0; + public static int UI_MODE_NIGHT_NO = 0; + public static int UI_MODE_NIGHT_UNDEFINED = 0; + public static int UI_MODE_NIGHT_YES = 0; + public static int UI_MODE_TYPE_APPLIANCE = 0; + public static int UI_MODE_TYPE_CAR = 0; + public static int UI_MODE_TYPE_DESK = 0; + public static int UI_MODE_TYPE_MASK = 0; + public static int UI_MODE_TYPE_NORMAL = 0; + public static int UI_MODE_TYPE_TELEVISION = 0; + public static int UI_MODE_TYPE_UNDEFINED = 0; + public static int UI_MODE_TYPE_VR_HEADSET = 0; + public static int UI_MODE_TYPE_WATCH = 0; + public void readFromParcel(Parcel p0){} + public void setLayoutDirection(Locale p0){} + public void setLocale(Locale p0){} + public void setLocales(LocaleList p0){} + public void setTo(Configuration p0){} + public void setToDefaults(){} + public void writeToParcel(Parcel p0, int p1){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/res/Resources.java b/java/ql/test/stubs/google-android-9.0.0/android/content/res/Resources.java new file mode 100644 index 00000000000..96847810672 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/res/Resources.java @@ -0,0 +1,101 @@ +// Generated automatically from android.content.res.Resources for testing purposes + +package android.content.res; + +import android.content.res.AssetFileDescriptor; +import android.content.res.AssetManager; +import android.content.res.ColorStateList; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.Movie; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import java.io.InputStream; + +public class Resources +{ + protected Resources() {} + public AssetFileDescriptor openRawResourceFd(int p0){ return null; } + public CharSequence getQuantityText(int p0, int p1){ return null; } + public CharSequence getText(int p0){ return null; } + public CharSequence getText(int p0, CharSequence p1){ return null; } + public CharSequence[] getTextArray(int p0){ return null; } + public ColorStateList getColorStateList(int p0){ return null; } + public ColorStateList getColorStateList(int p0, Resources.Theme p1){ return null; } + public Configuration getConfiguration(){ return null; } + public DisplayMetrics getDisplayMetrics(){ return null; } + public Drawable getDrawable(int p0){ return null; } + public Drawable getDrawable(int p0, Resources.Theme p1){ return null; } + public Drawable getDrawableForDensity(int p0, int p1){ return null; } + public Drawable getDrawableForDensity(int p0, int p1, Resources.Theme p2){ return null; } + public InputStream openRawResource(int p0){ return null; } + public InputStream openRawResource(int p0, TypedValue p1){ return null; } + public Movie getMovie(int p0){ return null; } + public Resources(AssetManager p0, DisplayMetrics p1, Configuration p2){} + public String getQuantityString(int p0, int p1){ return null; } + public String getQuantityString(int p0, int p1, Object... p2){ return null; } + public String getResourceEntryName(int p0){ return null; } + public String getResourceName(int p0){ return null; } + public String getResourcePackageName(int p0){ return null; } + public String getResourceTypeName(int p0){ return null; } + public String getString(int p0){ return null; } + public String getString(int p0, Object... p1){ return null; } + public String[] getStringArray(int p0){ return null; } + public TypedArray obtainAttributes(AttributeSet p0, int[] p1){ return null; } + public TypedArray obtainTypedArray(int p0){ return null; } + public Typeface getFont(int p0){ return null; } + public XmlResourceParser getAnimation(int p0){ return null; } + public XmlResourceParser getLayout(int p0){ return null; } + public XmlResourceParser getXml(int p0){ return null; } + public boolean getBoolean(int p0){ return false; } + public class Theme + { + public Drawable getDrawable(int p0){ return null; } + public Resources getResources(){ return null; } + public TypedArray obtainStyledAttributes(AttributeSet p0, int[] p1, int p2, int p3){ return null; } + public TypedArray obtainStyledAttributes(int p0, int[] p1){ return null; } + public TypedArray obtainStyledAttributes(int[] p0){ return null; } + public boolean resolveAttribute(int p0, TypedValue p1, boolean p2){ return false; } + public int getChangingConfigurations(){ return 0; } + public int getExplicitStyle(AttributeSet p0){ return 0; } + public int[] getAttributeResolutionStack(int p0, int p1, int p2){ return null; } + public void applyStyle(int p0, boolean p1){} + public void dump(int p0, String p1, String p2){} + public void rebase(){} + public void setTo(Resources.Theme p0){} + } + public final AssetManager getAssets(){ return null; } + public final Resources.Theme newTheme(){ return null; } + public final void finishPreloading(){} + public final void flushLayoutCache(){} + public float getDimension(int p0){ return 0; } + public float getFloat(int p0){ return 0; } + public float getFraction(int p0, int p1, int p2){ return 0; } + public int getColor(int p0){ return 0; } + public int getColor(int p0, Resources.Theme p1){ return 0; } + public int getDimensionPixelOffset(int p0){ return 0; } + public int getDimensionPixelSize(int p0){ return 0; } + public int getIdentifier(String p0, String p1, String p2){ return 0; } + public int getInteger(int p0){ return 0; } + public int[] getIntArray(int p0){ return null; } + public static Resources getSystem(){ return null; } + public static int ID_NULL = 0; + public static int getAttributeSetSourceResId(AttributeSet p0){ return 0; } + public void getValue(String p0, TypedValue p1, boolean p2){} + public void getValue(int p0, TypedValue p1, boolean p2){} + public void getValueForDensity(int p0, int p1, TypedValue p2, boolean p3){} + public void parseBundleExtra(String p0, AttributeSet p1, Bundle p2){} + public void parseBundleExtras(XmlResourceParser p0, Bundle p1){} + public void updateConfiguration(Configuration p0, DisplayMetrics p1){} + static public class NotFoundException extends RuntimeException + { + public NotFoundException(){} + public NotFoundException(String p0){} + public NotFoundException(String p0, Exception p1){} + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/res/TypedArray.java b/java/ql/test/stubs/google-android-9.0.0/android/content/res/TypedArray.java new file mode 100644 index 00000000000..3578fd23292 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/res/TypedArray.java @@ -0,0 +1,47 @@ +// Generated automatically from android.content.res.TypedArray for testing purposes + +package android.content.res; + +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.util.TypedValue; + +public class TypedArray +{ + protected TypedArray() {} + public CharSequence getText(int p0){ return null; } + public CharSequence[] getTextArray(int p0){ return null; } + public ColorStateList getColorStateList(int p0){ return null; } + public Drawable getDrawable(int p0){ return null; } + public Resources getResources(){ return null; } + public String getNonResourceString(int p0){ return null; } + public String getPositionDescription(){ return null; } + public String getString(int p0){ return null; } + public String toString(){ return null; } + public TypedValue peekValue(int p0){ return null; } + public Typeface getFont(int p0){ return null; } + public boolean getBoolean(int p0, boolean p1){ return false; } + public boolean getValue(int p0, TypedValue p1){ return false; } + public boolean hasValue(int p0){ return false; } + public boolean hasValueOrEmpty(int p0){ return false; } + public float getDimension(int p0, float p1){ return 0; } + public float getFloat(int p0, float p1){ return 0; } + public float getFraction(int p0, int p1, int p2, float p3){ return 0; } + public int getChangingConfigurations(){ return 0; } + public int getColor(int p0, int p1){ return 0; } + public int getDimensionPixelOffset(int p0, int p1){ return 0; } + public int getDimensionPixelSize(int p0, int p1){ return 0; } + public int getIndex(int p0){ return 0; } + public int getIndexCount(){ return 0; } + public int getInt(int p0, int p1){ return 0; } + public int getInteger(int p0, int p1){ return 0; } + public int getLayoutDimension(int p0, String p1){ return 0; } + public int getLayoutDimension(int p0, int p1){ return 0; } + public int getResourceId(int p0, int p1){ return 0; } + public int getSourceResourceId(int p0, int p1){ return 0; } + public int getType(int p0){ return 0; } + public int length(){ return 0; } + public void recycle(){} +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/res/XmlResourceParser.java b/java/ql/test/stubs/google-android-9.0.0/android/content/res/XmlResourceParser.java new file mode 100644 index 00000000000..61a50fe8bec --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/res/XmlResourceParser.java @@ -0,0 +1,12 @@ +// Generated automatically from android.content.res.XmlResourceParser for testing purposes + +package android.content.res; + +import android.util.AttributeSet; +import org.xmlpull.v1.XmlPullParser; + +public interface XmlResourceParser extends AttributeSet, AutoCloseable, XmlPullParser +{ + String getAttributeNamespace(int p0); + void close(); +} From 490168fb05171c67da1d5d18796bb748bfff75fe Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Thu, 12 Aug 2021 11:22:51 +0100 Subject: [PATCH 234/361] Fix comments --- java/ql/lib/semmle/code/java/frameworks/android/Android.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index 15bdb1fb95e..9b7410c4634 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -238,7 +238,7 @@ private class TaintPropagationModels extends SummaryModelCsv { "ShortArray", "Size", "SizeF", "SparseParcelableArray", "StringArrayList" ] + ";;;Argument[-1];ReturnValue;taint" or - // Intent readers that return their value + // Parcel readers that return their value s = "android.os;Parcel;false;read" + [ @@ -248,7 +248,7 @@ private class TaintPropagationModels extends SummaryModelCsv { "StrongBinder", "TypedObject", "Value" ] + ";;;Argument[-1];ReturnValue;taint" or - // Intent readers that write to an existing object + // Parcel readers that write to an existing object s = "android.os;Parcel;false;read" + [ @@ -257,7 +257,7 @@ private class TaintPropagationModels extends SummaryModelCsv { "StringList", "TypedArray", "TypedList" ] + ";;;Argument[-1];Argument[0];taint" or - // One Intent method that aliases an argument to a return value + // One Parcel method that aliases an argument to a return value s = "android.os;Parcel;false;readParcelableList;;;Argument[0];ReturnValue;value" } } From 9e0b112f055124e7c3f41e0f8f6fb7c3d7ad9965 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Thu, 7 Oct 2021 12:13:20 +0100 Subject: [PATCH 235/361] Remove now-unnecessary models and tests --- .../code/java/dataflow/ExternalFlow.qll | 1 - .../code/java/frameworks/android/Android.qll | 19 +- .../frameworks/android/flow-steps/Test.java | 497 ------------------ .../frameworks/android/flow-steps/test.ql | 53 +- 4 files changed, 2 insertions(+), 568 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index cedeb71189c..cfbcd16f75e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -80,7 +80,6 @@ private module Frameworks { private import semmle.code.java.frameworks.android.Android private import semmle.code.java.frameworks.android.Intent private import semmle.code.java.frameworks.android.XssSinks - private import semmle.code.java.frameworks.android.Intent private import semmle.code.java.frameworks.ApacheHttp private import semmle.code.java.frameworks.apache.Collections private import semmle.code.java.frameworks.apache.Lang diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index 9b7410c4634..f11f188c0f8 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -219,25 +219,8 @@ class CreateFromParcelMethod extends Method { } } -private class TaintPropagationModels extends SummaryModelCsv { +private class ParcelPropagationModels extends SummaryModelCsv { override predicate row(string s) { - // BaseBundle getters. These are also modelled on Bundle because BaseBundle was factored out of Bundle - // in Android 5.0; before that these methods were declared directly on Bundle. - s = - "android.os;" + ["BaseBundle", "Bundle"] + ";true;get" + - ["Boolean", "Double", "Int", "Long", "String"] + ["", "Array"] + - ";;;Argument[-1];ReturnValue;taint" - or - // Bundle getters - s = - "android.os;Bundle;true;get" + - [ - "Binder", "Bundle", "Byte", "ByteArray", "Char", "CharArray", "CharSequence", - "CharSequenceArray", "CharSequenceArrayList", "Float", "FloatArray", "IntegerArrayList", - "Parcelable", "ParcelableArray", "ParcelableArrayList", "Serializable", "Short", - "ShortArray", "Size", "SizeF", "SparseParcelableArray", "StringArrayList" - ] + ";;;Argument[-1];ReturnValue;taint" - or // Parcel readers that return their value s = "android.os;Parcel;false;read" + diff --git a/java/ql/test/library-tests/frameworks/android/flow-steps/Test.java b/java/ql/test/library-tests/frameworks/android/flow-steps/Test.java index b8f7e910c02..7ac9f2a8490 100644 --- a/java/ql/test/library-tests/frameworks/android/flow-steps/Test.java +++ b/java/ql/test/library-tests/frameworks/android/flow-steps/Test.java @@ -26,503 +26,6 @@ public class Test { public void test() throws Exception { - { - // "android.content;Intent;true;getBooleanArrayExtra;;;Argument[-1];ReturnValue;taint" - boolean[] out = null; - Intent in = (Intent)source(); - out = in.getBooleanArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getBooleanExtra;;;Argument[-1];ReturnValue;taint" - boolean out = false; - Intent in = (Intent)source(); - out = in.getBooleanExtra(null, false); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getBundleExtra;;;Argument[-1];ReturnValue;taint" - Bundle out = null; - Intent in = (Intent)source(); - out = in.getBundleExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getByteArrayExtra;;;Argument[-1];ReturnValue;taint" - byte[] out = null; - Intent in = (Intent)source(); - out = in.getByteArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getByteExtra;;;Argument[-1];ReturnValue;taint" - byte out = 0; - Intent in = (Intent)source(); - out = in.getByteExtra(null, (byte)0); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getCharArrayExtra;;;Argument[-1];ReturnValue;taint" - char[] out = null; - Intent in = (Intent)source(); - out = in.getCharArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getCharExtra;;;Argument[-1];ReturnValue;taint" - char out = 'a'; - Intent in = (Intent)source(); - out = in.getCharExtra(null, 'a'); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getCharSequenceArrayExtra;;;Argument[-1];ReturnValue;taint" - CharSequence[] out = null; - Intent in = (Intent)source(); - out = in.getCharSequenceArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getCharSequenceArrayListExtra;;;Argument[-1];ReturnValue;taint" - ArrayList out = null; - Intent in = (Intent)source(); - out = in.getCharSequenceArrayListExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getCharSequenceExtra;;;Argument[-1];ReturnValue;taint" - CharSequence out = null; - Intent in = (Intent)source(); - out = in.getCharSequenceExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getDoubleArrayExtra;;;Argument[-1];ReturnValue;taint" - double[] out = null; - Intent in = (Intent)source(); - out = in.getDoubleArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getDoubleExtra;;;Argument[-1];ReturnValue;taint" - double out = 0.0; - Intent in = (Intent)source(); - out = in.getDoubleExtra(null, 0.0); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getExtras;;;Argument[-1];ReturnValue;taint" - Bundle out = null; - Intent in = (Intent)source(); - out = in.getExtras(); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getFloatArrayExtra;;;Argument[-1];ReturnValue;taint" - float[] out = null; - Intent in = (Intent)source(); - out = in.getFloatArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getFloatExtra;;;Argument[-1];ReturnValue;taint" - float out = 0.0f; - Intent in = (Intent)source(); - out = in.getFloatExtra(null, 0.0f); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getIntArrayExtra;;;Argument[-1];ReturnValue;taint" - int[] out = null; - Intent in = (Intent)source(); - out = in.getIntArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getIntExtra;;;Argument[-1];ReturnValue;taint" - int out = 0; - Intent in = (Intent)source(); - out = in.getIntExtra(null, 0); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getIntegerArrayListExtra;;;Argument[-1];ReturnValue;taint" - ArrayList out = null; - Intent in = (Intent)source(); - out = in.getIntegerArrayListExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getLongArrayExtra;;;Argument[-1];ReturnValue;taint" - long[] out = null; - Intent in = (Intent)source(); - out = in.getLongArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getLongExtra;;;Argument[-1];ReturnValue;taint" - long out = 0L; - Intent in = (Intent)source(); - out = in.getLongExtra(null, 0L); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getParcelableArrayExtra;;;Argument[-1];ReturnValue;taint" - Parcelable[] out = null; - Intent in = (Intent)source(); - out = in.getParcelableArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getParcelableArrayListExtra;;;Argument[-1];ReturnValue;taint" - ArrayList out = null; - Intent in = (Intent)source(); - out = in.getParcelableArrayListExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getParcelableExtra;;;Argument[-1];ReturnValue;taint" - Parcelable out = null; - Intent in = (Intent)source(); - out = in.getParcelableExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getSerializableExtra;;;Argument[-1];ReturnValue;taint" - Serializable out = null; - Intent in = (Intent)source(); - out = in.getSerializableExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getShortArrayExtra;;;Argument[-1];ReturnValue;taint" - short[] out = null; - Intent in = (Intent)source(); - out = in.getShortArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getShortExtra;;;Argument[-1];ReturnValue;taint" - short out = 0; - Intent in = (Intent)source(); - out = in.getShortExtra(null, (short)0); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getStringArrayExtra;;;Argument[-1];ReturnValue;taint" - String[] out = null; - Intent in = (Intent)source(); - out = in.getStringArrayExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getStringArrayListExtra;;;Argument[-1];ReturnValue;taint" - ArrayList out = null; - Intent in = (Intent)source(); - out = in.getStringArrayListExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.content;Intent;true;getStringExtra;;;Argument[-1];ReturnValue;taint" - String out = null; - Intent in = (Intent)source(); - out = in.getStringExtra(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getBoolean;;;Argument[-1];ReturnValue;taint" - boolean out = false; - BaseBundle in = (BaseBundle)source(); - out = in.getBoolean(null, false); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getBoolean;;;Argument[-1];ReturnValue;taint" - boolean out = false; - BaseBundle in = (BaseBundle)source(); - out = in.getBoolean(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getBooleanArray;;;Argument[-1];ReturnValue;taint" - boolean[] out = null; - BaseBundle in = (BaseBundle)source(); - out = in.getBooleanArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getDouble;;;Argument[-1];ReturnValue;taint" - double out = 0.0; - BaseBundle in = (BaseBundle)source(); - out = in.getDouble(null, 0.0); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getDouble;;;Argument[-1];ReturnValue;taint" - double out = 0.0; - BaseBundle in = (BaseBundle)source(); - out = in.getDouble(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getDoubleArray;;;Argument[-1];ReturnValue;taint" - double[] out = null; - BaseBundle in = (BaseBundle)source(); - out = in.getDoubleArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getInt;;;Argument[-1];ReturnValue;taint" - int out = 0; - BaseBundle in = (BaseBundle)source(); - out = in.getInt(null, 0); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getInt;;;Argument[-1];ReturnValue;taint" - int out = 0; - BaseBundle in = (BaseBundle)source(); - out = in.getInt(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getIntArray;;;Argument[-1];ReturnValue;taint" - int[] out = null; - BaseBundle in = (BaseBundle)source(); - out = in.getIntArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getLong;;;Argument[-1];ReturnValue;taint" - long out = 0L; - BaseBundle in = (BaseBundle)source(); - out = in.getLong(null, 0L); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getLong;;;Argument[-1];ReturnValue;taint" - long out = 0L; - BaseBundle in = (BaseBundle)source(); - out = in.getLong(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getLongArray;;;Argument[-1];ReturnValue;taint" - long[] out = null; - BaseBundle in = (BaseBundle)source(); - out = in.getLongArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getString;;;Argument[-1];ReturnValue;taint" - String out = null; - BaseBundle in = (BaseBundle)source(); - out = in.getString(null, null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getString;;;Argument[-1];ReturnValue;taint" - String out = null; - BaseBundle in = (BaseBundle)source(); - out = in.getString(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;BaseBundle;true;getStringArray;;;Argument[-1];ReturnValue;taint" - String[] out = null; - BaseBundle in = (BaseBundle)source(); - out = in.getStringArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getBinder;;;Argument[-1];ReturnValue;taint" - IBinder out = null; - Bundle in = (Bundle)source(); - out = in.getBinder(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getBundle;;;Argument[-1];ReturnValue;taint" - Bundle out = null; - Bundle in = (Bundle)source(); - out = in.getBundle(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getByte;;;Argument[-1];ReturnValue;taint" - byte out = 0; - Bundle in = (Bundle)source(); - out = in.getByte(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getByte;;;Argument[-1];ReturnValue;taint" - byte out = 0; - Bundle in = (Bundle)source(); - out = in.getByte(null, (byte)0); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getByteArray;;;Argument[-1];ReturnValue;taint" - byte[] out = null; - Bundle in = (Bundle)source(); - out = in.getByteArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getChar;;;Argument[-1];ReturnValue;taint" - char out = 'a'; - Bundle in = (Bundle)source(); - out = in.getChar(null, 'a'); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getChar;;;Argument[-1];ReturnValue;taint" - char out = 'a'; - Bundle in = (Bundle)source(); - out = in.getChar(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getCharArray;;;Argument[-1];ReturnValue;taint" - char[] out = null; - Bundle in = (Bundle)source(); - out = in.getCharArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getCharSequence;;;Argument[-1];ReturnValue;taint" - CharSequence out = null; - Bundle in = (Bundle)source(); - out = in.getCharSequence(null, null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getCharSequence;;;Argument[-1];ReturnValue;taint" - CharSequence out = null; - Bundle in = (Bundle)source(); - out = in.getCharSequence(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getCharSequenceArray;;;Argument[-1];ReturnValue;taint" - CharSequence[] out = null; - Bundle in = (Bundle)source(); - out = in.getCharSequenceArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getCharSequenceArrayList;;;Argument[-1];ReturnValue;taint" - ArrayList out = null; - Bundle in = (Bundle)source(); - out = in.getCharSequenceArrayList(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getFloat;;;Argument[-1];ReturnValue;taint" - float out = 0.0f; - Bundle in = (Bundle)source(); - out = in.getFloat(null, 0.0f); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getFloat;;;Argument[-1];ReturnValue;taint" - float out = 0.0f; - Bundle in = (Bundle)source(); - out = in.getFloat(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getFloatArray;;;Argument[-1];ReturnValue;taint" - float[] out = null; - Bundle in = (Bundle)source(); - out = in.getFloatArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getIntegerArrayList;;;Argument[-1];ReturnValue;taint" - ArrayList out = null; - Bundle in = (Bundle)source(); - out = in.getIntegerArrayList(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getParcelable;;;Argument[-1];ReturnValue;taint" - Parcelable out = null; - Bundle in = (Bundle)source(); - out = in.getParcelable(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getParcelableArray;;;Argument[-1];ReturnValue;taint" - Parcelable[] out = null; - Bundle in = (Bundle)source(); - out = in.getParcelableArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getParcelableArrayList;;;Argument[-1];ReturnValue;taint" - ArrayList out = null; - Bundle in = (Bundle)source(); - out = in.getParcelableArrayList(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getSerializable;;;Argument[-1];ReturnValue;taint" - Serializable out = null; - Bundle in = (Bundle)source(); - out = in.getSerializable(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getShort;;;Argument[-1];ReturnValue;taint" - short out = 0; - Bundle in = (Bundle)source(); - out = in.getShort(null, (short)0); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getShort;;;Argument[-1];ReturnValue;taint" - short out = 0; - Bundle in = (Bundle)source(); - out = in.getShort(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getShortArray;;;Argument[-1];ReturnValue;taint" - short[] out = null; - Bundle in = (Bundle)source(); - out = in.getShortArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getSize;;;Argument[-1];ReturnValue;taint" - Size out = null; - Bundle in = (Bundle)source(); - out = in.getSize(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getSizeF;;;Argument[-1];ReturnValue;taint" - SizeF out = null; - Bundle in = (Bundle)source(); - out = in.getSizeF(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getSparseParcelableArray;;;Argument[-1];ReturnValue;taint" - SparseArray out = null; - Bundle in = (Bundle)source(); - out = in.getSparseParcelableArray(null); - sink(out); // $ hasTaintFlow - } - { - // "android.os;Bundle;true;getStringArrayList;;;Argument[-1];ReturnValue;taint" - ArrayList out = null; - Bundle in = (Bundle)source(); - out = in.getStringArrayList(null); - sink(out); // $ hasTaintFlow - } { // "android.os;Parcel;false;readArray;;;Argument[-1];ReturnValue;taint" Object[] out = null; diff --git a/java/ql/test/library-tests/frameworks/android/flow-steps/test.ql b/java/ql/test/library-tests/frameworks/android/flow-steps/test.ql index 465161863cc..5d91e4e8e26 100644 --- a/java/ql/test/library-tests/frameworks/android/flow-steps/test.ql +++ b/java/ql/test/library-tests/frameworks/android/flow-steps/test.ql @@ -1,53 +1,2 @@ import java -import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.ExternalFlow -import semmle.code.java.dataflow.TaintTracking -import TestUtilities.InlineExpectationsTest - -class ValueFlowConf extends DataFlow::Configuration { - ValueFlowConf() { this = "qltest:valueFlowConf" } - - override predicate isSource(DataFlow::Node n) { - n.asExpr().(MethodAccess).getMethod().hasName("source") - } - - override predicate isSink(DataFlow::Node n) { - n.asExpr().(Argument).getCall().getCallee().hasName("sink") - } -} - -class TaintFlowConf extends TaintTracking::Configuration { - TaintFlowConf() { this = "qltest:taintFlowConf" } - - override predicate isSource(DataFlow::Node n) { - n.asExpr().(MethodAccess).getMethod().hasName("source") - } - - override predicate isSink(DataFlow::Node n) { - n.asExpr().(Argument).getCall().getCallee().hasName("sink") - } -} - -class HasFlowTest extends InlineExpectationsTest { - HasFlowTest() { this = "HasFlowTest" } - - override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } - - override predicate hasActualResult(Location location, string element, string tag, string value) { - tag = "hasValueFlow" and - exists(DataFlow::Node src, DataFlow::Node sink, ValueFlowConf conf | conf.hasFlow(src, sink) | - sink.getLocation() = location and - element = sink.toString() and - value = "" - ) - or - tag = "hasTaintFlow" and - exists(DataFlow::Node src, DataFlow::Node sink, TaintFlowConf conf | - conf.hasFlow(src, sink) and not any(ValueFlowConf c).hasFlow(src, sink) - | - sink.getLocation() = location and - element = sink.toString() and - value = "" - ) - } -} +import TestUtilities.InlineFlowTest From 1afc03b9b527e929f37a1617e1d2953175a928d0 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Thu, 7 Oct 2021 12:14:14 +0100 Subject: [PATCH 236/361] Remove redundant import --- java/ql/lib/semmle/code/java/frameworks/android/Android.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index f11f188c0f8..a599f7befc9 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -5,7 +5,6 @@ import java import semmle.code.java.dataflow.ExternalFlow import semmle.code.xml.AndroidManifest -private import semmle.code.java.dataflow.ExternalFlow /** * Gets a transitive superType avoiding magic optimisation From 5da392ebfe7fbdbf068544bd6690a820d63a2cc3 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Thu, 7 Oct 2021 11:20:19 +0100 Subject: [PATCH 237/361] Introduce TaintInheritingContent --- .../ql/lib/semmle/code/java/frameworks/android/Intent.qll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 3798d91d99a..94c95c3bcad 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -75,6 +75,14 @@ class IntentGetParcelableExtraMethod extends Method { } } +/** + * Specifies that if an `Intent` is tainted, then so are its synthetic fields. + */ +private class IntentFieldsInheritTaint extends DataFlow::SyntheticFieldContent, + TaintInheritingContent { + IntentFieldsInheritTaint() { this.getField().matches("android.content.Intent.%") } +} + private class IntentBundleFlowSteps extends SummaryModelCsv { override predicate row(string row) { row = From 205b6fe6d76b950725473a3071b8b22c3781fb74 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Thu, 7 Oct 2021 12:33:41 +0100 Subject: [PATCH 238/361] Fix bad merge on Uri.java --- .../google-android-9.0.0/android/net/Uri.java | 148 ------------------ 1 file changed, 148 deletions(-) diff --git a/java/ql/test/stubs/google-android-9.0.0/android/net/Uri.java b/java/ql/test/stubs/google-android-9.0.0/android/net/Uri.java index 38ad75077d6..963829742b2 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/net/Uri.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/net/Uri.java @@ -72,152 +72,4 @@ abstract public class Uri implements Comparable<Uri>, Parcelable public Uri.Builder query(String p0){ return null; } public Uri.Builder scheme(String p0){ return null; } } - - public Builder buildUpon() { return null; } - - /** - * Helper class for building or manipulating URI references. Not safe for - * concurrent use. - * - * <p>An absolute hierarchical URI reference follows the pattern: - * {@code <scheme>://<authority><absolute path>?<query>#<fragment>} - * - * <p>Relative URI references (which are always hierarchical) follow one - * of two patterns: {@code <relative or absolute path>?<query>#<fragment>} - * or {@code //<authority><absolute path>?<query>#<fragment>} - * - * <p>An opaque URI follows this pattern: - * {@code <scheme>:<opaque part>#<fragment>} - * - * <p>Use {@link Uri#buildUpon()} to obtain a builder representing an existing URI. - */ - public static final class Builder { - /** - * Constructs a new Builder. - */ - public Builder() {} - /** - * Sets the scheme. - * - * @param scheme name or {@code null} if this is a relative Uri - */ - public Builder scheme(String scheme) { - return null; - } - /** - * Encodes and sets the given opaque scheme-specific-part. - * - * @param opaquePart decoded opaque part - */ - public Builder opaquePart(String opaquePart) { - return null; - } - /** - * Sets the previously encoded opaque scheme-specific-part. - * - * @param opaquePart encoded opaque part - */ - public Builder encodedOpaquePart(String opaquePart) { - return null; - } - /** - * Encodes and sets the authority. - */ - public Builder authority(String authority) { - return null; - } - /** - * Sets the previously encoded authority. - */ - public Builder encodedAuthority(String authority) { - return null; - } - /** - * Sets the path. Leaves '/' characters intact but encodes others as - * necessary. - * - * <p>If the path is not null and doesn't start with a '/', and if - * you specify a scheme and/or authority, the builder will prepend the - * given path with a '/'. - */ - public Builder path(String path) { - return null; - } - /** - * Sets the previously encoded path. - * - * <p>If the path is not null and doesn't start with a '/', and if - * you specify a scheme and/or authority, the builder will prepend the - * given path with a '/'. - */ - public Builder encodedPath(String path) { - return null; - } - /** - * Encodes the given segment and appends it to the path. - */ - public Builder appendPath(String newSegment) { - return null; - } - /** - * Appends the given segment to the path. - */ - public Builder appendEncodedPath(String newSegment) { - return null; - } - /** - * Encodes and sets the query. - */ - public Builder query(String query) { - return null; - } - /** - * Sets the previously encoded query. - */ - public Builder encodedQuery(String query) { - return null; - } - /** - * Encodes and sets the fragment. - */ - public Builder fragment(String fragment) { - return null; - } - /** - * Sets the previously encoded fragment. - */ - public Builder encodedFragment(String fragment) { - return null; - } - /** - * Encodes the key and value and then appends the parameter to the - * query string. - * - * @param key which will be encoded - * @param value which will be encoded - */ - public Builder appendQueryParameter(String key, String value) { - return null; - } - /** - * Clears the the previously set query. - */ - public Builder clearQuery() { - return null; - } - /** - * Constructs a Uri with the current attributes. - * - * @throws UnsupportedOperationException if the URI is opaque and the - * scheme is null - */ - public Uri build() { - return null; - } - @Override - public String toString() { - return null; - } - } - } From 8816aa1431e61dac5a072f8d218e1e52b78c467f Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 12 Oct 2021 12:33:51 +0100 Subject: [PATCH 239/361] Improve Android stub fidelity to the point that all relevant tests work Note these still aren't entirely mechanically generated stubs matching the real Android 9. --- .../dataflow/taintsources/remote.expected | 36 +- .../android/annotation/StyleRes.java | 38 + .../android/app/Activity.java | 53 +- .../android/content/BroadcastReceiver.java | 293 +- .../android/content/ComponentName.java | 58 +- .../android/content/Context.java | 1282 ++----- .../android/content/ContextWrapper.java | 280 +- .../android/content/Intent.java | 3061 +++-------------- .../android/content/SharedPreferences.java | 384 +-- .../android/view/ContextThemeWrapper.java | 132 + 10 files changed, 1122 insertions(+), 4495 deletions(-) create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/annotation/StyleRes.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/view/ContextThemeWrapper.java diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.expected b/java/ql/test/library-tests/dataflow/taintsources/remote.expected index c6b22148e24..26cc2a15d19 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.expected @@ -5,34 +5,34 @@ | A.java:41:5:41:53 | getInputStream(...) | A.java:41:5:41:53 | getInputStream(...) | | A.java:42:5:42:45 | getInputStream(...) | A.java:42:5:42:45 | getInputStream(...) | | A.java:43:5:43:47 | getHostName(...) | A.java:43:5:43:47 | getHostName(...) | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] to write: return (return) in getStringExtra | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | parameter this | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:35 | getIntent(...) | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:57 | getStringExtra(...) | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:10:29:10:35 | trouble | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] to write: return (return) in getStringExtra | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | parameter this | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:30 | getIntent(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:52 | getStringExtra(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:17:29:17:35 | trouble | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | [summary] read: android.content.Intent.extras of argument -1 in getExtras | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | [summary] to write: return (return) in getExtras | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | parameter this | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] read: <map.value> of argument -1 in getString | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] to write: return (return) in getString | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | parameter this | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:33:19:33:27 | [summary] read: android.content.Intent.extras of argument -1 in getExtras | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:33:19:33:27 | [summary] to write: return (return) in getExtras | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:33:19:33:27 | parameter this | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:12:19:12:27 | [summary] read: <map.value> of argument -1 in getString | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:12:19:12:27 | [summary] to write: return (return) in getString | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:12:19:12:27 | parameter this | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:30 | getIntent(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:42 | getExtras(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:59 | getString(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:24:29:24:35 | trouble | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | [summary] to write: return (return) in getStringExtra | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:105:19:105:32 | parameter this | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:33 | getIntent(...) | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:55 | getStringExtra(...) | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:34:29:34:35 | trouble | diff --git a/java/ql/test/stubs/google-android-9.0.0/android/annotation/StyleRes.java b/java/ql/test/stubs/google-android-9.0.0/android/annotation/StyleRes.java new file mode 100644 index 00000000000..2a75e140347 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/annotation/StyleRes.java @@ -0,0 +1,38 @@ + +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that a integer parameter, field or method return value is expected + * to be a style resource reference (e.g. {@link android.R.style#TextAppearance}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface StyleRes { +} \ No newline at end of file diff --git a/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java b/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java index 99b797fb2a8..9e31a58a260 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java @@ -15,11 +15,10 @@ */ package android.app; -import android.content.Context; -import android.content.ContextWrapper; import android.content.Intent; +import android.content.ComponentCallbacks2; import android.os.Bundle; -import android.view.View; +import android.view.*; /** * An activity is a single, focused thing that the user can do. Almost all @@ -189,7 +188,7 @@ import android.view.View; * </p> * * </p> - * + * * <pre class="prettyprint"> * public class Activity extends ApplicationContext { * protected void onCreate(Bundle savedInstanceState); @@ -677,16 +676,7 @@ import android.view.View; * upload, independent of whether the original activity is paused, stopped, or * finished. */ -public class Activity extends ContextWrapper { - /** Standard activity result: operation canceled. */ - public static final int RESULT_CANCELED = 0; - - /** Standard activity result: operation succeeded. */ - public static final int RESULT_OK = -1; - - /** Start of user-defined activity results. */ - public static final int RESULT_FIRST_USER = 1; - +public class Activity extends ContextThemeWrapper { /** Return the intent that started this activity. */ public Intent getIntent() { return null; @@ -1154,36 +1144,7 @@ public class Activity extends ContextWrapper { public void startActivities(Intent[] intents, Bundle options) { } - /** - * Called when an activity you launched exits, giving you the requestCode - * you started it with, the resultCode it returned, and any additional - * data from it. The <var>resultCode</var> will be - * {@link #RESULT_CANCELED} if the activity explicitly returned that, - * didn't return any result, or crashed during its operation. - * - * <p>An activity can never receive a result in the resumed state. You can count on - * {@link #onResume} being called after this method, though not necessarily immediately after. - * If the activity was resumed, it will be paused and the result will be delivered, followed - * by {@link #onResume}. If the activity wasn't in the resumed state, then the result will - * be delivered, with {@link #onResume} called sometime later when the activity becomes active - * again. - * - * <p>This method is never invoked if your activity sets - * {@link android.R.styleable#AndroidManifestActivity_noHistory noHistory} to - * <code>true</code>. - * - * @param requestCode The integer request code originally supplied to - * startActivityForResult(), allowing you to identify who this - * result came from. - * @param resultCode The integer result code returned by the child activity - * through its setResult(). - * @param data An Intent, which can return result data to the caller - * (various data can be attached to Intent "extras"). - * - * @see #startActivityForResult - * @see #createPendingResult - * @see #setResult(int) - */ - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - } + protected void onActivityResult(int requestCode, int resultCode, Intent data) { } + + public static final int RESULT_OK = -1; } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/BroadcastReceiver.java b/java/ql/test/stubs/google-android-9.0.0/android/content/BroadcastReceiver.java index 1d73018c96d..f199fcccc75 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/BroadcastReceiver.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/BroadcastReceiver.java @@ -1,255 +1,46 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.content.BroadcastReceiver for testing purposes + package android.content; +import android.content.Context; +import android.content.Intent; import android.os.Bundle; -/** - * Base class for code that will receive intents sent by sendBroadcast(). - * - * <p>If you don't need to send broadcasts across applications, consider using - * this class with {@link android.support.v4.content.LocalBroadcastManager} instead - * of the more general facilities described below. This will give you a much - * more efficient implementation (no cross-process communication needed) and allow - * you to avoid thinking about any security issues related to other applications - * being able to receive or send your broadcasts. - * - * <p>You can either dynamically register an instance of this class with - * {@link Context#registerReceiver Context.registerReceiver()} - * or statically publish an implementation through the - * {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag in your <code>AndroidManifest.xml</code>. - * - * <p><em><strong>Note:</strong></em> - *    If registering a receiver in your - * {@link android.app.Activity#onResume() Activity.onResume()} - * implementation, you should unregister it in - * {@link android.app.Activity#onPause() Activity.onPause()}. - * (You won't receive intents when paused, - * and this will cut down on unnecessary system overhead). Do not unregister in - * {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) Activity.onSaveInstanceState()}, - * because this won't be called if the user moves back in the history - * stack. - * - * <p>There are two major classes of broadcasts that can be received:</p> - * <ul> - * <li> <b>Normal broadcasts</b> (sent with {@link Context#sendBroadcast(Intent) - * Context.sendBroadcast}) are completely asynchronous. All receivers of the - * broadcast are run in an undefined order, often at the same time. This is - * more efficient, but means that receivers cannot use the result or abort - * APIs included here. - * <li> <b>Ordered broadcasts</b> (sent with {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast}) are delivered to one receiver at a time. - * As each receiver executes in turn, it can propagate a result to the next - * receiver, or it can completely abort the broadcast so that it won't be passed - * to other receivers. The order receivers run in can be controlled with the - * {@link android.R.styleable#AndroidManifestIntentFilter_priority - * android:priority} attribute of the matching intent-filter; receivers with - * the same priority will be run in an arbitrary order. - * </ul> - * - * <p>Even in the case of normal broadcasts, the system may in some - * situations revert to delivering the broadcast one receiver at a time. In - * particular, for receivers that may require the creation of a process, only - * one will be run at a time to avoid overloading the system with new processes. - * In this situation, however, the non-ordered semantics hold: these receivers still - * cannot return results or abort their broadcast.</p> - * - * <p>Note that, although the Intent class is used for sending and receiving - * these broadcasts, the Intent broadcast mechanism here is completely separate - * from Intents that are used to start Activities with - * {@link Context#startActivity Context.startActivity()}. - * There is no way for a BroadcastReceiver - * to see or capture Intents used with startActivity(); likewise, when - * you broadcast an Intent, you will never find or start an Activity. - * These two operations are semantically very different: starting an - * Activity with an Intent is a foreground operation that modifies what the - * user is currently interacting with; broadcasting an Intent is a background - * operation that the user is not normally aware of. - * - * <p>The BroadcastReceiver class (when launched as a component through - * a manifest's {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag) is an important part of an - * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">application's overall lifecycle</a>.</p> - * - * <p>Topics covered here: - * <ol> - * <li><a href="#Security">Security</a> - * <li><a href="#ReceiverLifecycle">Receiver Lifecycle</a> - * <li><a href="#ProcessLifecycle">Process Lifecycle</a> - * </ol> - * - * <div class="special reference"> - * <h3>Developer Guides</h3> - * <p>For information about how to use this class to receive and resolve intents, read the - * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a> - * developer guide.</p> - * </div> - * - * <a name="Security"></a> - * <h3>Security</h3> - * - * <p>Receivers used with the {@link Context} APIs are by their nature a - * cross-application facility, so you must consider how other applications - * may be able to abuse your use of them. Some things to consider are: - * - * <ul> - * <li><p>The Intent namespace is global. Make sure that Intent action names and - * other strings are written in a namespace you own, or else you may inadvertantly - * conflict with other applications. - * <li><p>When you use {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)}, - * <em>any</em> application may send broadcasts to that registered receiver. You can - * control who can send broadcasts to it through permissions described below. - * <li><p>When you publish a receiver in your application's manifest and specify - * intent-filters for it, any other application can send broadcasts to it regardless - * of the filters you specify. To prevent others from sending to it, make it - * unavailable to them with <code>android:exported="false"</code>. - * <li><p>When you use {@link Context#sendBroadcast(Intent)} or related methods, - * normally any other application can receive these broadcasts. You can control who - * can receive such broadcasts through permissions described below. Alternatively, - * starting with {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, you - * can also safely restrict the broadcast to a single application with - * {@link Intent#setPackage(String) Intent.setPackage} - * </ul> - * - * <p>None of these issues exist when using - * {@link android.support.v4.content.LocalBroadcastManager}, since intents - * broadcast it never go outside of the current process. - * - * <p>Access permissions can be enforced by either the sender or receiver - * of a broadcast. - * - * <p>To enforce a permission when sending, you supply a non-null - * <var>permission</var> argument to - * {@link Context#sendBroadcast(Intent, String)} or - * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}. - * Only receivers who have been granted this permission - * (by requesting it with the - * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} - * tag in their <code>AndroidManifest.xml</code>) will be able to receive - * the broadcast. - * - * <p>To enforce a permission when receiving, you supply a non-null - * <var>permission</var> when registering your receiver -- either when calling - * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)} - * or in the static - * {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag in your <code>AndroidManifest.xml</code>. Only broadcasters who have - * been granted this permission (by requesting it with the - * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} - * tag in their <code>AndroidManifest.xml</code>) will be able to send an - * Intent to the receiver. - * - * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> - * document for more information on permissions and security in general. - * - * <a name="ReceiverLifecycle"></a> - * <h3>Receiver Lifecycle</h3> - * - * <p>A BroadcastReceiver object is only valid for the duration of the call - * to {@link #onReceive}. Once your code returns from this function, - * the system considers the object to be finished and no longer active. - * - * <p>This has important repercussions to what you can do in an - * {@link #onReceive} implementation: anything that requires asynchronous - * operation is not available, because you will need to return from the - * function to handle the asynchronous operation, but at that point the - * BroadcastReceiver is no longer active and thus the system is free to kill - * its process before the asynchronous operation completes. - * - * <p>In particular, you may <i>not</i> show a dialog or bind to a service from - * within a BroadcastReceiver. For the former, you should instead use the - * {@link android.app.NotificationManager} API. For the latter, you can - * use {@link android.content.Context#startService Context.startService()} to - * send a command to the service. - * - * <a name="ProcessLifecycle"></a> - * <h3>Process Lifecycle</h3> - * - * <p>A process that is currently executing a BroadcastReceiver (that is, - * currently running the code in its {@link #onReceive} method) is - * considered to be a foreground process and will be kept running by the - * system except under cases of extreme memory pressure. - * - * <p>Once you return from onReceive(), the BroadcastReceiver is no longer - * active, and its hosting process is only as important as any other application - * components that are running in it. This is especially important because if - * that process was only hosting the BroadcastReceiver (a common case for - * applications that the user has never or not recently interacted with), then - * upon returning from onReceive() the system will consider its process - * to be empty and aggressively kill it so that resources are available for other - * more important processes. - * - * <p>This means that for longer-running operations you will often use - * a {@link android.app.Service} in conjunction with a BroadcastReceiver to keep - * the containing process active for the entire time of your operation. - */ -public abstract class BroadcastReceiver { - - /** - * State for a result that is pending for a broadcast receiver. Returned - * by {@link BroadcastReceiver#goAsync() goAsync()} - * while in {@link BroadcastReceiver#onReceive BroadcastReceiver.onReceive()}. - * This allows you to return from onReceive() without having the broadcast - * terminate; you must call {@link #finish()} once you are done with the - * broadcast. This allows you to process the broadcast off of the main - * thread of your app. - * - * <p>Note on threading: the state inside of this class is not itself - * thread-safe, however you can use it from any thread if you properly - * sure that you do not have races. Typically this means you will hand - * the entire object to another thread, which will be solely responsible - * for setting any results and finally calling {@link #finish()}. - */ - - public BroadcastReceiver() { +import android.os.IBinder; + +abstract public class BroadcastReceiver +{ + public BroadcastReceiver(){} + public IBinder peekService(Context p0, Intent p1){ return null; } + public abstract void onReceive(Context p0, Intent p1); + public final BroadcastReceiver.PendingResult goAsync(){ return null; } + public final Bundle getResultExtras(boolean p0){ return null; } + public final String getResultData(){ return null; } + public final boolean getAbortBroadcast(){ return false; } + public final boolean getDebugUnregister(){ return false; } + public final boolean isInitialStickyBroadcast(){ return false; } + public final boolean isOrderedBroadcast(){ return false; } + public final int getResultCode(){ return 0; } + public final void abortBroadcast(){} + public final void clearAbortBroadcast(){} + public final void setDebugUnregister(boolean p0){} + public final void setOrderedHint(boolean p0){} + public final void setResult(int p0, String p1, Bundle p2){} + public final void setResultCode(int p0){} + public final void setResultData(String p0){} + public final void setResultExtras(Bundle p0){} + static public class PendingResult + { + protected PendingResult() {} + public final Bundle getResultExtras(boolean p0){ return null; } + public final String getResultData(){ return null; } + public final boolean getAbortBroadcast(){ return false; } + public final int getResultCode(){ return 0; } + public final void abortBroadcast(){} + public final void clearAbortBroadcast(){} + public final void finish(){} + public final void setResult(int p0, String p1, Bundle p2){} + public final void setResultCode(int p0){} + public final void setResultData(String p0){} + public final void setResultExtras(Bundle p0){} } - /** - * This method is called when the BroadcastReceiver is receiving an Intent - * broadcast. During this time you can use the other methods on - * BroadcastReceiver to view/modify the current result values. This method - * is always called within the main thread of its process, unless you - * explicitly asked for it to be scheduled on a different thread using - * {@link android.content.Context#registerReceiver(BroadcastReceiver, - * IntentFilter, String, android.os.Handler)}. When it runs on the main - * thread you should - * never perform long-running operations in it (there is a timeout of - * 10 seconds that the system allows before considering the receiver to - * be blocked and a candidate to be killed). You cannot launch a popup dialog - * in your implementation of onReceive(). - * - * <p><b>If this BroadcastReceiver was launched through a <receiver> tag, - * then the object is no longer alive after returning from this - * function.</b> This means you should not perform any operations that - * return a result to you asynchronously -- in particular, for interacting - * with services, you should use - * {@link Context#startService(Intent)} instead of - * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish - * to interact with a service that is already running, you can use - * {@link #peekService}. - * - * <p>The Intent filters used in {@link android.content.Context#registerReceiver} - * and in application manifests are <em>not</em> guaranteed to be exclusive. They - * are hints to the operating system about how to find suitable recipients. It is - * possible for senders to force delivery to specific recipients, bypassing filter - * resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()} - * implementations should respond only to known actions, ignoring any unexpected - * Intents that they may receive. - * - * @param context The Context in which the receiver is running. - * @param intent The Intent being received. - */ - public abstract void onReceive(Context context, Intent intent); -} \ No newline at end of file +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java index adb50343ca4..2c72a0a5125 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java @@ -1,29 +1,35 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.content.ComponentName for testing purposes + package android.content; -/** - * Identifier for a specific application component - * ({@link android.app.Activity}, {@link android.app.Service}, - * {@link android.content.BroadcastReceiver}, or - * {@link android.content.ContentProvider}) that is available. Two - * pieces of information, encapsulated here, are required to identify - * a component: the package (a String) it exists in, and the class (a String) - * name inside of that package. - * - */ -public final class ComponentName { +import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; + +public class ComponentName implements Cloneable, Comparable<ComponentName>, Parcelable +{ + protected ComponentName() {} + public ComponentName clone(){ return null; } + public ComponentName(Context p0, Class<? extends Object> p1){} + public ComponentName(Context p0, String p1){} + public ComponentName(Parcel p0){} + public ComponentName(String p0, String p1){} + public String flattenToShortString(){ return null; } + public String flattenToString(){ return null; } + public String getClassName(){ return null; } + public String getPackageName(){ return null; } + public String getShortClassName(){ return null; } + public String toShortString(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int compareTo(ComponentName p0){ return 0; } + public int describeContents(){ return 0; } + public int hashCode(){ return 0; } + public static ComponentName createRelative(Context p0, String p1){ return null; } + public static ComponentName createRelative(String p0, String p1){ return null; } + public static ComponentName readFromParcel(Parcel p0){ return null; } + public static ComponentName unflattenFromString(String p0){ return null; } + public static Parcelable.Creator<ComponentName> CREATOR = null; + public static void writeToParcel(ComponentName p0, Parcel p1){} + public void writeToParcel(Parcel p0, int p1){} } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java b/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java index 8ddd1f2c8ef..a857f97e20f 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java @@ -1,1051 +1,255 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.content.Context for testing purposes + package android.content; -import java.io.File; +import android.content.BroadcastReceiver; +import android.content.ComponentCallbacks; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.IntentSender; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.AssetManager; +import android.content.res.ColorStateList; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.database.DatabaseErrorHandler; +import android.database.sqlite.SQLiteDatabase; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.util.AttributeSet; +import android.view.Display; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.concurrent.Executor; -/** - * Interface to global information about an application environment. This is an - * abstract class whose implementation is provided by the Android system. It - * allows access to application-specific resources and classes, as well as - * up-calls for application-level operations such as launching activities, - * broadcasting and receiving intents, etc. - */ -public abstract class Context { - /** - * File creation mode: the default mode, where the created file can only - * be accessed by the calling application (or all applications sharing the - * same user ID). - * @see #MODE_WORLD_READABLE - * @see #MODE_WORLD_WRITEABLE - */ - public static final int MODE_PRIVATE = 0x0000; - - /** - * @deprecated Creating world-readable files is very dangerous, and likely - * to cause security holes in applications. It is strongly discouraged; - * instead, applications should use more formal mechanism for interactions - * such as {@link ContentProvider}, {@link BroadcastReceiver}, and - * {@link android.app.Service}. There are no guarantees that this - * access mode will remain on a file, such as when it goes through a - * backup and restore. - * File creation mode: allow all other applications to have read access - * to the created file. - * @see #MODE_PRIVATE - * @see #MODE_WORLD_WRITEABLE - */ - @Deprecated - public static final int MODE_WORLD_READABLE = 0x0001; - - /** - * @deprecated Creating world-writable files is very dangerous, and likely - * to cause security holes in applications. It is strongly discouraged; - * instead, applications should use more formal mechanism for interactions - * such as {@link ContentProvider}, {@link BroadcastReceiver}, and - * {@link android.app.Service}. There are no guarantees that this - * access mode will remain on a file, such as when it goes through a - * backup and restore. - * File creation mode: allow all other applications to have write access - * to the created file. - * @see #MODE_PRIVATE - * @see #MODE_WORLD_READABLE - */ - @Deprecated - public static final int MODE_WORLD_WRITEABLE = 0x0002; - - /** - * File creation mode: for use with {@link #openFileOutput}, if the file - * already exists then write data to the end of the existing file - * instead of erasing it. - * @see #openFileOutput - */ - public static final int MODE_APPEND = 0x8000; - - /** - * SharedPreference loading flag: when set, the file on disk will - * be checked for modification even if the shared preferences - * instance is already loaded in this process. This behavior is - * sometimes desired in cases where the application has multiple - * processes, all writing to the same SharedPreferences file. - * Generally there are better forms of communication between - * processes, though. - * - * <p>This was the legacy (but undocumented) behavior in and - * before Gingerbread (Android 2.3) and this flag is implied when - * targetting such releases. For applications targetting SDK - * versions <em>greater than</em> Android 2.3, this flag must be - * explicitly set if desired. - * - * @see #getSharedPreferences - */ - public static final int MODE_MULTI_PROCESS = 0x0004; - - /** - * Database open flag: when set, the database is opened with write-ahead - * logging enabled by default. - * - * @see #openOrCreateDatabase(String, int, CursorFactory) - * @see #openOrCreateDatabase(String, int, CursorFactory, DatabaseErrorHandler) - * @see SQLiteDatabase#enableWriteAheadLogging - */ - public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008; - - /** - * Return the context of the single, global Application object of the current - * process. This generally should only be used if you need a Context whose - * lifecycle is separate from the current context, that is tied to the lifetime - * of the process rather than the current component. - * - * <p> - * Consider for example how this interacts with - * {@link #registerReceiver(BroadcastReceiver, IntentFilter)}: - * <ul> - * <li> - * <p> - * If used from an Activity context, the receiver is being registered within - * that activity. This means that you are expected to unregister before the - * activity is done being destroyed; in fact if you do not do so, the framework - * will clean up your leaked registration as it removes the activity and log an - * error. Thus, if you use the Activity context to register a receiver that is - * static (global to the process, not associated with an Activity instance) then - * that registration will be removed on you at whatever point the activity you - * used is destroyed. - * <li> - * <p> - * If used from the Context returned here, the receiver is being registered with - * the global state associated with your application. Thus it will never be - * unregistered for you. This is necessary if the receiver is associated with - * static data, not a particular component. However using the ApplicationContext - * elsewhere can easily lead to serious leaks if you forget to unregister, - * unbind, etc. - * </ul> - */ +abstract public class Context +{ + public Context(){} + public Executor getMainExecutor(){ return null; } + public String getOpPackageName(){ return null; } + public abstract ApplicationInfo getApplicationInfo(); + public abstract AssetManager getAssets(); + public abstract ClassLoader getClassLoader(); + public abstract ComponentName startForegroundService(Intent p0); + public abstract ComponentName startService(Intent p0); + public abstract ContentResolver getContentResolver(); + public abstract Context createConfigurationContext(Configuration p0); + public abstract Context createContextForSplit(String p0); + public abstract Context createDeviceProtectedStorageContext(); + public abstract Context createDisplayContext(Display p0); + public abstract Context createPackageContext(String p0, int p1); public abstract Context getApplicationContext(); - - /** - * Returns the absolute path on the filesystem where a file created with - * {@link #openFileOutput} is stored. - * <p> - * The returned path may change over time if the calling app is moved to an - * adopted storage device, so only relative paths should be persisted. - * - * @param name The name of the file for which you would like to get its path. - * - * @return An absolute path to the given file. - * - * @see #openFileOutput - * @see #getFilesDir - * @see #getDir - */ - public abstract File getFileStreamPath(String name); - - /** - * {@hide} - * Return the full path to the shared prefs file for the given prefs group name. - * - * <p>Note: this is not generally useful for applications, since they should - * not be directly accessing the file system. - */ - public abstract File getSharedPrefsFile(String name); - - /** - * Retrieve and hold the contents of the preferences file 'name', returning - * a SharedPreferences through which you can retrieve and modify its - * values. Only one instance of the SharedPreferences object is returned - * to any callers for the same name, meaning they will see each other's - * edits as soon as they are made. - * - * @param name Desired preferences file. If a preferences file by this name - * does not exist, it will be created when you retrieve an - * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()). - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation, {@link #MODE_WORLD_READABLE} - * and {@link #MODE_WORLD_WRITEABLE} to control permissions. The bit - * {@link #MODE_MULTI_PROCESS} can also be used if multiple processes - * are mutating the same SharedPreferences file. {@link #MODE_MULTI_PROCESS} - * is always on in apps targetting Gingerbread (Android 2.3) and below, and - * off by default in later versions. - * - * @return Returns the single SharedPreferences instance that can be used - * to retrieve and modify the preference values. - * - * @see #MODE_PRIVATE - * @see #MODE_WORLD_READABLE - * @see #MODE_WORLD_WRITEABLE - * @see #MODE_MULTI_PROCESS - */ - public abstract SharedPreferences getSharedPreferences(String name, - int mode); - - /** - * Returns the absolute path to the directory on the filesystem where all - * private files belonging to this app are stored. Apps should not use this path - * directly; they should instead use {@link #getFilesDir()}, - * {@link #getCacheDir()}, {@link #getDir(String, int)}, or other storage APIs - * on this class. - * <p> - * The returned path may change over time if the calling app is moved to an - * adopted storage device, so only relative paths should be persisted. - * <p> - * No additional permissions are required for the calling app to read or write - * files under the returned path. - * - * @see ApplicationInfo#dataDir - */ - public abstract File getDataDir(); - - /** - * Returns the absolute path to the directory on the filesystem where files - * created with {@link #openFileOutput} are stored. - * <p> - * The returned path may change over time if the calling app is moved to an - * adopted storage device, so only relative paths should be persisted. - * <p> - * No additional permissions are required for the calling app to read or write - * files under the returned path. - * - * @return The path of the directory holding application files. - * @see #openFileOutput - * @see #getFileStreamPath - * @see #getDir - */ - public abstract File getFilesDir(); - - /** - * Returns the absolute path to the directory on the filesystem similar to - * {@link #getFilesDir()}. The difference is that files placed under this - * directory will be excluded from automatic backup to remote storage. See - * {@link android.app.backup.BackupAgent BackupAgent} for a full discussion of - * the automatic backup mechanism in Android. - * <p> - * The returned path may change over time if the calling app is moved to an - * adopted storage device, so only relative paths should be persisted. - * <p> - * No additional permissions are required for the calling app to read or write - * files under the returned path. - * - * @return The path of the directory holding application files that will not be - * automatically backed up to remote storage. - * @see #openFileOutput - * @see #getFileStreamPath - * @see #getDir - * @see android.app.backup.BackupAgent - */ - public abstract File getNoBackupFilesDir(); - - /** - * Returns the absolute path to the directory on the primary shared/external - * storage device where the application can place persistent files it owns. - * These files are internal to the applications, and not typically visible to - * the user as media. - * <p> - * This is like {@link #getFilesDir()} in that these files will be deleted when - * the application is uninstalled, however there are some important differences: - * <ul> - * <li>Shared storage may not always be available, since removable media can be - * ejected by the user. Media state can be checked using - * {@link Environment#getExternalStorageState(File)}. - * <li>There is no security enforced with these files. For example, any - * application holding - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to these - * files. - * </ul> - * <p> - * If a shared storage device is emulated (as determined by - * {@link Environment#isExternalStorageEmulated(File)}), it's contents are - * backed by a private user data partition, which means there is little benefit - * to storing data here instead of the private directories returned by - * {@link #getFilesDir()}, etc. - * <p> - * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions are - * required to read or write to the returned path; it's always accessible to the - * calling app. This only applies to paths generated for package name of the - * calling application. To access paths belonging to other packages, - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or - * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required. - * <p> - * On devices with multiple users (as described by {@link UserManager}), each - * user has their own isolated shared storage. Applications only have access to - * the shared storage for the user they're running as. - * <p> - * The returned path may change over time if different shared storage media is - * inserted, so only relative paths should be persisted. - * <p> - * Here is an example of typical code to manipulate a file in an application's - * shared storage: - * </p> - * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java - * private_file} - * <p> - * If you supply a non-null <var>type</var> to this function, the returned file - * will be a path to a sub-directory of the given type. Though these files are - * not automatically scanned by the media scanner, you can explicitly add them - * to the media database with - * {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[], android.media.MediaScannerConnection.OnScanCompletedListener) - * MediaScannerConnection.scanFile}. Note that this is not the same as - * {@link android.os.Environment#getExternalStoragePublicDirectory - * Environment.getExternalStoragePublicDirectory()}, which provides directories - * of media shared by all applications. The directories returned here are owned - * by the application, and their contents will be removed when the application - * is uninstalled. Unlike - * {@link android.os.Environment#getExternalStoragePublicDirectory - * Environment.getExternalStoragePublicDirectory()}, the directory returned here - * will be automatically created for you. - * <p> - * Here is an example of typical code to manipulate a picture in an - * application's shared storage and add it to the media database: - * </p> - * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java - * private_picture} - * - * @param type The type of files directory to return. May be {@code null} for - * the root of the files directory or one of the following constants - * for a subdirectory: - * {@link android.os.Environment#DIRECTORY_MUSIC}, - * {@link android.os.Environment#DIRECTORY_PODCASTS}, - * {@link android.os.Environment#DIRECTORY_RINGTONES}, - * {@link android.os.Environment#DIRECTORY_ALARMS}, - * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS}, - * {@link android.os.Environment#DIRECTORY_PICTURES}, or - * {@link android.os.Environment#DIRECTORY_MOVIES}. - * @return the absolute path to application-specific directory. May return - * {@code null} if shared storage is not currently available. - * @see #getFilesDir - * @see #getExternalFilesDirs(String) - * @see Environment#getExternalStorageState(File) - * @see Environment#isExternalStorageEmulated(File) - * @see Environment#isExternalStorageRemovable(File) - */ - public abstract File getExternalFilesDir(String type); - - /** - * Returns absolute paths to application-specific directories on all - * shared/external storage devices where the application can place persistent - * files it owns. These files are internal to the application, and not typically - * visible to the user as media. - * <p> - * This is like {@link #getFilesDir()} in that these files will be deleted when - * the application is uninstalled, however there are some important differences: - * <ul> - * <li>Shared storage may not always be available, since removable media can be - * ejected by the user. Media state can be checked using - * {@link Environment#getExternalStorageState(File)}. - * <li>There is no security enforced with these files. For example, any - * application holding - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to these - * files. - * </ul> - * <p> - * If a shared storage device is emulated (as determined by - * {@link Environment#isExternalStorageEmulated(File)}), it's contents are - * backed by a private user data partition, which means there is little benefit - * to storing data here instead of the private directories returned by - * {@link #getFilesDir()}, etc. - * <p> - * Shared storage devices returned here are considered a stable part of the - * device, including physical media slots under a protective cover. The returned - * paths do not include transient devices, such as USB flash drives connected to - * handheld devices. - * <p> - * An application may store data on any or all of the returned devices. For - * example, an app may choose to store large files on the device with the most - * available space, as measured by {@link StatFs}. - * <p> - * No additional permissions are required for the calling app to read or write - * files under the returned path. Write access outside of these paths on - * secondary external storage devices is not available. - * <p> - * The returned path may change over time if different shared storage media is - * inserted, so only relative paths should be persisted. - * - * @param type The type of files directory to return. May be {@code null} for - * the root of the files directory or one of the following constants - * for a subdirectory: - * {@link android.os.Environment#DIRECTORY_MUSIC}, - * {@link android.os.Environment#DIRECTORY_PODCASTS}, - * {@link android.os.Environment#DIRECTORY_RINGTONES}, - * {@link android.os.Environment#DIRECTORY_ALARMS}, - * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS}, - * {@link android.os.Environment#DIRECTORY_PICTURES}, or - * {@link android.os.Environment#DIRECTORY_MOVIES}. - * @return the absolute paths to application-specific directories. Some - * individual paths may be {@code null} if that shared storage is not - * currently available. The first path returned is the same as - * {@link #getExternalFilesDir(String)}. - * @see #getExternalFilesDir(String) - * @see Environment#getExternalStorageState(File) - * @see Environment#isExternalStorageEmulated(File) - * @see Environment#isExternalStorageRemovable(File) - */ - public abstract File[] getExternalFilesDirs(String type); - - /** - * Return the primary shared/external storage directory where this application's - * OBB files (if there are any) can be found. Note if the application does not - * have any OBB files, this directory may not exist. - * <p> - * This is like {@link #getFilesDir()} in that these files will be deleted when - * the application is uninstalled, however there are some important differences: - * <ul> - * <li>Shared storage may not always be available, since removable media can be - * ejected by the user. Media state can be checked using - * {@link Environment#getExternalStorageState(File)}. - * <li>There is no security enforced with these files. For example, any - * application holding - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to these - * files. - * </ul> - * <p> - * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions are - * required to read or write to the path that this method returns. However, - * starting from {@link android.os.Build.VERSION_CODES#M}, to read the OBB - * expansion files, you must declare the - * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission in the - * app manifest and ask for permission at runtime as follows: - * </p> - * <p> - * {@code <uses-permission android:name= - * "android.permission.READ_EXTERNAL_STORAGE" - * android:maxSdkVersion="23" />} - * </p> - * <p> - * Starting from {@link android.os.Build.VERSION_CODES#N}, - * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission is not - * required, so don't ask for this permission at runtime. To handle both cases, - * your app must first try to read the OBB file, and if it fails, you must - * request {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission - * at runtime. - * </p> - * - * <p> - * The following code snippet shows how to do this: - * </p> - * - * <pre> - * File obb = new File(obb_filename); - * boolean open_failed = false; - * - * try { - * BufferedReader br = new BufferedReader(new FileReader(obb)); - * open_failed = false; - * ReadObbFile(br); - * } catch (IOException e) { - * open_failed = true; - * } - * - * if (open_failed) { - * // request READ_EXTERNAL_STORAGE permission before reading OBB file - * ReadObbFileWithPermission(); - * } - * </pre> - * - * On devices with multiple users (as described by {@link UserManager}), - * multiple users may share the same OBB storage location. Applications should - * ensure that multiple instances running under different users don't interfere - * with each other. - * - * @return the absolute path to application-specific directory. May return - * {@code null} if shared storage is not currently available. - * @see #getObbDirs() - * @see Environment#getExternalStorageState(File) - * @see Environment#isExternalStorageEmulated(File) - * @see Environment#isExternalStorageRemovable(File) - */ - public abstract File getObbDir(); - - /** - * Returns absolute paths to application-specific directories on all - * shared/external storage devices where the application's OBB files (if there - * are any) can be found. Note if the application does not have any OBB files, - * these directories may not exist. - * <p> - * This is like {@link #getFilesDir()} in that these files will be deleted when - * the application is uninstalled, however there are some important differences: - * <ul> - * <li>Shared storage may not always be available, since removable media can be - * ejected by the user. Media state can be checked using - * {@link Environment#getExternalStorageState(File)}. - * <li>There is no security enforced with these files. For example, any - * application holding - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to these - * files. - * </ul> - * <p> - * Shared storage devices returned here are considered a stable part of the - * device, including physical media slots under a protective cover. The returned - * paths do not include transient devices, such as USB flash drives connected to - * handheld devices. - * <p> - * An application may store data on any or all of the returned devices. For - * example, an app may choose to store large files on the device with the most - * available space, as measured by {@link StatFs}. - * <p> - * No additional permissions are required for the calling app to read or write - * files under the returned path. Write access outside of these paths on - * secondary external storage devices is not available. - * - * @return the absolute paths to application-specific directories. Some - * individual paths may be {@code null} if that shared storage is not - * currently available. The first path returned is the same as - * {@link #getObbDir()} - * @see #getObbDir() - * @see Environment#getExternalStorageState(File) - * @see Environment#isExternalStorageEmulated(File) - * @see Environment#isExternalStorageRemovable(File) - */ - public abstract File[] getObbDirs(); - - /** - * Returns the absolute path to the application specific cache directory on the - * filesystem. - * <p> - * The system will automatically delete files in this directory as disk space is - * needed elsewhere on the device. The system will always delete older files - * first, as reported by {@link File#lastModified()}. If desired, you can exert - * more control over how files are deleted using - * {@link StorageManager#setCacheBehaviorGroup(File, boolean)} and - * {@link StorageManager#setCacheBehaviorTombstone(File, boolean)}. - * <p> - * Apps are strongly encouraged to keep their usage of cache space below the - * quota returned by {@link StorageManager#getCacheQuotaBytes(java.util.UUID)}. - * If your app goes above this quota, your cached files will be some of the - * first to be deleted when additional disk space is needed. Conversely, if your - * app stays under this quota, your cached files will be some of the last to be - * deleted when additional disk space is needed. - * <p> - * Note that your cache quota will change over time depending on how frequently - * the user interacts with your app, and depending on how much system-wide disk - * space is used. - * <p> - * The returned path may change over time if the calling app is moved to an - * adopted storage device, so only relative paths should be persisted. - * <p> - * Apps require no extra permissions to read or write to the returned path, - * since this path lives in their private storage. - * - * @return The path of the directory holding application cache files. - * @see #openFileOutput - * @see #getFileStreamPath - * @see #getDir - * @see #getExternalCacheDir - */ + public abstract Drawable getWallpaper(); + public abstract Drawable peekWallpaper(); public abstract File getCacheDir(); - - /** - * Returns the absolute path to the application specific cache directory on the - * filesystem designed for storing cached code. - * <p> - * The system will delete any files stored in this location both when your - * specific application is upgraded, and when the entire platform is upgraded. - * <p> - * This location is optimal for storing compiled or optimized code generated by - * your application at runtime. - * <p> - * The returned path may change over time if the calling app is moved to an - * adopted storage device, so only relative paths should be persisted. - * <p> - * Apps require no extra permissions to read or write to the returned path, - * since this path lives in their private storage. - * - * @return The path of the directory holding application code cache files. - */ public abstract File getCodeCacheDir(); - - /** - * Returns absolute path to application-specific directory on the primary - * shared/external storage device where the application can place cache files it - * owns. These files are internal to the application, and not typically visible - * to the user as media. - * <p> - * This is like {@link #getCacheDir()} in that these files will be deleted when - * the application is uninstalled, however there are some important differences: - * <ul> - * <li>The platform does not always monitor the space available in shared - * storage, and thus may not automatically delete these files. Apps should - * always manage the maximum space used in this location. Currently the only - * time files here will be deleted by the platform is when running on - * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} or later and - * {@link Environment#isExternalStorageEmulated(File)} returns true. - * <li>Shared storage may not always be available, since removable media can be - * ejected by the user. Media state can be checked using - * {@link Environment#getExternalStorageState(File)}. - * <li>There is no security enforced with these files. For example, any - * application holding - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to these - * files. - * </ul> - * <p> - * If a shared storage device is emulated (as determined by - * {@link Environment#isExternalStorageEmulated(File)}), its contents are backed - * by a private user data partition, which means there is little benefit to - * storing data here instead of the private directory returned by - * {@link #getCacheDir()}. - * <p> - * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions are - * required to read or write to the returned path; it's always accessible to the - * calling app. This only applies to paths generated for package name of the - * calling application. To access paths belonging to other packages, - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or - * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required. - * <p> - * On devices with multiple users (as described by {@link UserManager}), each - * user has their own isolated shared storage. Applications only have access to - * the shared storage for the user they're running as. - * <p> - * The returned path may change over time if different shared storage media is - * inserted, so only relative paths should be persisted. - * - * @return the absolute path to application-specific directory. May return - * {@code null} if shared storage is not currently available. - * @see #getCacheDir - * @see #getExternalCacheDirs() - * @see Environment#getExternalStorageState(File) - * @see Environment#isExternalStorageEmulated(File) - * @see Environment#isExternalStorageRemovable(File) - */ + public abstract File getDataDir(); + public abstract File getDatabasePath(String p0); + public abstract File getDir(String p0, int p1); public abstract File getExternalCacheDir(); - - /** - * Returns absolute path to application-specific directory in the preloaded - * cache. - * <p> - * Files stored in the cache directory can be deleted when the device runs low - * on storage. There is no guarantee when these files will be deleted. - * - * @hide - */ - public abstract File getPreloadsFileCache(); - - /** - * Returns absolute paths to application-specific directories on all - * shared/external storage devices where the application can place cache files - * it owns. These files are internal to the application, and not typically - * visible to the user as media. - * <p> - * This is like {@link #getCacheDir()} in that these files will be deleted when - * the application is uninstalled, however there are some important differences: - * <ul> - * <li>The platform does not always monitor the space available in shared - * storage, and thus may not automatically delete these files. Apps should - * always manage the maximum space used in this location. Currently the only - * time files here will be deleted by the platform is when running on - * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} or later and - * {@link Environment#isExternalStorageEmulated(File)} returns true. - * <li>Shared storage may not always be available, since removable media can be - * ejected by the user. Media state can be checked using - * {@link Environment#getExternalStorageState(File)}. - * <li>There is no security enforced with these files. For example, any - * application holding - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to these - * files. - * </ul> - * <p> - * If a shared storage device is emulated (as determined by - * {@link Environment#isExternalStorageEmulated(File)}), it's contents are - * backed by a private user data partition, which means there is little benefit - * to storing data here instead of the private directory returned by - * {@link #getCacheDir()}. - * <p> - * Shared storage devices returned here are considered a stable part of the - * device, including physical media slots under a protective cover. The returned - * paths do not include transient devices, such as USB flash drives connected to - * handheld devices. - * <p> - * An application may store data on any or all of the returned devices. For - * example, an app may choose to store large files on the device with the most - * available space, as measured by {@link StatFs}. - * <p> - * No additional permissions are required for the calling app to read or write - * files under the returned path. Write access outside of these paths on - * secondary external storage devices is not available. - * <p> - * The returned paths may change over time if different shared storage media is - * inserted, so only relative paths should be persisted. - * - * @return the absolute paths to application-specific directories. Some - * individual paths may be {@code null} if that shared storage is not - * currently available. The first path returned is the same as - * {@link #getExternalCacheDir()}. - * @see #getExternalCacheDir() - * @see Environment#getExternalStorageState(File) - * @see Environment#isExternalStorageEmulated(File) - * @see Environment#isExternalStorageRemovable(File) - */ + public abstract File getExternalFilesDir(String p0); + public abstract File getFileStreamPath(String p0); + public abstract File getFilesDir(); + public abstract File getNoBackupFilesDir(); + public abstract File getObbDir(); + public abstract FileInputStream openFileInput(String p0); + public abstract FileOutputStream openFileOutput(String p0, int p1); public abstract File[] getExternalCacheDirs(); - - /** - * Returns absolute paths to application-specific directories on all - * shared/external storage devices where the application can place media files. - * These files are scanned and made available to other apps through - * {@link MediaStore}. - * <p> - * This is like {@link #getExternalFilesDirs} in that these files will be - * deleted when the application is uninstalled, however there are some important - * differences: - * <ul> - * <li>Shared storage may not always be available, since removable media can be - * ejected by the user. Media state can be checked using - * {@link Environment#getExternalStorageState(File)}. - * <li>There is no security enforced with these files. For example, any - * application holding - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to these - * files. - * </ul> - * <p> - * Shared storage devices returned here are considered a stable part of the - * device, including physical media slots under a protective cover. The returned - * paths do not include transient devices, such as USB flash drives connected to - * handheld devices. - * <p> - * An application may store data on any or all of the returned devices. For - * example, an app may choose to store large files on the device with the most - * available space, as measured by {@link StatFs}. - * <p> - * No additional permissions are required for the calling app to read or write - * files under the returned path. Write access outside of these paths on - * secondary external storage devices is not available. - * <p> - * The returned paths may change over time if different shared storage media is - * inserted, so only relative paths should be persisted. - * - * @return the absolute paths to application-specific directories. Some - * individual paths may be {@code null} if that shared storage is not - * currently available. - * @see Environment#getExternalStorageState(File) - * @see Environment#isExternalStorageEmulated(File) - * @see Environment#isExternalStorageRemovable(File) - */ + public abstract File[] getExternalFilesDirs(String p0); public abstract File[] getExternalMediaDirs(); - - /** - * Returns an array of strings naming the private files associated with this - * Context's application package. - * - * @return Array of strings naming the private files. - * - * @see #openFileInput - * @see #openFileOutput - * @see #deleteFile - */ + public abstract File[] getObbDirs(); + public abstract Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1); + public abstract Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, String p2, Handler p3); + public abstract Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, String p2, Handler p3, int p4); + public abstract Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, int p2); + public abstract Looper getMainLooper(); + public abstract Object getSystemService(String p0); + public abstract PackageManager getPackageManager(); + public abstract Resources getResources(); + public abstract Resources.Theme getTheme(); + public abstract SQLiteDatabase openOrCreateDatabase(String p0, int p1, SQLiteDatabase.CursorFactory p2); + public abstract SQLiteDatabase openOrCreateDatabase(String p0, int p1, SQLiteDatabase.CursorFactory p2, DatabaseErrorHandler p3); + public abstract SharedPreferences getSharedPreferences(String p0, int p1); + public abstract String getPackageCodePath(); + public abstract String getPackageName(); + public abstract String getPackageResourcePath(); + public abstract String getSystemServiceName(Class<? extends Object> p0); + public abstract String[] databaseList(); public abstract String[] fileList(); - - /** - * Retrieve, creating if needed, a new directory in which the application can - * place its own custom data files. You can use the returned File object to - * create and access files in this directory. Note that files created through a - * File object will only be accessible by your own application; you can only set - * the mode of the entire directory, not of individual files. - * <p> - * The returned path may change over time if the calling app is moved to an - * adopted storage device, so only relative paths should be persisted. - * <p> - * Apps require no extra permissions to read or write to the returned path, - * since this path lives in their private storage. - * - * @param name Name of the directory to retrieve. This is a directory that is - * created as part of your application data. - * @param mode Operating mode. - * - * @return A {@link File} object for the requested directory. The directory will - * have been created if it does not already exist. - * - * @see #openFileOutput(String, int) - */ - public abstract File getDir(String name, int mode); - - /** - * Same as {@link #startActivity(Intent, Bundle)} with no options specified. - * - * @param intent The description of the activity to start. - * - * @throws ActivityNotFoundException   ` - * @see #startActivity(Intent, Bundle) - * @see PackageManager#resolveActivity - */ - public abstract void startActivity(Intent intent); - - /** - * Launch a new activity. You will not receive any information about when the - * activity exits. - * - * <p> - * Note that if this method is being called from outside of an - * {@link android.app.Activity} Context, then the Intent must include the - * {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag. This is because, without - * being started from an existing Activity, there is no existing task in which - * to place the new activity and thus it needs to be placed in its own separate - * task. - * - * <p> - * This method throws {@link ActivityNotFoundException} if there was no Activity - * found to run the given Intent. - * - * @param intent The description of the activity to start. - * @param options Additional options for how the Activity should be started. May - * be null if there are no options. See - * {@link android.app.ActivityOptions} for how to build the - * Bundle supplied here; there are no supported definitions for - * building it manually. - * - * @throws ActivityNotFoundException   - * - * @see #startActivity(Intent) - * @see PackageManager#resolveActivity - */ - public abstract void startActivity(Intent intent, Bundle options); - - /** - * Identifies whether this Context instance will be able to process calls to - * {@link #startActivityForResult(String, Intent, int, Bundle)}. - * - * @hide - */ - public boolean canStartActivityForResult() { - return false; - } - - /** - * Same as {@link #startActivities(Intent[], Bundle)} with no options specified. - * - * @param intents An array of Intents to be started. - * - * @throws ActivityNotFoundException   - * - * @see #startActivities(Intent[], Bundle) - * @see PackageManager#resolveActivity - */ - public abstract void startActivities(Intent[] intents); - - /** - * Launch multiple new activities. This is generally the same as calling - * {@link #startActivity(Intent)} for the first Intent in the array, that - * activity during its creation calling {@link #startActivity(Intent)} for the - * second entry, etc. Note that unlike that approach, generally none of the - * activities except the last in the array will be created at this point, but - * rather will be created when the user first visits them (due to pressing back - * from the activity on top). - * - * <p> - * This method throws {@link ActivityNotFoundException} if there was no Activity - * found for <em>any</em> given Intent. In this case the state of the activity - * stack is undefined (some Intents in the list may be on it, some not), so you - * probably want to avoid such situations. - * - * @param intents An array of Intents to be started. - * @param options Additional options for how the Activity should be started. See - * {@link android.content.Context#startActivity(Intent, Bundle)} - * Context.startActivity(Intent, Bundle)} for more details. - * - * @throws ActivityNotFoundException   - * - * @see #startActivities(Intent[]) - * @see PackageManager#resolveActivity - */ - public abstract void startActivities(Intent[] intents, Bundle options); - - /** - * Broadcast the given intent to all interested BroadcastReceivers. This call is - * asynchronous; it returns immediately, and you will continue executing while - * the receivers are run. No results are propagated from receivers and receivers - * can not abort the broadcast. If you want to allow receivers to propagate - * results or abort the broadcast, you must send an ordered broadcast using - * {@link #sendOrderedBroadcast(Intent, String)}. - * - * <p> - * See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param intent The Intent to broadcast; all receivers matching this Intent - * will receive the broadcast. - * - * @see android.content.BroadcastReceiver - * @see #registerReceiver - * @see #sendBroadcast(Intent, String) - * @see #sendOrderedBroadcast(Intent, String) - * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, - * String, Bundle) - */ - public abstract void sendBroadcast(Intent intent); - - /** - * Broadcast the given intent to all interested BroadcastReceivers, allowing an - * optional required permission to be enforced. This call is asynchronous; it - * returns immediately, and you will continue executing while the receivers are - * run. No results are propagated from receivers and receivers can not abort the - * broadcast. If you want to allow receivers to propagate results or abort the - * broadcast, you must send an ordered broadcast using - * {@link #sendOrderedBroadcast(Intent, String)}. - * - * <p> - * See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param intent The Intent to broadcast; all receivers matching - * this Intent will receive the broadcast. - * @param receiverPermission (optional) String naming a permission that a - * receiver must hold in order to receive your - * broadcast. If null, no permission is required. - * - * @see android.content.BroadcastReceiver - * @see #registerReceiver - * @see #sendBroadcast(Intent) - * @see #sendOrderedBroadcast(Intent, String) - * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, - * String, Bundle) - */ - public abstract void sendBroadcast(Intent intent, String receiverPermission); - - /** - * Like {@link #sendBroadcast(Intent, String)}, but also allows specification of - * an associated app op as per {@link android.app.AppOpsManager}. - * - * @hide - */ - public abstract void sendBroadcast(Intent intent, String receiverPermission, int appOp); - - /** - * Broadcast the given intent to all interested BroadcastReceivers, allowing - * an array of required permissions to be enforced. This call is asynchronous; it returns - * immediately, and you will continue executing while the receivers are run. No results are - * propagated from receivers and receivers can not abort the broadcast. If you want to allow - * receivers to propagate results or abort the broadcast, you must send an ordered broadcast - * using {@link #sendOrderedBroadcast(Intent, String)}. - * - * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param intent The Intent to broadcast; all receivers matching this - * Intent will receive the broadcast. - * @param receiverPermissions Array of names of permissions that a receiver must hold - * in order to receive your broadcast. - * If empty, no permissions are required. - * - * @see android.content.BroadcastReceiver - * @see #registerReceiver - * @see #sendBroadcast(Intent) - * @see #sendOrderedBroadcast(Intent, String) - * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) - * @hide - */ - public abstract void sendBroadcastWithMultiplePermissions (Intent intent, String[] receiverPermissions); - - /** - * Broadcast the given intent to all interested BroadcastReceivers, delivering - * them one at a time to allow more preferred receivers to consume the - * broadcast before it is delivered to less preferred receivers. This - * call is asynchronous; it returns immediately, and you will continue - * executing while the receivers are run. - * - * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param intent The Intent to broadcast; all receivers matching this - * Intent will receive the broadcast. - * @param receiverPermission (optional) String naming a permissions that - * a receiver must hold in order to receive your broadcast. - * If null, no permission is required. - * - * @see android.content.BroadcastReceiver - * @see #registerReceiver - * @see #sendBroadcast(Intent) - * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) - */ - public abstract void sendOrderedBroadcast(Intent intent, String receiverPermission); - - /** - * Request that a given application service be started. The Intent - * should either contain the complete class name of a specific service - * implementation to start, or a specific package name to target. If the - * Intent is less specified, it logs a warning about this. In this case any of the - * multiple matching services may be used. If this service - * is not already running, it will be instantiated and started (creating a - * process for it if needed); if it is running then it remains running. - * - * <p>Every call to this method will result in a corresponding call to - * the target service's {@link android.app.Service#onStartCommand} method, - * with the <var>intent</var> given here. This provides a convenient way - * to submit jobs to a service without having to bind and call on to its - * interface. - * - * <p>Using startService() overrides the default service lifetime that is - * managed by {@link #bindService}: it requires the service to remain - * running until {@link #stopService} is called, regardless of whether - * any clients are connected to it. Note that calls to startService() - * do not nest: no matter how many times you call startService(), - * a single call to {@link #stopService} will stop it. - * - * <p>The system attempts to keep running services around as much as - * possible. The only time they should be stopped is if the current - * foreground application is using so many resources that the service needs - * to be killed. If any errors happen in the service's process, it will - * automatically be restarted. - * - * <p>This function will throw {@link SecurityException} if you do not - * have permission to start the given service. - * - * <p class="note"><strong>Note:</strong> Each call to startService() - * results in significant work done by the system to manage service - * lifecycle surrounding the processing of the intent, which can take - * multiple milliseconds of CPU time. Due to this cost, startService() - * should not be used for frequent intent delivery to a service, and only - * for scheduling significant work. Use {@link #bindService bound services} - * for high frequency calls. - * </p> - * - * @param service Identifies the service to be started. The Intent must be - * fully explicit (supplying a component name). Additional values - * may be included in the Intent extras to supply arguments along with - * this specific start call. - * - * @return If the service is being started or is already running, the - * {@link ComponentName} of the actual service that was started is - * returned; else if the service does not exist null is returned. - * - * @throws SecurityException If the caller does not have permission to access the service - * or the service can not be found. - * @throws IllegalStateException If the application is in a state where the service - * can not be started (such as not in the foreground in a state when services are allowed). - * - * @see #stopService - * @see #bindService - */ - public abstract ComponentName startService(Intent service); - - /** - * Similar to {@link #startService(Intent)}, but with an implicit promise that the - * Service will call {@link android.app.Service#startForeground(int, android.app.Notification) - * startForeground(int, android.app.Notification)} once it begins running. The service is given - * an amount of time comparable to the ANR interval to do this, otherwise the system - * will automatically stop the service and declare the app ANR. - * - * <p>Unlike the ordinary {@link #startService(Intent)}, this method can be used - * at any time, regardless of whether the app hosting the service is in a foreground - * state. - * - * @param service Identifies the service to be started. The Intent must be - * fully explicit (supplying a component name). Additional values - * may be included in the Intent extras to supply arguments along with - * this specific start call. - * - * @return If the service is being started or is already running, the - * {@link ComponentName} of the actual service that was started is - * returned; else if the service does not exist null is returned. - * - * @throws SecurityException If the caller does not have permission to access the service - * or the service can not be found. - * - * @see #stopService - * @see android.app.Service#startForeground(int, android.app.Notification) - */ - public abstract ComponentName startForegroundService(Intent service); + public abstract boolean bindService(Intent p0, ServiceConnection p1, int p2); + public abstract boolean deleteDatabase(String p0); + public abstract boolean deleteFile(String p0); + public abstract boolean deleteSharedPreferences(String p0); + public abstract boolean isDeviceProtectedStorage(); + public abstract boolean moveDatabaseFrom(Context p0, String p1); + public abstract boolean moveSharedPreferencesFrom(Context p0, String p1); + public abstract boolean startInstrumentation(ComponentName p0, String p1, Bundle p2); + public abstract boolean stopService(Intent p0); + public abstract int checkCallingOrSelfPermission(String p0); + public abstract int checkCallingOrSelfUriPermission(Uri p0, int p1); + public abstract int checkCallingPermission(String p0); + public abstract int checkCallingUriPermission(Uri p0, int p1); + public abstract int checkPermission(String p0, int p1, int p2); + public abstract int checkSelfPermission(String p0); + public abstract int checkUriPermission(Uri p0, String p1, String p2, int p3, int p4, int p5); + public abstract int checkUriPermission(Uri p0, int p1, int p2, int p3); + public abstract int getWallpaperDesiredMinimumHeight(); + public abstract int getWallpaperDesiredMinimumWidth(); + public abstract void clearWallpaper(); + public abstract void enforceCallingOrSelfPermission(String p0, String p1); + public abstract void enforceCallingOrSelfUriPermission(Uri p0, int p1, String p2); + public abstract void enforceCallingPermission(String p0, String p1); + public abstract void enforceCallingUriPermission(Uri p0, int p1, String p2); + public abstract void enforcePermission(String p0, int p1, int p2, String p3); + public abstract void enforceUriPermission(Uri p0, String p1, String p2, int p3, int p4, int p5, String p6); + public abstract void enforceUriPermission(Uri p0, int p1, int p2, int p3, String p4); + public abstract void grantUriPermission(String p0, Uri p1, int p2); + public abstract void removeStickyBroadcast(Intent p0); + public abstract void removeStickyBroadcastAsUser(Intent p0, UserHandle p1); + public abstract void revokeUriPermission(String p0, Uri p1, int p2); + public abstract void revokeUriPermission(Uri p0, int p1); + public abstract void sendBroadcast(Intent p0); + public abstract void sendBroadcast(Intent p0, String p1); + public abstract void sendBroadcastAsUser(Intent p0, UserHandle p1); + public abstract void sendBroadcastAsUser(Intent p0, UserHandle p1, String p2); + // Slight cheat: this is an Android 11 function which shouldn't really be present in this Android 9 stub. + public abstract void sendBroadcastWithMultiplePermissions(Intent p1, String[] p2); + public abstract void sendOrderedBroadcast(Intent p0, String p1); + public abstract void sendOrderedBroadcast(Intent p0, String p1, BroadcastReceiver p2, Handler p3, int p4, String p5, Bundle p6); + public abstract void sendOrderedBroadcastAsUser(Intent p0, UserHandle p1, String p2, BroadcastReceiver p3, Handler p4, int p5, String p6, Bundle p7); + public abstract void sendStickyBroadcast(Intent p0); + public abstract void sendStickyBroadcastAsUser(Intent p0, UserHandle p1); + public abstract void sendStickyOrderedBroadcast(Intent p0, BroadcastReceiver p1, Handler p2, int p3, String p4, Bundle p5); + public abstract void sendStickyOrderedBroadcastAsUser(Intent p0, UserHandle p1, BroadcastReceiver p2, Handler p3, int p4, String p5, Bundle p6); + public abstract void setTheme(int p0); + public abstract void setWallpaper(Bitmap p0); + public abstract void setWallpaper(InputStream p0); + public abstract void startActivities(Intent[] p0); + public abstract void startActivities(Intent[] p0, Bundle p1); + public abstract void startActivity(Intent p0); + public abstract void startActivity(Intent p0, Bundle p1); + public abstract void startIntentSender(IntentSender p0, Intent p1, int p2, int p3, int p4); + public abstract void startIntentSender(IntentSender p0, Intent p1, int p2, int p3, int p4, Bundle p5); + public abstract void unbindService(ServiceConnection p0); + public abstract void unregisterReceiver(BroadcastReceiver p0); + public boolean bindIsolatedService(Intent p0, int p1, String p2, Executor p3, ServiceConnection p4){ return false; } + public boolean bindService(Intent p0, int p1, Executor p2, ServiceConnection p3){ return false; } + public boolean isRestricted(){ return false; } + public final <T> T getSystemService(Class<T> p0){ return null; } + public final CharSequence getText(int p0){ return null; } + public final ColorStateList getColorStateList(int p0){ return null; } + public final Drawable getDrawable(int p0){ return null; } + public final String getString(int p0){ return null; } + public final String getString(int p0, Object... p1){ return null; } + public final TypedArray obtainStyledAttributes(AttributeSet p0, int[] p1){ return null; } + public final TypedArray obtainStyledAttributes(AttributeSet p0, int[] p1, int p2, int p3){ return null; } + public final TypedArray obtainStyledAttributes(int p0, int[] p1){ return null; } + public final TypedArray obtainStyledAttributes(int[] p0){ return null; } + public final int getColor(int p0){ return 0; } + public static String ACCESSIBILITY_SERVICE = null; + public static String ACCOUNT_SERVICE = null; + public static String ACTIVITY_SERVICE = null; + public static String ALARM_SERVICE = null; + public static String APPWIDGET_SERVICE = null; + public static String APP_OPS_SERVICE = null; + public static String AUDIO_SERVICE = null; + public static String BATTERY_SERVICE = null; + public static String BIOMETRIC_SERVICE = null; + public static String BLUETOOTH_SERVICE = null; + public static String CAMERA_SERVICE = null; + public static String CAPTIONING_SERVICE = null; + public static String CARRIER_CONFIG_SERVICE = null; + public static String CLIPBOARD_SERVICE = null; + public static String COMPANION_DEVICE_SERVICE = null; + public static String CONNECTIVITY_SERVICE = null; + public static String CONSUMER_IR_SERVICE = null; + public static String CROSS_PROFILE_APPS_SERVICE = null; + public static String DEVICE_POLICY_SERVICE = null; + public static String DISPLAY_SERVICE = null; + public static String DOWNLOAD_SERVICE = null; + public static String DROPBOX_SERVICE = null; + public static String EUICC_SERVICE = null; + public static String FINGERPRINT_SERVICE = null; + public static String HARDWARE_PROPERTIES_SERVICE = null; + public static String INPUT_METHOD_SERVICE = null; + public static String INPUT_SERVICE = null; + public static String IPSEC_SERVICE = null; + public static String JOB_SCHEDULER_SERVICE = null; + public static String KEYGUARD_SERVICE = null; + public static String LAUNCHER_APPS_SERVICE = null; + public static String LAYOUT_INFLATER_SERVICE = null; + public static String LOCATION_SERVICE = null; + public static String MEDIA_PROJECTION_SERVICE = null; + public static String MEDIA_ROUTER_SERVICE = null; + public static String MEDIA_SESSION_SERVICE = null; + public static String MIDI_SERVICE = null; + public static String NETWORK_STATS_SERVICE = null; + public static String NFC_SERVICE = null; + public static String NOTIFICATION_SERVICE = null; + public static String NSD_SERVICE = null; + public static String POWER_SERVICE = null; + public static String PRINT_SERVICE = null; + public static String RESTRICTIONS_SERVICE = null; + public static String ROLE_SERVICE = null; + public static String SEARCH_SERVICE = null; + public static String SENSOR_SERVICE = null; + public static String SHORTCUT_SERVICE = null; + public static String STORAGE_SERVICE = null; + public static String STORAGE_STATS_SERVICE = null; + public static String SYSTEM_HEALTH_SERVICE = null; + public static String TELECOM_SERVICE = null; + public static String TELEPHONY_SERVICE = null; + public static String TELEPHONY_SUBSCRIPTION_SERVICE = null; + public static String TEXT_CLASSIFICATION_SERVICE = null; + public static String TEXT_SERVICES_MANAGER_SERVICE = null; + public static String TV_INPUT_SERVICE = null; + public static String UI_MODE_SERVICE = null; + public static String USAGE_STATS_SERVICE = null; + public static String USB_SERVICE = null; + public static String USER_SERVICE = null; + public static String VIBRATOR_SERVICE = null; + public static String WALLPAPER_SERVICE = null; + public static String WIFI_AWARE_SERVICE = null; + public static String WIFI_P2P_SERVICE = null; + public static String WIFI_RTT_RANGING_SERVICE = null; + public static String WIFI_SERVICE = null; + public static String WINDOW_SERVICE = null; + public static int BIND_ABOVE_CLIENT = 0; + public static int BIND_ADJUST_WITH_ACTIVITY = 0; + public static int BIND_ALLOW_OOM_MANAGEMENT = 0; + public static int BIND_AUTO_CREATE = 0; + public static int BIND_DEBUG_UNBIND = 0; + public static int BIND_EXTERNAL_SERVICE = 0; + public static int BIND_IMPORTANT = 0; + public static int BIND_INCLUDE_CAPABILITIES = 0; + public static int BIND_NOT_FOREGROUND = 0; + public static int BIND_NOT_PERCEPTIBLE = 0; + public static int BIND_WAIVE_PRIORITY = 0; + public static int CONTEXT_IGNORE_SECURITY = 0; + public static int CONTEXT_INCLUDE_CODE = 0; + public static int CONTEXT_RESTRICTED = 0; + public static int MODE_APPEND = 0; + public static int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0; + public static int MODE_MULTI_PROCESS = 0; + public static int MODE_NO_LOCALIZED_COLLATORS = 0; + public static int MODE_PRIVATE = 0; + public static int MODE_WORLD_READABLE = 0; + public static int MODE_WORLD_WRITEABLE = 0; + public static int RECEIVER_VISIBLE_TO_INSTANT_APPS = 0; + public void registerComponentCallbacks(ComponentCallbacks p0){} + public void unregisterComponentCallbacks(ComponentCallbacks p0){} + public void updateServiceGroup(ServiceConnection p0, int p1, int p2){} } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java b/java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java index d3e23384cbd..bffda8f1956 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java @@ -15,8 +15,38 @@ */ package android.content; -import java.io.File; +import android.content.BroadcastReceiver; +import android.content.ComponentCallbacks; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.IntentSender; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.AssetManager; +import android.content.res.ColorStateList; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.database.DatabaseErrorHandler; +import android.database.sqlite.SQLiteDatabase; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.util.AttributeSet; +import android.view.Display; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.concurrent.Executor; /** * Proxying implementation of Context that simply delegates all of its calls to @@ -29,106 +59,6 @@ public class ContextWrapper extends Context { public ContextWrapper(Context base) { } - - @Override - public Context getApplicationContext() { - return null; - } - - @Override - public File getFileStreamPath(String name) { - return null; - } - - @Override - public SharedPreferences getSharedPreferences(String name, int mode) { - return null; - } - - @Override - public File getSharedPrefsFile(String name) { - return null; - } - - @Override - public String[] fileList() { - return null; - } - - @Override - public File getDataDir() { - return null; - } - - @Override - public File getFilesDir() { - return null; - } - - @Override - public File getNoBackupFilesDir() { - return null; - } - - @Override - public File getExternalFilesDir(String type) { - return null; - } - - @Override - public File[] getExternalFilesDirs(String type) { - return null; - } - - @Override - public File getObbDir() { - return null; - } - - @Override - public File[] getObbDirs() { - return null; - } - - @Override - public File getCacheDir() { - return null; - } - - @Override - public File getCodeCacheDir() { - return null; - } - - @Override - public File getExternalCacheDir() { - return null; - } - - @Override - public File[] getExternalCacheDirs() { - return null; - } - - @Override - public File[] getExternalMediaDirs() { - return null; - } - - @Override - public File getDir(String name, int mode) { - return null; - } - - /** @hide **/ - @Override - public File getPreloadsFileCache() { - return null; - } - - @Override - public void startActivity(Intent intent) { - } /** @hide **/ public void startActivityForResult( @@ -139,48 +69,110 @@ public class ContextWrapper extends Context { public boolean canStartActivityForResult() { return false; } - @Override - public void startActivity(Intent intent, Bundle options) { - } - - @Override - public void startActivities(Intent[] intents) { - } - - @Override - public void startActivities(Intent[] intents, Bundle options) { - } - - @Override - public void sendBroadcast(Intent intent) { - } - - @Override - public void sendBroadcast(Intent intent, String receiverPermission) { - } - - @Override - public void sendBroadcastWithMultiplePermissions(Intent intent, String[] receiverPermissions) { - } - - /** @hide */ - @Override - public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { - } - - @Override - public void sendOrderedBroadcast(Intent intent, - String receiverPermission) { - } - - @Override - public ComponentName startService(Intent service) { - return null; - } - - @Override - public ComponentName startForegroundService(Intent service) { - return null; - } + @Override public ApplicationInfo getApplicationInfo() { return null; } + @Override public AssetManager getAssets() { return null; } + @Override public ClassLoader getClassLoader() { return null; } + @Override public ComponentName startForegroundService(Intent p0) { return null; } + @Override public ComponentName startService(Intent p0) { return null; } + @Override public ContentResolver getContentResolver() { return null; } + @Override public Context createConfigurationContext(Configuration p0) { return null; } + @Override public Context createContextForSplit(String p0) { return null; } + @Override public Context createDeviceProtectedStorageContext() { return null; } + @Override public Context createDisplayContext(Display p0) { return null; } + @Override public Context createPackageContext(String p0, int p1) { return null; } + @Override public Context getApplicationContext() { return null; } + @Override public Drawable getWallpaper() { return null; } + @Override public Drawable peekWallpaper() { return null; } + @Override public File getCacheDir() { return null; } + @Override public File getCodeCacheDir() { return null; } + @Override public File getDataDir() { return null; } + @Override public File getDatabasePath(String p0) { return null; } + @Override public File getDir(String p0, int p1) { return null; } + @Override public File getExternalCacheDir() { return null; } + @Override public File getExternalFilesDir(String p0) { return null; } + @Override public File getFileStreamPath(String p0) { return null; } + @Override public File getFilesDir() { return null; } + @Override public File getNoBackupFilesDir() { return null; } + @Override public File getObbDir() { return null; } + @Override public FileInputStream openFileInput(String p0) { return null; } + @Override public FileOutputStream openFileOutput(String p0, int p1) { return null; } + @Override public File[] getExternalCacheDirs() { return null; } + @Override public File[] getExternalFilesDirs(String p0) { return null; } + @Override public File[] getExternalMediaDirs() { return null; } + @Override public File[] getObbDirs() { return null; } + @Override public Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1) { return null; } + @Override public Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, String p2, Handler p3) { return null; } + @Override public Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, String p2, Handler p3, int p4) { return null; } + @Override public Intent registerReceiver(BroadcastReceiver p0, IntentFilter p1, int p2) { return null; } + @Override public Looper getMainLooper() { return null; } + @Override public Object getSystemService(String p0) { return null; } + @Override public PackageManager getPackageManager() { return null; } + @Override public Resources getResources() { return null; } + @Override public Resources.Theme getTheme() { return null; } + @Override public SQLiteDatabase openOrCreateDatabase(String p0, int p1, SQLiteDatabase.CursorFactory p2) { return null; } + @Override public SQLiteDatabase openOrCreateDatabase(String p0, int p1, SQLiteDatabase.CursorFactory p2, DatabaseErrorHandler p3) { return null; } + @Override public SharedPreferences getSharedPreferences(String p0, int p1) { return null; } + @Override public String getPackageCodePath() { return null; } + @Override public String getPackageName() { return null; } + @Override public String getPackageResourcePath() { return null; } + @Override public String getSystemServiceName(Class<? extends Object> p0) { return null; } + @Override public String[] databaseList() { return null; } + @Override public String[] fileList() { return null; } + @Override public boolean bindService(Intent p0, ServiceConnection p1, int p2) { return false; } + @Override public boolean deleteDatabase(String p0) { return false; } + @Override public boolean deleteFile(String p0) { return false; } + @Override public boolean deleteSharedPreferences(String p0) { return false; } + @Override public boolean isDeviceProtectedStorage() { return false; } + @Override public boolean moveDatabaseFrom(Context p0, String p1) { return false; } + @Override public boolean moveSharedPreferencesFrom(Context p0, String p1) { return false; } + @Override public boolean startInstrumentation(ComponentName p0, String p1, Bundle p2) { return false; } + @Override public boolean stopService(Intent p0) { return false; } + @Override public int checkCallingOrSelfPermission(String p0) { return 0; } + @Override public int checkCallingOrSelfUriPermission(Uri p0, int p1) { return 0; } + @Override public int checkCallingPermission(String p0) { return 0; } + @Override public int checkCallingUriPermission(Uri p0, int p1) { return 0; } + @Override public int checkPermission(String p0, int p1, int p2) { return 0; } + @Override public int checkSelfPermission(String p0) { return 0; } + @Override public int checkUriPermission(Uri p0, String p1, String p2, int p3, int p4, int p5) { return 0; } + @Override public int checkUriPermission(Uri p0, int p1, int p2, int p3) { return 0; } + @Override public int getWallpaperDesiredMinimumHeight() { return 0; } + @Override public int getWallpaperDesiredMinimumWidth() { return 0; } + @Override public void clearWallpaper() { } + @Override public void enforceCallingOrSelfPermission(String p0, String p1) { } + @Override public void enforceCallingOrSelfUriPermission(Uri p0, int p1, String p2) { } + @Override public void enforceCallingPermission(String p0, String p1) { } + @Override public void enforceCallingUriPermission(Uri p0, int p1, String p2) { } + @Override public void enforcePermission(String p0, int p1, int p2, String p3) { } + @Override public void enforceUriPermission(Uri p0, String p1, String p2, int p3, int p4, int p5, String p6) { } + @Override public void enforceUriPermission(Uri p0, int p1, int p2, int p3, String p4) { } + @Override public void grantUriPermission(String p0, Uri p1, int p2) { } + @Override public void removeStickyBroadcast(Intent p0) { } + @Override public void removeStickyBroadcastAsUser(Intent p0, UserHandle p1) { } + @Override public void revokeUriPermission(String p0, Uri p1, int p2) { } + @Override public void revokeUriPermission(Uri p0, int p1) { } + @Override public void sendBroadcast(Intent p0) { } + @Override public void sendBroadcast(Intent p0, String p1) { } + @Override public void sendBroadcastAsUser(Intent p0, UserHandle p1) { } + @Override public void sendBroadcastAsUser(Intent p0, UserHandle p1, String p2) { } + // Slight cheat: this is an Android 11 function which shouldn't really be present in this Android 9 stub. + @Override public void sendBroadcastWithMultiplePermissions(Intent p1, String[] p2) { } + @Override public void sendOrderedBroadcast(Intent p0, String p1) { } + @Override public void sendOrderedBroadcast(Intent p0, String p1, BroadcastReceiver p2, Handler p3, int p4, String p5, Bundle p6) { } + @Override public void sendOrderedBroadcastAsUser(Intent p0, UserHandle p1, String p2, BroadcastReceiver p3, Handler p4, int p5, String p6, Bundle p7) { } + @Override public void sendStickyBroadcast(Intent p0) { } + @Override public void sendStickyBroadcastAsUser(Intent p0, UserHandle p1) { } + @Override public void sendStickyOrderedBroadcast(Intent p0, BroadcastReceiver p1, Handler p2, int p3, String p4, Bundle p5) { } + @Override public void sendStickyOrderedBroadcastAsUser(Intent p0, UserHandle p1, BroadcastReceiver p2, Handler p3, int p4, String p5, Bundle p6) { } + @Override public void setTheme(int p0) { } + @Override public void setWallpaper(Bitmap p0) { } + @Override public void setWallpaper(InputStream p0) { } + @Override public void startActivities(Intent[] p0) { } + @Override public void startActivities(Intent[] p0, Bundle p1) { } + @Override public void startActivity(Intent p0) { } + @Override public void startActivity(Intent p0, Bundle p1) { } + @Override public void startIntentSender(IntentSender p0, Intent p1, int p2, int p3, int p4) { } + @Override public void startIntentSender(IntentSender p0, Intent p1, int p2, int p3, int p4, Bundle p5) { } + @Override public void unbindService(ServiceConnection p0) { } + @Override public void unregisterReceiver(BroadcastReceiver p0) { } } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java b/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java index 03004b437d2..fe8f9f5a942 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java @@ -1,2627 +1,454 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.content.Intent for testing purposes + package android.content; +import android.content.ClipData; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.IntentSender; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; - -import java.io.IOException; -import java.io.PrintWriter; +import android.util.AttributeSet; import java.io.Serializable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Objects; import java.util.Set; - -/** - * An intent is an abstract description of an operation to be performed. It can - * be used with {@link Context#startActivity(Intent) startActivity} to launch an - * {@link android.app.Activity}, - * {@link android.content.Context#sendBroadcast(Intent) broadcastIntent} to send - * it to any interested {@link BroadcastReceiver BroadcastReceiver} components, - * and {@link android.content.Context#startService} or - * {@link android.content.Context#bindService} to communicate with a background - * {@link android.app.Service}. - * - * <p> - * An Intent provides a facility for performing late runtime binding between the - * code in different applications. Its most significant use is in the launching - * of activities, where it can be thought of as the glue between activities. It - * is basically a passive data structure holding an abstract description of an - * action to be performed. - * </p> - * - * <div class="special reference"> - * <h3>Developer Guides</h3> - * <p> - * For information about how to create and resolve intents, read the - * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and - * Intent Filters</a> developer guide. - * </p> - * </div> - * - * <a name="IntentStructure"></a> - * <h3>Intent Structure</h3> - * <p> - * The primary pieces of information in an intent are: - * </p> - * - * <ul> - * <li> - * <p> - * <b>action</b> -- The general action to be performed, such as - * {@link #ACTION_VIEW}, {@link #ACTION_EDIT}, {@link #ACTION_MAIN}, etc. - * </p> - * </li> - * <li> - * <p> - * <b>data</b> -- The data to operate on, such as a person record in the - * contacts database, expressed as a {@link android.net.Uri}. - * </p> - * </li> - * </ul> - * - * - * <p> - * Some examples of action/data pairs are: - * </p> - * - * <ul> - * <li> - * <p> - * <b>{@link #ACTION_VIEW} <i>content://contacts/people/1</i></b> -- Display - * information about the person whose identifier is "1". - * </p> - * </li> - * <li> - * <p> - * <b>{@link #ACTION_DIAL} <i>content://contacts/people/1</i></b> -- Display the - * phone dialer with the person filled in. - * </p> - * </li> - * <li> - * <p> - * <b>{@link #ACTION_VIEW} <i>tel:123</i></b> -- Display the phone dialer with - * the given number filled in. Note how the VIEW action does what is considered - * the most reasonable thing for a particular URI. - * </p> - * </li> - * <li> - * <p> - * <b>{@link #ACTION_DIAL} <i>tel:123</i></b> -- Display the phone dialer with - * the given number filled in. - * </p> - * </li> - * <li> - * <p> - * <b>{@link #ACTION_EDIT} <i>content://contacts/people/1</i></b> -- Edit - * information about the person whose identifier is "1". - * </p> - * </li> - * <li> - * <p> - * <b>{@link #ACTION_VIEW} <i>content://contacts/people/</i></b> -- Display a - * list of people, which the user can browse through. This example is a typical - * top-level entry into the Contacts application, showing you the list of - * people. Selecting a particular person to view would result in a new intent { - * <b>{@link #ACTION_VIEW} <i>content://contacts/people/N</i></b> } being used - * to start an activity to display that person. - * </p> - * </li> - * </ul> - * - * <p> - * In addition to these primary attributes, there are a number of secondary - * attributes that you can also include with an intent: - * </p> - * - * <ul> - * <li> - * <p> - * <b>category</b> -- Gives additional information about the action to execute. - * For example, {@link #CATEGORY_LAUNCHER} means it should appear in the - * Launcher as a top-level application, while {@link #CATEGORY_ALTERNATIVE} - * means it should be included in a list of alternative actions the user can - * perform on a piece of data. - * </p> - * <li> - * <p> - * <b>type</b> -- Specifies an explicit type (a MIME type) of the intent data. - * Normally the type is inferred from the data itself. By setting this - * attribute, you disable that evaluation and force an explicit type. - * </p> - * <li> - * <p> - * <b>component</b> -- Specifies an explicit name of a component class to use - * for the intent. Normally this is determined by looking at the other - * information in the intent (the action, data/type, and categories) and - * matching that with a component that can handle it. If this attribute is set - * then none of the evaluation is performed, and this component is used exactly - * as is. By specifying this attribute, all of the other Intent attributes - * become optional. - * </p> - * <li> - * <p> - * <b>extras</b> -- This is a {@link Bundle} of any additional information. This - * can be used to provide extended information to the component. For example, if - * we have a action to send an e-mail message, we could also include extra - * pieces of data here to supply a subject, body, etc. - * </p> - * </ul> - * - * <p> - * Here are some examples of other operations you can specify as intents using - * these additional parameters: - * </p> - * - * <ul> - * <li> - * <p> - * <b>{@link #ACTION_MAIN} with category {@link #CATEGORY_HOME}</b> -- Launch - * the home screen. - * </p> - * </li> - * <li> - * <p> - * <b>{@link #ACTION_GET_CONTENT} with MIME type - * <i>{@link android.provider.Contacts.Phones#CONTENT_URI - * vnd.android.cursor.item/phone}</i></b> -- Display the list of people's phone - * numbers, allowing the user to browse through them and pick one and return it - * to the parent activity. - * </p> - * </li> - * <li> - * <p> - * <b>{@link #ACTION_GET_CONTENT} with MIME type <i>*{@literal /}*</i> and - * category {@link #CATEGORY_OPENABLE}</b> -- Display all pickers for data that - * can be opened with {@link ContentResolver#openInputStream(Uri) - * ContentResolver.openInputStream()}, allowing the user to pick one of them and - * then some data inside of it and returning the resulting URI to the caller. - * This can be used, for example, in an e-mail application to allow the user to - * pick some data to include as an attachment. - * </p> - * </li> - * </ul> - * - * <p> - * There are a variety of standard Intent action and category constants defined - * in the Intent class, but applications can also define their own. These - * strings use Java-style scoping, to ensure they are unique -- for example, the - * standard {@link #ACTION_VIEW} is called "android.intent.action.VIEW". - * </p> - * - * <p> - * Put together, the set of actions, data types, categories, and extra data - * defines a language for the system allowing for the expression of phrases such - * as "call john smith's cell". As applications are added to the system, they - * can extend this language by adding new actions, types, and categories, or - * they can modify the behavior of existing phrases by supplying their own - * activities that handle them. - * </p> - * - * <a name="IntentResolution"></a> - * <h3>Intent Resolution</h3> - * - * <p> - * There are two primary forms of intents you will use. - * - * <ul> - * <li> - * <p> - * <b>Explicit Intents</b> have specified a component (via {@link #setComponent} - * or {@link #setClass}), which provides the exact class to be run. Often these - * will not include any other information, simply being a way for an application - * to launch various internal activities it has as the user interacts with the - * application. - * - * <li> - * <p> - * <b>Implicit Intents</b> have not specified a component; instead, they must - * include enough information for the system to determine which of the available - * components is best to run for that intent. - * </ul> - * - * <p> - * When using implicit intents, given such an arbitrary intent we need to know - * what to do with it. This is handled by the process of <em>Intent - * resolution</em>, which maps an Intent to an {@link android.app.Activity}, - * {@link BroadcastReceiver}, or {@link android.app.Service} (or sometimes two - * or more activities/receivers) that can handle it. - * </p> - * - * <p> - * The intent resolution mechanism basically revolves around matching an Intent - * against all of the <intent-filter> descriptions in the installed - * application packages. (Plus, in the case of broadcasts, any - * {@link BroadcastReceiver} objects explicitly registered with - * {@link Context#registerReceiver}.) More details on this can be found in the - * documentation on the {@link IntentFilter} class. - * </p> - * - * <p> - * There are three pieces of information in the Intent that are used for - * resolution: the action, type, and category. Using this information, a query - * is done on the {@link PackageManager} for a component that can handle the - * intent. The appropriate component is determined based on the intent - * information supplied in the <code>AndroidManifest.xml</code> file as follows: - * </p> - * - * <ul> - * <li> - * <p> - * The <b>action</b>, if given, must be listed by the component as one it - * handles. - * </p> - * <li> - * <p> - * The <b>type</b> is retrieved from the Intent's data, if not already supplied - * in the Intent. Like the action, if a type is included in the intent (either - * explicitly or implicitly in its data), then this must be listed by the - * component as one it handles. - * </p> - * <li>For data that is not a <code>content:</code> URI and where no explicit - * type is included in the Intent, instead the <b>scheme</b> of the intent data - * (such as <code>http:</code> or <code>mailto:</code>) is considered. Again - * like the action, if we are matching a scheme it must be listed by the - * component as one it can handle. - * <li> - * <p> - * The <b>categories</b>, if supplied, must <em>all</em> be listed by the - * activity as categories it handles. That is, if you include the categories - * {@link #CATEGORY_LAUNCHER} and {@link #CATEGORY_ALTERNATIVE}, then you will - * only resolve to components with an intent that lists <em>both</em> of those - * categories. Activities will very often need to support the - * {@link #CATEGORY_DEFAULT} so that they can be found by - * {@link Context#startActivity Context.startActivity()}. - * </p> - * </ul> - * - * <p> - * For example, consider the Note Pad sample application that allows a user to - * browse through a list of notes data and view details about individual items. - * Text in italics indicates places where you would replace a name with one - * specific to your own package. - * </p> - * - * <pre> - * <manifest xmlns:android="http://schemas.android.com/apk/res/android" - * package="<i>com.android.notepad</i>"> - * <application android:icon="@drawable/app_notes" - * android:label="@string/app_name"> - * - * <provider class=".NotePadProvider" - * android:authorities="<i>com.google.provider.NotePad</i>" /> - * - * <activity class=".NotesList" android:label="@string/title_notes_list"> - * <intent-filter> - * <action android:name="android.intent.action.MAIN" /> - * <category android:name="android.intent.category.LAUNCHER" /> - * </intent-filter> - * <intent-filter> - * <action android:name="android.intent.action.VIEW" /> - * <action android:name="android.intent.action.EDIT" /> - * <action android:name="android.intent.action.PICK" /> - * <category android:name="android.intent.category.DEFAULT" /> - * <data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> - * </intent-filter> - * <intent-filter> - * <action android:name="android.intent.action.GET_CONTENT" /> - * <category android:name="android.intent.category.DEFAULT" /> - * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * </activity> - * - * <activity class=".NoteEditor" android:label="@string/title_note"> - * <intent-filter android:label="@string/resolve_edit"> - * <action android:name="android.intent.action.VIEW" /> - * <action android:name="android.intent.action.EDIT" /> - * <category android:name="android.intent.category.DEFAULT" /> - * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * - * <intent-filter> - * <action android:name="android.intent.action.INSERT" /> - * <category android:name="android.intent.category.DEFAULT" /> - * <data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> - * </intent-filter> - * - * </activity> - * - * <activity class=".TitleEditor" android:label="@string/title_edit_title" - * android:theme="@android:style/Theme.Dialog"> - * <intent-filter android:label="@string/resolve_title"> - * <action android:name="<i>com.android.notepad.action.EDIT_TITLE</i>" /> - * <category android:name="android.intent.category.DEFAULT" /> - * <category android:name="android.intent.category.ALTERNATIVE" /> - * <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> - * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * </activity> - * - * </application> - * </manifest> - * </pre> - * - * <p> - * The first activity, <code>com.android.notepad.NotesList</code>, serves as our - * main entry into the app. It can do three things as described by its three - * intent templates: - * <ol> - * <li> - * - * <pre> - * <intent-filter> - * <action android:name="{@link #ACTION_MAIN android.intent.action.MAIN}" /> - * <category android:name="{@link #CATEGORY_LAUNCHER android.intent.category.LAUNCHER}" /> - * </intent-filter> - * </pre> - * <p> - * This provides a top-level entry into the NotePad application: the standard - * MAIN action is a main entry point (not requiring any other information in the - * Intent), and the LAUNCHER category says that this entry point should be - * listed in the application launcher. - * </p> - * <li> - * - * <pre> - * <intent-filter> - * <action android:name="{@link #ACTION_VIEW android.intent.action.VIEW}" /> - * <action android:name="{@link #ACTION_EDIT android.intent.action.EDIT}" /> - * <action android:name="{@link #ACTION_PICK android.intent.action.PICK}" /> - * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> - * </intent-filter> - * </pre> - * <p> - * This declares the things that the activity can do on a directory of notes. - * The type being supported is given with the <type> tag, where - * <code>vnd.android.cursor.dir/vnd.google.note</code> is a URI from which a - * Cursor of zero or more items (<code>vnd.android.cursor.dir</code>) can be - * retrieved which holds our note pad data (<code>vnd.google.note</code>). The - * activity allows the user to view or edit the directory of data (via the VIEW - * and EDIT actions), or to pick a particular note and return it to the caller - * (via the PICK action). Note also the DEFAULT category supplied here: this is - * <em>required</em> for the {@link Context#startActivity Context.startActivity} - * method to resolve your activity when its component name is not explicitly - * specified. - * </p> - * <li> - * - * <pre> - * <intent-filter> - * <action android:name="{@link #ACTION_GET_CONTENT android.intent.action.GET_CONTENT}" /> - * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * </pre> - * <p> - * This filter describes the ability to return to the caller a note selected by - * the user without needing to know where it came from. The data type - * <code>vnd.android.cursor.item/vnd.google.note</code> is a URI from which a - * Cursor of exactly one (<code>vnd.android.cursor.item</code>) item can be - * retrieved which contains our note pad data (<code>vnd.google.note</code>). - * The GET_CONTENT action is similar to the PICK action, where the activity will - * return to its caller a piece of data selected by the user. Here, however, the - * caller specifies the type of data they desire instead of the type of data the - * user will be picking from. - * </p> - * </ol> - * - * <p> - * Given these capabilities, the following intents will resolve to the NotesList - * activity: - * </p> - * - * <ul> - * <li> - * <p> - * <b>{ action=android.app.action.MAIN }</b> matches all of the activities that - * can be used as top-level entry points into an application. - * </p> - * <li> - * <p> - * <b>{ action=android.app.action.MAIN, category=android.app.category.LAUNCHER - * }</b> is the actual intent used by the Launcher to populate its top-level - * list. - * </p> - * <li> - * <p> - * <b>{ action=android.intent.action.VIEW - * data=content://com.google.provider.NotePad/notes }</b> displays a list of all - * the notes under "content://com.google.provider.NotePad/notes", which the user - * can browse through and see the details on. - * </p> - * <li> - * <p> - * <b>{ action=android.app.action.PICK - * data=content://com.google.provider.NotePad/notes }</b> provides a list of the - * notes under "content://com.google.provider.NotePad/notes", from which the - * user can pick a note whose data URL is returned back to the caller. - * </p> - * <li> - * <p> - * <b>{ action=android.app.action.GET_CONTENT - * type=vnd.android.cursor.item/vnd.google.note }</b> is similar to the pick - * action, but allows the caller to specify the kind of data they want back so - * that the system can find the appropriate activity to pick something of that - * data type. - * </p> - * </ul> - * - * <p> - * The second activity, <code>com.android.notepad.NoteEditor</code>, shows the - * user a single note entry and allows them to edit it. It can do two things as - * described by its two intent templates: - * <ol> - * <li> - * - * <pre> - * <intent-filter android:label="@string/resolve_edit"> - * <action android:name="{@link #ACTION_VIEW android.intent.action.VIEW}" /> - * <action android:name="{@link #ACTION_EDIT android.intent.action.EDIT}" /> - * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * </pre> - * <p> - * The first, primary, purpose of this activity is to let the user interact with - * a single note, as decribed by the MIME type - * <code>vnd.android.cursor.item/vnd.google.note</code>. The activity can either - * VIEW a note or allow the user to EDIT it. Again we support the DEFAULT - * category to allow the activity to be launched without explicitly specifying - * its component. - * </p> - * <li> - * - * <pre> - * <intent-filter> - * <action android:name="{@link #ACTION_INSERT android.intent.action.INSERT}" /> - * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> - * </intent-filter> - * </pre> - * <p> - * The secondary use of this activity is to insert a new note entry into an - * existing directory of notes. This is used when the user creates a new note: - * the INSERT action is executed on the directory of notes, causing this - * activity to run and have the user create the new note data which it then adds - * to the content provider. - * </p> - * </ol> - * - * <p> - * Given these capabilities, the following intents will resolve to the - * NoteEditor activity: - * </p> - * - * <ul> - * <li> - * <p> - * <b>{ action=android.intent.action.VIEW - * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b> shows - * the user the content of note <var>{ID}</var>. - * </p> - * <li> - * <p> - * <b>{ action=android.app.action.EDIT - * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b> allows - * the user to edit the content of note <var>{ID}</var>. - * </p> - * <li> - * <p> - * <b>{ action=android.app.action.INSERT - * data=content://com.google.provider.NotePad/notes }</b> creates a new, empty - * note in the notes list at "content://com.google.provider.NotePad/notes" and - * allows the user to edit it. If they keep their changes, the URI of the newly - * created note is returned to the caller. - * </p> - * </ul> - * - * <p> - * The last activity, <code>com.android.notepad.TitleEditor</code>, allows the - * user to edit the title of a note. This could be implemented as a class that - * the application directly invokes (by explicitly setting its component in the - * Intent), but here we show a way you can publish alternative operations on - * existing data: - * </p> - * - * <pre> - * <intent-filter android:label="@string/resolve_title"> - * <action android:name="<i>com.android.notepad.action.EDIT_TITLE</i>" /> - * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <category android:name="{@link #CATEGORY_ALTERNATIVE android.intent.category.ALTERNATIVE}" /> - * <category android:name="{@link #CATEGORY_SELECTED_ALTERNATIVE android.intent.category.SELECTED_ALTERNATIVE}" /> - * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * </pre> - * - * <p> - * In the single intent template here, we have created our own private action - * called <code>com.android.notepad.action.EDIT_TITLE</code> which means to edit - * the title of a note. It must be invoked on a specific note (data type - * <code>vnd.android.cursor.item/vnd.google.note</code>) like the previous view - * and edit actions, but here displays and edits the title contained in the note - * data. - * - * <p> - * In addition to supporting the default category as usual, our title editor - * also supports two other standard categories: ALTERNATIVE and - * SELECTED_ALTERNATIVE. Implementing these categories allows others to find the - * special action it provides without directly knowing about it, through the - * {@link android.content.pm.PackageManager#queryIntentActivityOptions} method, - * or more often to build dynamic menu items with - * {@link android.view.Menu#addIntentOptions}. Note that in the intent template - * here was also supply an explicit name for the template (via - * <code>android:label="@string/resolve_title"</code>) to better control what - * the user sees when presented with this activity as an alternative action to - * the data they are viewing. - * - * <p> - * Given these capabilities, the following intent will resolve to the - * TitleEditor activity: - * </p> - * - * <ul> - * <li> - * <p> - * <b>{ action=com.android.notepad.action.EDIT_TITLE - * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b> - * displays and allows the user to edit the title associated with note - * <var>{ID}</var>. - * </p> - * </ul> - * - * <h3>Standard Activity Actions</h3> - * - * <p> - * These are the current standard actions that Intent defines for launching - * activities (usually through {@link Context#startActivity}. The most - * important, and by far most frequently used, are {@link #ACTION_MAIN} and - * {@link #ACTION_EDIT}. - * - * <ul> - * <li>{@link #ACTION_MAIN} - * <li>{@link #ACTION_VIEW} - * <li>{@link #ACTION_ATTACH_DATA} - * <li>{@link #ACTION_EDIT} - * <li>{@link #ACTION_PICK} - * <li>{@link #ACTION_CHOOSER} - * <li>{@link #ACTION_GET_CONTENT} - * <li>{@link #ACTION_DIAL} - * <li>{@link #ACTION_CALL} - * <li>{@link #ACTION_SEND} - * <li>{@link #ACTION_SENDTO} - * <li>{@link #ACTION_ANSWER} - * <li>{@link #ACTION_INSERT} - * <li>{@link #ACTION_DELETE} - * <li>{@link #ACTION_RUN} - * <li>{@link #ACTION_SYNC} - * <li>{@link #ACTION_PICK_ACTIVITY} - * <li>{@link #ACTION_SEARCH} - * <li>{@link #ACTION_WEB_SEARCH} - * <li>{@link #ACTION_FACTORY_TEST} - * </ul> - * - * <h3>Standard Broadcast Actions</h3> - * - * <p> - * These are the current standard actions that Intent defines for receiving - * broadcasts (usually through {@link Context#registerReceiver} or a - * <receiver> tag in a manifest). - * - * <ul> - * <li>{@link #ACTION_TIME_TICK} - * <li>{@link #ACTION_TIME_CHANGED} - * <li>{@link #ACTION_TIMEZONE_CHANGED} - * <li>{@link #ACTION_BOOT_COMPLETED} - * <li>{@link #ACTION_PACKAGE_ADDED} - * <li>{@link #ACTION_PACKAGE_CHANGED} - * <li>{@link #ACTION_PACKAGE_REMOVED} - * <li>{@link #ACTION_PACKAGE_RESTARTED} - * <li>{@link #ACTION_PACKAGE_DATA_CLEARED} - * <li>{@link #ACTION_PACKAGES_SUSPENDED} - * <li>{@link #ACTION_PACKAGES_UNSUSPENDED} - * <li>{@link #ACTION_UID_REMOVED} - * <li>{@link #ACTION_BATTERY_CHANGED} - * <li>{@link #ACTION_POWER_CONNECTED} - * <li>{@link #ACTION_POWER_DISCONNECTED} - * <li>{@link #ACTION_SHUTDOWN} - * </ul> - * - * <h3>Standard Categories</h3> - * - * <p> - * These are the current standard categories that can be used to further clarify - * an Intent via {@link #addCategory}. - * - * <ul> - * <li>{@link #CATEGORY_DEFAULT} - * <li>{@link #CATEGORY_BROWSABLE} - * <li>{@link #CATEGORY_TAB} - * <li>{@link #CATEGORY_ALTERNATIVE} - * <li>{@link #CATEGORY_SELECTED_ALTERNATIVE} - * <li>{@link #CATEGORY_LAUNCHER} - * <li>{@link #CATEGORY_INFO} - * <li>{@link #CATEGORY_HOME} - * <li>{@link #CATEGORY_PREFERENCE} - * <li>{@link #CATEGORY_TEST} - * <li>{@link #CATEGORY_CAR_DOCK} - * <li>{@link #CATEGORY_DESK_DOCK} - * <li>{@link #CATEGORY_LE_DESK_DOCK} - * <li>{@link #CATEGORY_HE_DESK_DOCK} - * <li>{@link #CATEGORY_CAR_MODE} - * <li>{@link #CATEGORY_APP_MARKET} - * <li>{@link #CATEGORY_VR_HOME} - * </ul> - * - * <h3>Standard Extra Data</h3> - * - * <p> - * These are the current standard fields that can be used as extra data via - * {@link #putExtra}. - * - * <ul> - * <li>{@link #EXTRA_ALARM_COUNT} - * <li>{@link #EXTRA_BCC} - * <li>{@link #EXTRA_CC} - * <li>{@link #EXTRA_CHANGED_COMPONENT_NAME} - * <li>{@link #EXTRA_DATA_REMOVED} - * <li>{@link #EXTRA_DOCK_STATE} - * <li>{@link #EXTRA_DOCK_STATE_HE_DESK} - * <li>{@link #EXTRA_DOCK_STATE_LE_DESK} - * <li>{@link #EXTRA_DOCK_STATE_CAR} - * <li>{@link #EXTRA_DOCK_STATE_DESK} - * <li>{@link #EXTRA_DOCK_STATE_UNDOCKED} - * <li>{@link #EXTRA_DONT_KILL_APP} - * <li>{@link #EXTRA_EMAIL} - * <li>{@link #EXTRA_INITIAL_INTENTS} - * <li>{@link #EXTRA_INTENT} - * <li>{@link #EXTRA_KEY_EVENT} - * <li>{@link #EXTRA_ORIGINATING_URI} - * <li>{@link #EXTRA_PHONE_NUMBER} - * <li>{@link #EXTRA_REFERRER} - * <li>{@link #EXTRA_REMOTE_INTENT_TOKEN} - * <li>{@link #EXTRA_REPLACING} - * <li>{@link #EXTRA_SHORTCUT_ICON} - * <li>{@link #EXTRA_SHORTCUT_ICON_RESOURCE} - * <li>{@link #EXTRA_SHORTCUT_INTENT} - * <li>{@link #EXTRA_STREAM} - * <li>{@link #EXTRA_SHORTCUT_NAME} - * <li>{@link #EXTRA_SUBJECT} - * <li>{@link #EXTRA_TEMPLATE} - * <li>{@link #EXTRA_TEXT} - * <li>{@link #EXTRA_TITLE} - * <li>{@link #EXTRA_UID} - * </ul> - * - * <h3>Flags</h3> - * - * <p> - * These are the possible flags that can be used in the Intent via - * {@link #setFlags} and {@link #addFlags}. See {@link #setFlags} for a list of - * all possible flags. - */ -public class Intent implements Parcelable, Cloneable { - - /** - * Activity Action: Start as a main entry point, does not expect to - * receive data. - * <p>Input: nothing - * <p>Output: nothing - */ - public static final String ACTION_MAIN = "android.intent.action.MAIN"; - - /** - * Activity Action: Display the data to the user. This is the most common - * action performed on data -- it is the generic action you can use on - * a piece of data to get the most reasonable thing to occur. For example, - * when used on a contacts entry it will view the entry; when used on a - * mailto: URI it will bring up a compose window filled with the information - * supplied by the URI; when used with a tel: URI it will invoke the - * dialer. - * <p>Input: {@link #getData} is URI from which to retrieve data. - * <p>Output: nothing. - */ - public static final String ACTION_VIEW = "android.intent.action.VIEW"; - - /** - * A synonym for {@link #ACTION_VIEW}, the "standard" action that is - * performed on a piece of data. - */ - public static final String ACTION_DEFAULT = ACTION_VIEW; - - /** - * Used to indicate that some piece of data should be attached to some other - * place. For example, image data could be attached to a contact. It is up - * to the recipient to decide where the data should be attached; the intent - * does not specify the ultimate destination. - * <p>Input: {@link #getData} is URI of data to be attached. - * <p>Output: nothing. - */ - public static final String ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA"; - - /** - * Activity Action: Provide explicit editable access to the given data. - * <p>Input: {@link #getData} is URI of data to be edited. - * <p>Output: nothing. - */ - public static final String ACTION_EDIT = "android.intent.action.EDIT"; - - /** - * Activity Action: Pick an existing item, or insert a new item, and then edit it. - * <p>Input: {@link #getType} is the desired MIME type of the item to create or edit. - * The extras can contain type specific data to pass through to the editing/creating - * activity. - * <p>Output: The URI of the item that was picked. This must be a content: - * URI so that any receiver can access it. - */ - public static final String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT"; - - /** - * Activity Action: Pick an item from the data, returning what was selected. - * <p>Input: {@link #getData} is URI containing a directory of data - * (vnd.android.cursor.dir/*) from which to pick an item. - * <p>Output: The URI of the item that was picked. - */ - public static final String ACTION_PICK = "android.intent.action.PICK"; - - /** - * Activity Action: Creates a shortcut. - * <p>Input: Nothing.</p> - * <p>Output: An Intent representing the shortcut. The intent must contain three - * extras: SHORTCUT_INTENT (value: Intent), SHORTCUT_NAME (value: String), - * and SHORTCUT_ICON (value: Bitmap) or SHORTCUT_ICON_RESOURCE - * (value: ShortcutIconResource).</p> - * - * @see #EXTRA_SHORTCUT_INTENT - * @see #EXTRA_SHORTCUT_NAME - * @see #EXTRA_SHORTCUT_ICON - * @see #EXTRA_SHORTCUT_ICON_RESOURCE - * @see android.content.Intent.ShortcutIconResource - */ - public static final String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT"; - - /** - * Activity Action: Display an activity chooser, allowing the user to pick - * what they want to before proceeding. This can be used as an alternative - * to the standard activity picker that is displayed by the system when - * you try to start an activity with multiple possible matches, with these - * differences in behavior: - * <ul> - * <li>You can specify the title that will appear in the activity chooser. - * <li>The user does not have the option to make one of the matching - * activities a preferred activity, and all possible activities will - * always be shown even if one of them is currently marked as the - * preferred activity. - * </ul> - * <p> - * This action should be used when the user will naturally expect to - * select an activity in order to proceed. An example if when not to use - * it is when the user clicks on a "mailto:" link. They would naturally - * expect to go directly to their mail app, so startActivity() should be - * called directly: it will - * either launch the current preferred app, or put up a dialog allowing the - * user to pick an app to use and optionally marking that as preferred. - * <p> - * In contrast, if the user is selecting a menu item to send a picture - * they are viewing to someone else, there are many different things they - * may want to do at this point: send it through e-mail, upload it to a - * web service, etc. In this case the CHOOSER action should be used, to - * always present to the user a list of the things they can do, with a - * nice title given by the caller such as "Send this photo with:". - * <p> - * As a convenience, an Intent of this form can be created with the - * {@link #createChooser} function. - * <p>Input: No data should be specified. get*Extra must have - * a {@link #EXTRA_INTENT} field containing the Intent being executed, - * and can optionally have a {@link #EXTRA_TITLE} field containing the - * title text to display in the chooser. - * <p>Output: Depends on the protocol of {@link #EXTRA_INTENT}. - */ - public static final String ACTION_CHOOSER = "android.intent.action.CHOOSER"; - - /** - * Convenience function for creating a {@link #ACTION_CHOOSER} Intent. - * - * @param target The Intent that the user will be selecting an activity - * to perform. - * @param title Optional title that will be displayed in the chooser. - * @return Return a new Intent object that you can hand to - * {@link Context#startActivity(Intent) Context.startActivity()} and - * related methods. - */ - public static Intent createChooser(Intent target, CharSequence title) { - return null; - } - - /** - * Activity Action: Allow the user to select a particular kind of data and - * return it. This is different than {@link #ACTION_PICK} in that here we - * just say what kind of data is desired, not a URI of existing data from - * which the user can pick. A ACTION_GET_CONTENT could allow the user to - * create the data as it runs (for example taking a picture or recording a - * sound), let them browse over the web and download the desired data, - * etc. - * <p> - * There are two main ways to use this action: if you want a specific kind - * of data, such as a person contact, you set the MIME type to the kind of - * data you want and launch it with {@link Context#startActivity(Intent)}. - * The system will then launch the best application to select that kind - * of data for you. - * <p> - * You may also be interested in any of a set of types of content the user - * can pick. For example, an e-mail application that wants to allow the - * user to add an attachment to an e-mail message can use this action to - * bring up a list of all of the types of content the user can attach. - * <p> - * In this case, you should wrap the GET_CONTENT intent with a chooser - * (through {@link #createChooser}), which will give the proper interface - * for the user to pick how to send your data and allow you to specify - * a prompt indicating what they are doing. You will usually specify a - * broad MIME type (such as image/* or {@literal *}/*), resulting in a - * broad range of content types the user can select from. - * <p> - * When using such a broad GET_CONTENT action, it is often desirable to - * only pick from data that can be represented as a stream. This is - * accomplished by requiring the {@link #CATEGORY_OPENABLE} in the Intent. - * <p> - * Callers can optionally specify {@link #EXTRA_LOCAL_ONLY} to request that - * the launched content chooser only returns results representing data that - * is locally available on the device. For example, if this extra is set - * to true then an image picker should not show any pictures that are available - * from a remote server but not already on the local device (thus requiring - * they be downloaded when opened). - * <p> - * Input: {@link #getType} is the desired MIME type to retrieve. Note - * that no URI is supplied in the intent, as there are no constraints on - * where the returned data originally comes from. You may also include the - * {@link #CATEGORY_OPENABLE} if you can only accept data that can be - * opened as a stream. You may use {@link #EXTRA_LOCAL_ONLY} to limit content - * selection to local data. - * <p> - * Output: The URI of the item that was picked. This must be a content: - * URI so that any receiver can access it. - */ - public static final String ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT"; - - /** - * Activity Action: Dial a number as specified by the data. This shows a - * UI with the number being dialed, allowing the user to explicitly - * initiate the call. - * <p>Input: If nothing, an empty dialer is started; else {@link #getData} - * is URI of a phone number to be dialed or a tel: URI of an explicit phone - * number. - * <p>Output: nothing. - */ - public static final String ACTION_DIAL = "android.intent.action.DIAL"; - - /** - * Activity Action: Perform a call to someone specified by the data. - * <p>Input: If nothing, an empty dialer is started; else {@link #getData} - * is URI of a phone number to be dialed or a tel: URI of an explicit phone - * number. - * <p>Output: nothing. - * - * <p>Note: there will be restrictions on which applications can initiate a - * call; most applications should use the {@link #ACTION_DIAL}. - * <p>Note: this Intent <strong>cannot</strong> be used to call emergency - * numbers. Applications can <strong>dial</strong> emergency numbers using - * {@link #ACTION_DIAL}, however. - */ - public static final String ACTION_CALL = "android.intent.action.CALL"; - - /** - * Activity Action: Perform a call to an emergency number specified by the - * data. - * <p>Input: {@link #getData} is URI of a phone number to be dialed or a - * tel: URI of an explicit phone number. - * <p>Output: nothing. - * @hide - */ - public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY"; - - /** - * Activity action: Perform a call to any number (emergency or not) - * specified by the data. - * <p>Input: {@link #getData} is URI of a phone number to be dialed or a - * tel: URI of an explicit phone number. - * <p>Output: nothing. - * @hide - */ - public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED"; - - /** - * Activity Action: Send a message to someone specified by the data. - * <p>Input: {@link #getData} is URI describing the target. - * <p>Output: nothing. - */ - public static final String ACTION_SENDTO = "android.intent.action.SENDTO"; - - /** - * Activity Action: Deliver some data to someone else. Who the data is - * being delivered to is not specified; it is up to the receiver of this - * action to ask the user where the data should be sent. - * <p> - * When launching a SEND intent, you should usually wrap it in a chooser - * (through {@link #createChooser}), which will give the proper interface - * for the user to pick how to send your data and allow you to specify - * a prompt indicating what they are doing. - * <p> - * Input: {@link #getType} is the MIME type of the data being sent. - * get*Extra can have either a {@link #EXTRA_TEXT} - * or {@link #EXTRA_STREAM} field, containing the data to be sent. If - * using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it - * should be the MIME type of the data in EXTRA_STREAM. Use {@literal *}/* - * if the MIME type is unknown (this will only allow senders that can - * handle generic data streams). - * <p> - * Optional standard extras, which may be interpreted by some recipients as - * appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC}, - * {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}. - * <p> - * Output: nothing. - */ - public static final String ACTION_SEND = "android.intent.action.SEND"; - - /** - * Activity Action: Deliver multiple data to someone else. - * <p> - * Like ACTION_SEND, except the data is multiple. - * <p> - * Input: {@link #getType} is the MIME type of the data being sent. - * get*ArrayListExtra can have either a {@link #EXTRA_TEXT} or {@link - * #EXTRA_STREAM} field, containing the data to be sent. - * <p> - * Multiple types are supported, and receivers should handle mixed types - * whenever possible. The right way for the receiver to check them is to - * use the content resolver on each URI. The intent sender should try to - * put the most concrete mime type in the intent type, but it can fall - * back to {@literal <type>/*} or {@literal *}/* as needed. - * <p> - * e.g. if you are sending image/jpg and image/jpg, the intent's type can - * be image/jpg, but if you are sending image/jpg and image/png, then the - * intent's type should be image/*. - * <p> - * Optional standard extras, which may be interpreted by some recipients as - * appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC}, - * {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}. - * <p> - * Output: nothing. - */ - public static final String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE"; - - /** - * Activity Action: Handle an incoming phone call. - * <p>Input: nothing. - * <p>Output: nothing. - */ - public static final String ACTION_ANSWER = "android.intent.action.ANSWER"; - - /** - * Activity Action: Insert an empty item into the given container. - * <p>Input: {@link #getData} is URI of the directory (vnd.android.cursor.dir/*) - * in which to place the data. - * <p>Output: URI of the new data that was created. - */ - public static final String ACTION_INSERT = "android.intent.action.INSERT"; - - /** - * Activity Action: Create a new item in the given container, initializing it - * from the current contents of the clipboard. - * <p>Input: {@link #getData} is URI of the directory (vnd.android.cursor.dir/*) - * in which to place the data. - * <p>Output: URI of the new data that was created. - */ - public static final String ACTION_PASTE = "android.intent.action.PASTE"; - - /** - * Activity Action: Delete the given data from its container. - * <p>Input: {@link #getData} is URI of data to be deleted. - * <p>Output: nothing. - */ - public static final String ACTION_DELETE = "android.intent.action.DELETE"; - /** - * Activity Action: Run the data, whatever that means. - * <p>Input: ? (Note: this is currently specific to the test harness.) - * <p>Output: nothing. - */ - public static final String ACTION_RUN = "android.intent.action.RUN"; - - /** - * Activity Action: Perform a data synchronization. - * <p>Input: ? - * <p>Output: ? - */ - public static final String ACTION_SYNC = "android.intent.action.SYNC"; - - /** - * Activity Action: Pick an activity given an intent, returning the class - * selected. - * <p>Input: get*Extra field {@link #EXTRA_INTENT} is an Intent - * used with {@link PackageManager#queryIntentActivities} to determine the - * set of activities from which to pick. - * <p>Output: Class name of the activity that was selected. - */ - public static final String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY"; - - /** - * Activity Action: Perform a search. - * <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)} - * is the text to search for. If empty, simply - * enter your search results Activity with the search UI activated. - * <p>Output: nothing. - */ - public static final String ACTION_SEARCH = "android.intent.action.SEARCH"; - - /** - * Activity Action: Start the platform-defined tutorial - * <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)} - * is the text to search for. If empty, simply - * enter your search results Activity with the search UI activated. - * <p>Output: nothing. - */ - public static final String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL"; - - /** - * Activity Action: Perform a web search. - * <p> - * Input: {@link android.app.SearchManager#QUERY - * getStringExtra(SearchManager.QUERY)} is the text to search for. If it is - * a url starts with http or https, the site will be opened. If it is plain - * text, Google search will be applied. - * <p> - * Output: nothing. - */ - public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH"; - - /** - * Activity Action: List all available applications - * <p>Input: Nothing. - * <p>Output: nothing. - */ - public static final String ACTION_ALL_APPS = "android.intent.action.ALL_APPS"; - - /** - * Activity Action: Show settings for choosing wallpaper - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - public static final String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER"; - - /** - * Activity Action: Show activity for reporting a bug. - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - public static final String ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT"; - - /** - * Activity Action: Main entry point for factory tests. Only used when - * the device is booting in factory test node. The implementing package - * must be installed in the system image. - * <p>Input: nothing - * <p>Output: nothing - */ - public static final String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST"; - - /** - * Activity Action: The user pressed the "call" button to go to the dialer - * or other appropriate UI for placing a call. - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - public static final String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON"; - - /** - * Activity Action: Start Voice Command. - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND"; - - /** - * Activity Action: Start action associated with long pressing on the - * search key. - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS"; - - /** - * Activity Action: The user pressed the "Report" button in the crash/ANR dialog. - * This intent is delivered to the package which installed the application, usually - * Google Play. - * <p>Input: No data is specified. The bug report is passed in using - * an {@link #EXTRA_BUG_REPORT} field. - * <p>Output: Nothing. - * - * @see #EXTRA_BUG_REPORT - */ - public static final String ACTION_APP_ERROR = "android.intent.action.APP_ERROR"; - - /** - * Activity Action: Show power usage information to the user. - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - public static final String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY"; - - /** - * Activity Action: Setup wizard to launch after a platform update. This - * activity should have a string meta-data field associated with it, - * {@link #METADATA_SETUP_VERSION}, which defines the current version of - * the platform for setup. The activity will be launched only if - * {@link android.provider.Settings.Secure#LAST_SETUP_SHOWN} is not the - * same value. - * <p>Input: Nothing. - * <p>Output: Nothing. - * @hide - */ - public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP"; - - /** - * Activity Action: Show settings for managing network data usage of a - * specific application. Applications should define an activity that offers - * options to control data usage. - */ - public static final String ACTION_MANAGE_NETWORK_USAGE = - "android.intent.action.MANAGE_NETWORK_USAGE"; - - /** - * Activity Action: Launch application installer. - * <p> - * Input: The data must be a content: or file: URI at which the application - * can be retrieved. You can optionally supply - * {@link #EXTRA_INSTALLER_PACKAGE_NAME}, {@link #EXTRA_NOT_UNKNOWN_SOURCE}, - * {@link #EXTRA_ALLOW_REPLACE}, and {@link #EXTRA_RETURN_RESULT}. - * <p> - * Output: If {@link #EXTRA_RETURN_RESULT}, returns whether the install - * succeeded. - * - * @see #EXTRA_INSTALLER_PACKAGE_NAME - * @see #EXTRA_NOT_UNKNOWN_SOURCE - * @see #EXTRA_RETURN_RESULT - */ - public static final String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE"; - - /** - * Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a - * package. Tells the installer UI to skip the confirmation with the user - * if the .apk is replacing an existing one. - */ - public static final String EXTRA_ALLOW_REPLACE - = "android.intent.extra.ALLOW_REPLACE"; - - /** - * Extra used to indicate that an intent can allow the user to select and return multiple items. - * This is a boolean extra; the default is false. If true, an implementation is allowed to present - * the user with a UI where they can pick multiple items that are all returned to the caller. - * When this happens, they should be returned as the getClipData() part of the result Intent. - */ - public static final String EXTRA_ALLOW_MULTIPLE - = "android.intent.extra.ALLOW_MULTIPLE"; - - /** - * Used to indicate that a GET_CONTENT intent only wants URIs that can be opened with - * ContentResolver.openInputStream. Openable URIs must support the columns in OpenableColumns - * when queried, though it is allowable for those columns to be blank. - */ - public static final String CATEGORY_OPENABLE = "android.intent.category.OPENABLE"; - - /** - * Create an empty intent. - */ - public Intent() { - } - - /** - * Copy constructor. - */ - public Intent(Intent o) { - } - - /** - * Create an intent with a given action. All other fields (data, type, class) - * are null. Note that the action <em>must</em> be in a namespace because - * Intents are used globally in the system -- for example the system VIEW action - * is android.intent.action.VIEW; an application's custom action would be - * something like com.google.app.myapp.CUSTOM_ACTION. - * - * @param action The Intent action, such as ACTION_VIEW. - */ - public Intent(String action) { - } - - /** - * Create an intent with a given action and for a given data url. Note that the - * action <em>must</em> be in a namespace because Intents are used globally in - * the system -- for example the system VIEW action is - * android.intent.action.VIEW; an application's custom action would be something - * like com.google.app.myapp.CUSTOM_ACTION. - * - * <p> - * <em>Note: scheme and host name matching in the Android framework is - * case-sensitive, unlike the formal RFC. As a result, you should always ensure - * that you write your Uri with these elements using lower case letters, and - * normalize any Uris you receive from outside of Android to ensure the scheme - * and host is lower case.</em> - * </p> - * - * @param action The Intent action, such as ACTION_VIEW. - * @param uri The Intent data URI. - */ - public Intent(String action, Uri uri) { - } - - /** - * Create an intent for a specific component. All other fields (action, data, - * type, class) are null, though they can be modified later with explicit calls. - * This provides a convenient way to create an intent that is intended to - * execute a hard-coded class name, rather than relying on the system to find an - * appropriate class for you; see {@link #setComponent} for more information on - * the repercussions of this. - * - * @param packageContext A Context of the application package implementing this - * class. - * @param cls The component class that is to be used for the intent. - * - * @see #setClass - * @see #setComponent - * @see #Intent(String, android.net.Uri , Context, Class) - */ - public Intent(Context packageContext, Class<?> cls) { - } - - /** - * Create an intent for a specific component with a specified action and data. - * This is equivalent to using {@link #Intent(String, android.net.Uri)} to - * construct the Intent and then calling {@link #setClass} to set its class. - * - * <p> - * <em>Note: scheme and host name matching in the Android framework is - * case-sensitive, unlike the formal RFC. As a result, you should always ensure - * that you write your Uri with these elements using lower case letters, and - * normalize any Uris you receive from outside of Android to ensure the scheme - * and host is lower case.</em> - * </p> - * - * @param action The Intent action, such as ACTION_VIEW. - * @param uri The Intent data URI. - * @param packageContext A Context of the application package implementing this - * class. - * @param cls The component class that is to be used for the intent. - * - * @see #Intent(String, android.net.Uri) - * @see #Intent(Context, Class) - * @see #setClass - * @see #setComponent - */ - public Intent(String action, Uri uri, Context packageContext, Class<?> cls) { - } - - /** - * Call {@link #parseUri} with 0 flags. - * - * @deprecated Use {@link #parseUri} instead. - */ - @Deprecated - public static Intent getIntent(String uri) { - return null; - } - - /** - * Create an intent from a URI. This URI may encode the action, category, and - * other intent fields, if it was returned by {@link #toUri}. If the Intent was - * not generate by toUri(), its data will be the entire URI and its action will - * be ACTION_VIEW. - * - * <p> - * The URI given here must not be relative -- that is, it must include the - * scheme and full path. - * - * @param uri The URI to turn into an Intent. - * @param flags Additional processing flags. - * - * @return Intent The newly created Intent object. - * - * @throws URISyntaxException Throws URISyntaxError if the basic URI syntax it - * bad (as parsed by the Uri class) or the Intent - * data within the URI is invalid. - * - * @see #toUri - */ - public static Intent parseUri(String uri, int flags) { - return null; - } - - /** - * Retrieve the general action to be performed, such as {@link #ACTION_VIEW}. - * The action describes the general way the rest of the information in the - * intent should be interpreted -- most importantly, what to do with the data - * returned by {@link #getData}. - * - * @return The action of this intent or null if none is specified. - * - * @see #setAction - */ - public String getAction() { - return null; - } - - /** - * Retrieve data this intent is operating on. This URI specifies the name of the - * data; often it uses the content: scheme, specifying data in a content - * provider. Other schemes may be handled by specific activities, such as http: - * by the web browser. - * - * @return The URI of the data this intent is targeting or null. - * - * @see #getScheme - * @see #setData - */ - public Uri getData() { - return null; - } - - /** - * The same as {@link #getData()}, but returns the URI as an encoded String. - */ - public String getDataString() { - return null; - } - - /** - * Return the scheme portion of the intent's data. If the data is null or does - * not include a scheme, null is returned. Otherwise, the scheme prefix without - * the final ':' is returned, i.e. "http". - * - * <p> - * This is the same as calling getData().getScheme() (and checking for null - * data). - * - * @return The scheme of this intent. - * - * @see #getData - */ - public String getScheme() { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if - * none was found. - * - * @deprecated - * @hide - */ - @Deprecated - public Object getExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired type - * is stored with the given name. - * - * @return the value of an item previously added with putExtra(), or the default - * value if none was found. - * - * @see #putExtra(String, boolean) - */ - public boolean getBooleanExtra(String name, boolean defaultValue) { - return false; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired type - * is stored with the given name. - * - * @return the value of an item previously added with putExtra(), or the default - * value if none was found. - * - * @see #putExtra(String, byte) - */ - public byte getByteExtra(String name, byte defaultValue) { - return -1; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired type - * is stored with the given name. - * - * @return the value of an item previously added with putExtra(), or the default - * value if none was found. - * - * @see #putExtra(String, short) - */ - public short getShortExtra(String name, short defaultValue) { - return -1; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired type - * is stored with the given name. - * - * @return the value of an item previously added with putExtra(), or the default - * value if none was found. - * - * @see #putExtra(String, char) - */ - public char getCharExtra(String name, char defaultValue) { - return 'a'; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired type - * is stored with the given name. - * - * @return the value of an item previously added with putExtra(), or the default - * value if none was found. - * - * @see #putExtra(String, int) - */ - public int getIntExtra(String name, int defaultValue) { - return -1; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired type - * is stored with the given name. - * - * @return the value of an item previously added with putExtra(), or the default - * value if none was found. - * - * @see #putExtra(String, long) - */ - public long getLongExtra(String name, long defaultValue) { - return -1; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired type - * is stored with the given name. - * - * @return the value of an item previously added with putExtra(), or the default - * value if no such item is present - * - * @see #putExtra(String, float) - */ - public float getFloatExtra(String name, float defaultValue) { - return -1; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired type - * is stored with the given name. - * - * @return the value of an item previously added with putExtra(), or the default - * value if none was found. - * - * @see #putExtra(String, double) - */ - public double getDoubleExtra(String name, double defaultValue) { - return -1; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * String value was found. - * - * @see #putExtra(String, String) - */ - public String getStringExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * CharSequence value was found. - * - * @see #putExtra(String, CharSequence) - */ - public CharSequence getCharSequenceExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * Parcelable value was found. - * - * @see #putExtra(String, Parcelable) - */ - public <T extends Parcelable> T getParcelableExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * Parcelable[] value was found. - * - * @see #putExtra(String, Parcelable[]) - */ - public Parcelable[] getParcelableArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with - * putParcelableArrayListExtra(), or null if no ArrayList<Parcelable> - * value was found. - * - * @see #putParcelableArrayListExtra(String, ArrayList) - */ - public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * Serializable value was found. - * - * @see #putExtra(String, Serializable) - */ - public Serializable getSerializableExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with - * putIntegerArrayListExtra(), or null if no ArrayList<Integer> value - * was found. - * - * @see #putIntegerArrayListExtra(String, ArrayList) - */ - public ArrayList<Integer> getIntegerArrayListExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putStringArrayListExtra(), - * or null if no ArrayList<String> value was found. - * - * @see #putStringArrayListExtra(String, ArrayList) - */ - public ArrayList<String> getStringArrayListExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with - * putCharSequenceArrayListExtra, or null if no ArrayList<CharSequence> - * value was found. - * - * @see #putCharSequenceArrayListExtra(String, ArrayList) - */ - public ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * boolean array value was found. - * - * @see #putExtra(String, boolean[]) - */ - public boolean[] getBooleanArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * byte array value was found. - * - * @see #putExtra(String, byte[]) - */ - public byte[] getByteArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * short array value was found. - * - * @see #putExtra(String, short[]) - */ - public short[] getShortArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * char array value was found. - * - * @see #putExtra(String, char[]) - */ - public char[] getCharArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * int array value was found. - * - * @see #putExtra(String, int[]) - */ - public int[] getIntArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * long array value was found. - * - * @see #putExtra(String, long[]) - */ - public long[] getLongArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * float array value was found. - * - * @see #putExtra(String, float[]) - */ - public float[] getFloatArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * double array value was found. - * - * @see #putExtra(String, double[]) - */ - public double[] getDoubleArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * String array value was found. - * - * @see #putExtra(String, String[]) - */ - public String[] getStringArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * CharSequence array value was found. - * - * @see #putExtra(String, CharSequence[]) - */ - public CharSequence[] getCharSequenceArrayExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item previously added with putExtra(), or null if no - * Bundle value was found. - * - * @see #putExtra(String, Bundle) - */ - public Bundle getBundleExtra(String name) { - return null; - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue The default value to return in case no item is associated - * with the key 'name' - * - * @return the value of an item previously added with putExtra(), or - * defaultValue if none was found. - * - * @see #putExtra - * - * @deprecated - * @hide - */ - @Deprecated - public Object getExtra(String name, Object defaultValue) { - return null; - } - - /** - * Retrieves a map of extended data from the intent. - * - * @return the map of all extras previously added with putExtra(), or null if - * none have been added. - */ - public Bundle getExtras() { - return null; - } - - /** - * Filter extras to only basic types. - * - * @hide - */ - public void removeUnsafeExtras() { - } - - /** - * Set the general action to be performed. - * - * @param action An action name, such as ACTION_VIEW. Application-specific - * actions should be prefixed with the vendor's package name. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #getAction - */ - public Intent setAction(String action) { - return null; - } - - /** - * Set the data this intent is operating on. This method automatically clears - * any type that was previously set by {@link #setType} or - * {@link #setTypeAndNormalize}. - * - * <p> - * <em>Note: scheme matching in the Android framework is case-sensitive, unlike - * the formal RFC. As a result, you should always write your Uri with a lower - * case scheme, or use {@link Uri#normalizeScheme} or - * {@link #setDataAndNormalize} to ensure that the scheme is converted to lower - * case.</em> - * - * @param data The Uri of the data this intent is now targeting. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #getData - * @see #setDataAndNormalize - * @see android.net.Uri#normalizeScheme() - */ - public Intent setData(Uri data) { - return null; - } - - /** - * Set an explicit MIME data type. - * - * <p>This is used to create intents that only specify a type and not data, - * for example to indicate the type of data to return. - * - * <p>This method automatically clears any data that was - * previously set (for example by {@link #setData}). - * - * <p><em>Note: MIME type matching in the Android framework is - * case-sensitive, unlike formal RFC MIME types. As a result, - * you should always write your MIME types with lower case letters, - * or use {@link #normalizeMimeType} or {@link #setTypeAndNormalize} - * to ensure that it is converted to lower case.</em> - * - * @param type The MIME type of the data being handled by this intent. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #getType - * @see #setTypeAndNormalize - * @see #setDataAndType - * @see #normalizeMimeType - */ - public Intent setType(String type) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The boolean data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getBooleanExtra(String, boolean) - */ - public Intent putExtra(String name, boolean value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The byte data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getByteExtra(String, byte) - */ - public Intent putExtra(String name, byte value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The char data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getCharExtra(String, char) - */ - public Intent putExtra(String name, char value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The short data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getShortExtra(String, short) - */ - public Intent putExtra(String name, short value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The integer data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getIntExtra(String, int) - */ - public Intent putExtra(String name, int value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The long data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getLongExtra(String, long) - */ - public Intent putExtra(String name, long value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The float data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getFloatExtra(String, float) - */ - public Intent putExtra(String name, float value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The double data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getDoubleExtra(String, double) - */ - public Intent putExtra(String name, double value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The String data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getStringExtra(String) - */ - public Intent putExtra(String name, String value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The CharSequence data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getCharSequenceExtra(String) - */ - public Intent putExtra(String name, CharSequence value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The Parcelable data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getParcelableExtra(String) - */ - public Intent putExtra(String name, Parcelable value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The Parcelable[] data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getParcelableArrayExtra(String) - */ - public Intent putExtra(String name, Parcelable[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The ArrayList<Parcelable> data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getParcelableArrayListExtra(String) - */ - public Intent putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The ArrayList<Integer> data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getIntegerArrayListExtra(String) - */ - public Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The ArrayList<String> data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getStringArrayListExtra(String) - */ - public Intent putStringArrayListExtra(String name, ArrayList<String> value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The ArrayList<CharSequence> data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getCharSequenceArrayListExtra(String) - */ - public Intent putCharSequenceArrayListExtra(String name, ArrayList<CharSequence> value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The Serializable data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getSerializableExtra(String) - */ - public Intent putExtra(String name, Serializable value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The boolean array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getBooleanArrayExtra(String) - */ - public Intent putExtra(String name, boolean[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The byte array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getByteArrayExtra(String) - */ - public Intent putExtra(String name, byte[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The short array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getShortArrayExtra(String) - */ - public Intent putExtra(String name, short[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The char array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getCharArrayExtra(String) - */ - public Intent putExtra(String name, char[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The int array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getIntArrayExtra(String) - */ - public Intent putExtra(String name, int[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The byte array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getLongArrayExtra(String) - */ - public Intent putExtra(String name, long[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The float array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getFloatArrayExtra(String) - */ - public Intent putExtra(String name, float[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The double array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getDoubleArrayExtra(String) - */ - public Intent putExtra(String name, double[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The String array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getStringArrayExtra(String) - */ - public Intent putExtra(String name, String[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The CharSequence array data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getCharSequenceArrayExtra(String) - */ - public Intent putExtra(String name, CharSequence[] value) { - return null; - } - - /** - * Add extended data to the intent. The name must include a package prefix, for - * example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The Bundle data value. - * - * @return Returns the same Intent object, for chaining multiple calls into a - * single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getBundleExtra(String) - */ - public Intent putExtra(String name, Bundle value) { - return null; - } - - /** - * Copy all extras in 'src' in to this intent. - * - * @param src Contains the extras to copy. - * - * @see #putExtra - */ - public Intent putExtras(Intent src) { - return null; - } - - /** - * Add a set of extended data to the intent. The keys must include a package - * prefix, for example the app com.android.contacts would use names like - * "com.android.contacts.ShowAll". - * - * @param extras The Bundle of extras to add to this intent. - * - * @see #putExtra - * @see #removeExtra - */ - public Intent putExtras(Bundle extras) { - return null; - } - - /** - * Completely replace the extras in the Intent with the extras in the given - * Intent. - * - * @param src The exact extras contained in this Intent are copied into the - * target intent, replacing any that were previously there. - */ - public Intent replaceExtras(Intent src) { - return null; - } - - /** - * Completely replace the extras in the Intent with the given Bundle of extras. - * - * @param extras The new set of extras in the Intent, or null to erase all - * extras. - */ - public Intent replaceExtras(Bundle extras) { - return null; - } - - /** - * Remove extended data from the intent. - * - * @see #putExtra - */ - public void removeExtra(String name) { - } - - public void writeToParcel(Parcel out, int flags) { - } - - public void readFromParcel(Parcel in) { - } - - /** - * Retrieve the application package name this Intent is limited to. When - * resolving an Intent, if non-null this limits the resolution to only - * components in the given application package. - * - * @return The name of the application package for the Intent. - * - * @see #resolveActivity - * @see #setPackage - */ - public String getPackage() { - return null; - } - - /** - * (Usually optional) Set an explicit application package name that limits - * the components this Intent will resolve to. If left to the default - * value of null, all components in all applications will considered. - * If non-null, the Intent can only match the components in the given - * application package. - * - * @param packageName The name of the application package to handle the - * intent, or null to allow any application package. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #getPackage - * @see #resolveActivity - */ - public Intent setPackage(String packageName) { - return null; - } - - /** - * Convenience for calling {@link #setComponent} with an - * explicit class name. - * - * @param packageContext A Context of the application package implementing - * this class. - * @param className The name of a class inside of the application package - * that will be used as the component for this Intent. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #setComponent - * @see #setClass - */ - public Intent setClassName(Context packageContext, String className) { - return null; - } - - /** - * Convenience for calling {@link #setComponent} with an - * explicit application package name and class name. - * - * @param packageName The name of the package implementing the desired - * component. - * @param className The name of a class inside of the application package - * that will be used as the component for this Intent. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #setComponent - * @see #setClass - */ - public Intent setClassName(String packageName, String className) { - return null; - } - - /** - * Add a new category to the intent. Categories provide additional detail - * about the action the intent performs. When resolving an intent, only - * activities that provide <em>all</em> of the requested categories will be - * used. - * - * @param category The desired category. This can be either one of the - * predefined Intent categories, or a custom category in your own - * namespace. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #hasCategory - * @see #removeCategory - */ - public Intent addCategory(String category) { - return null; - } +import org.xmlpull.v1.XmlPullParser; + +public class Intent implements Cloneable, Parcelable +{ + public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String p0){ return null; } + public <T extends Parcelable> T getParcelableExtra(String p0){ return null; } + public ActivityInfo resolveActivityInfo(PackageManager p0, int p1){ return null; } + public ArrayList<CharSequence> getCharSequenceArrayListExtra(String p0){ return null; } + public ArrayList<Integer> getIntegerArrayListExtra(String p0){ return null; } + public ArrayList<String> getStringArrayListExtra(String p0){ return null; } + public Bundle getBundleExtra(String p0){ return null; } + public Bundle getExtras(){ return null; } + public CharSequence getCharSequenceExtra(String p0){ return null; } + public CharSequence[] getCharSequenceArrayExtra(String p0){ return null; } + public ClipData getClipData(){ return null; } + public ComponentName getComponent(){ return null; } + public ComponentName resolveActivity(PackageManager p0){ return null; } + public Intent addCategory(String p0){ return null; } + public Intent addFlags(int p0){ return null; } + public Intent cloneFilter(){ return null; } + public Intent getSelector(){ return null; } + public Intent putCharSequenceArrayListExtra(String p0, ArrayList<CharSequence> p1){ return null; } + public Intent putExtra(String p0, Bundle p1){ return null; } + public Intent putExtra(String p0, CharSequence p1){ return null; } + public Intent putExtra(String p0, CharSequence[] p1){ return null; } + public Intent putExtra(String p0, Parcelable p1){ return null; } + public Intent putExtra(String p0, Parcelable[] p1){ return null; } + public Intent putExtra(String p0, Serializable p1){ return null; } + public Intent putExtra(String p0, String p1){ return null; } + public Intent putExtra(String p0, String[] p1){ return null; } + public Intent putExtra(String p0, boolean p1){ return null; } + public Intent putExtra(String p0, boolean[] p1){ return null; } + public Intent putExtra(String p0, byte p1){ return null; } + public Intent putExtra(String p0, byte[] p1){ return null; } + public Intent putExtra(String p0, char p1){ return null; } + public Intent putExtra(String p0, char[] p1){ return null; } + public Intent putExtra(String p0, double p1){ return null; } + public Intent putExtra(String p0, double[] p1){ return null; } + public Intent putExtra(String p0, float p1){ return null; } + public Intent putExtra(String p0, float[] p1){ return null; } + public Intent putExtra(String p0, int p1){ return null; } + public Intent putExtra(String p0, int[] p1){ return null; } + public Intent putExtra(String p0, long p1){ return null; } + public Intent putExtra(String p0, long[] p1){ return null; } + public Intent putExtra(String p0, short p1){ return null; } + public Intent putExtra(String p0, short[] p1){ return null; } + public Intent putExtras(Bundle p0){ return null; } + public Intent putExtras(Intent p0){ return null; } + public Intent putIntegerArrayListExtra(String p0, ArrayList<Integer> p1){ return null; } + public Intent putParcelableArrayListExtra(String p0, ArrayList<? extends Parcelable> p1){ return null; } + public Intent putStringArrayListExtra(String p0, ArrayList<String> p1){ return null; } + public Intent replaceExtras(Bundle p0){ return null; } + public Intent replaceExtras(Intent p0){ return null; } + public Intent setAction(String p0){ return null; } + public Intent setClass(Context p0, Class<? extends Object> p1){ return null; } + public Intent setClassName(Context p0, String p1){ return null; } + public Intent setClassName(String p0, String p1){ return null; } + public Intent setComponent(ComponentName p0){ return null; } + public Intent setData(Uri p0){ return null; } + public Intent setDataAndNormalize(Uri p0){ return null; } + public Intent setDataAndType(Uri p0, String p1){ return null; } + public Intent setDataAndTypeAndNormalize(Uri p0, String p1){ return null; } + public Intent setFlags(int p0){ return null; } + public Intent setIdentifier(String p0){ return null; } + public Intent setPackage(String p0){ return null; } + public Intent setType(String p0){ return null; } + public Intent setTypeAndNormalize(String p0){ return null; } + public Intent(){} + public Intent(Context p0, Class<? extends Object> p1){} + public Intent(Intent p0){} + public Intent(String p0){} + public Intent(String p0, Uri p1){} + public Intent(String p0, Uri p1, Context p2, Class<? extends Object> p3){} + public Object clone(){ return null; } + public Parcelable[] getParcelableArrayExtra(String p0){ return null; } + public Rect getSourceBounds(){ return null; } + public Serializable getSerializableExtra(String p0){ return null; } + public Set<String> getCategories(){ return null; } + public String getAction(){ return null; } + public String getDataString(){ return null; } + public String getIdentifier(){ return null; } + public String getPackage(){ return null; } + public String getScheme(){ return null; } + public String getStringExtra(String p0){ return null; } + public String getType(){ return null; } + public String resolveType(ContentResolver p0){ return null; } + public String resolveType(Context p0){ return null; } + public String resolveTypeIfNeeded(ContentResolver p0){ return null; } + public String toString(){ return null; } + public String toURI(){ return null; } + public String toUri(int p0){ return null; } + public String[] getStringArrayExtra(String p0){ return null; } + public Uri getData(){ return null; } + public boolean filterEquals(Intent p0){ return false; } + public boolean getBooleanExtra(String p0, boolean p1){ return false; } + public boolean hasCategory(String p0){ return false; } + public boolean hasExtra(String p0){ return false; } + public boolean hasFileDescriptors(){ return false; } + public boolean[] getBooleanArrayExtra(String p0){ return null; } + public byte getByteExtra(String p0, byte p1){ return 0; } + public byte[] getByteArrayExtra(String p0){ return null; } + public char getCharExtra(String p0, char p1){ return '0'; } + public char[] getCharArrayExtra(String p0){ return null; } + public double getDoubleExtra(String p0, double p1){ return 0; } + public double[] getDoubleArrayExtra(String p0){ return null; } + public float getFloatExtra(String p0, float p1){ return 0; } + public float[] getFloatArrayExtra(String p0){ return null; } + public int describeContents(){ return 0; } + public int fillIn(Intent p0, int p1){ return 0; } + public int filterHashCode(){ return 0; } + public int getFlags(){ return 0; } + public int getIntExtra(String p0, int p1){ return 0; } + public int[] getIntArrayExtra(String p0){ return null; } + public long getLongExtra(String p0, long p1){ return 0; } + public long[] getLongArrayExtra(String p0){ return null; } + public short getShortExtra(String p0, short p1){ return 0; } + public short[] getShortArrayExtra(String p0){ return null; } + public static Intent createChooser(Intent p0, CharSequence p1){ return null; } + public static Intent createChooser(Intent p0, CharSequence p1, IntentSender p2){ return null; } + public static Intent getIntent(String p0){ return null; } + public static Intent getIntentOld(String p0){ return null; } + public static Intent makeMainActivity(ComponentName p0){ return null; } + public static Intent makeMainSelectorActivity(String p0, String p1){ return null; } + public static Intent makeRestartActivityTask(ComponentName p0){ return null; } + public static Intent parseIntent(Resources p0, XmlPullParser p1, AttributeSet p2){ return null; } + public static Intent parseUri(String p0, int p1){ return null; } + public static Parcelable.Creator<Intent> CREATOR = null; + public static String ACTION_AIRPLANE_MODE_CHANGED = null; + public static String ACTION_ALL_APPS = null; + public static String ACTION_ANSWER = null; + public static String ACTION_APPLICATION_PREFERENCES = null; + public static String ACTION_APPLICATION_RESTRICTIONS_CHANGED = null; + public static String ACTION_APP_ERROR = null; + public static String ACTION_ASSIST = null; + public static String ACTION_ATTACH_DATA = null; + public static String ACTION_BATTERY_CHANGED = null; + public static String ACTION_BATTERY_LOW = null; + public static String ACTION_BATTERY_OKAY = null; + public static String ACTION_BOOT_COMPLETED = null; + public static String ACTION_BUG_REPORT = null; + public static String ACTION_CALL = null; + public static String ACTION_CALL_BUTTON = null; + public static String ACTION_CAMERA_BUTTON = null; + public static String ACTION_CARRIER_SETUP = null; + public static String ACTION_CHOOSER = null; + public static String ACTION_CLOSE_SYSTEM_DIALOGS = null; + public static String ACTION_CONFIGURATION_CHANGED = null; + public static String ACTION_CREATE_DOCUMENT = null; + public static String ACTION_CREATE_SHORTCUT = null; + public static String ACTION_DATE_CHANGED = null; + public static String ACTION_DEFAULT = null; + public static String ACTION_DEFINE = null; + public static String ACTION_DELETE = null; + public static String ACTION_DEVICE_STORAGE_LOW = null; + public static String ACTION_DEVICE_STORAGE_OK = null; + public static String ACTION_DIAL = null; + public static String ACTION_DOCK_EVENT = null; + public static String ACTION_DREAMING_STARTED = null; + public static String ACTION_DREAMING_STOPPED = null; + public static String ACTION_EDIT = null; + public static String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = null; + public static String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = null; + public static String ACTION_FACTORY_TEST = null; + public static String ACTION_GET_CONTENT = null; + public static String ACTION_GET_RESTRICTION_ENTRIES = null; + public static String ACTION_GTALK_SERVICE_CONNECTED = null; + public static String ACTION_GTALK_SERVICE_DISCONNECTED = null; + public static String ACTION_HEADSET_PLUG = null; + public static String ACTION_INPUT_METHOD_CHANGED = null; + public static String ACTION_INSERT = null; + public static String ACTION_INSERT_OR_EDIT = null; + public static String ACTION_INSTALL_FAILURE = null; + public static String ACTION_INSTALL_PACKAGE = null; + public static String ACTION_LOCALE_CHANGED = null; + public static String ACTION_LOCKED_BOOT_COMPLETED = null; + public static String ACTION_MAIN = null; + public static String ACTION_MANAGED_PROFILE_ADDED = null; + public static String ACTION_MANAGED_PROFILE_AVAILABLE = null; + public static String ACTION_MANAGED_PROFILE_REMOVED = null; + public static String ACTION_MANAGED_PROFILE_UNAVAILABLE = null; + public static String ACTION_MANAGED_PROFILE_UNLOCKED = null; + public static String ACTION_MANAGE_NETWORK_USAGE = null; + public static String ACTION_MANAGE_PACKAGE_STORAGE = null; + public static String ACTION_MEDIA_BAD_REMOVAL = null; + public static String ACTION_MEDIA_BUTTON = null; + public static String ACTION_MEDIA_CHECKING = null; + public static String ACTION_MEDIA_EJECT = null; + public static String ACTION_MEDIA_MOUNTED = null; + public static String ACTION_MEDIA_NOFS = null; + public static String ACTION_MEDIA_REMOVED = null; + public static String ACTION_MEDIA_SCANNER_FINISHED = null; + public static String ACTION_MEDIA_SCANNER_SCAN_FILE = null; + public static String ACTION_MEDIA_SCANNER_STARTED = null; + public static String ACTION_MEDIA_SHARED = null; + public static String ACTION_MEDIA_UNMOUNTABLE = null; + public static String ACTION_MEDIA_UNMOUNTED = null; + public static String ACTION_MY_PACKAGE_REPLACED = null; + public static String ACTION_MY_PACKAGE_SUSPENDED = null; + public static String ACTION_MY_PACKAGE_UNSUSPENDED = null; + public static String ACTION_NEW_OUTGOING_CALL = null; + public static String ACTION_OPEN_DOCUMENT = null; + public static String ACTION_OPEN_DOCUMENT_TREE = null; + public static String ACTION_PACKAGES_SUSPENDED = null; + public static String ACTION_PACKAGES_UNSUSPENDED = null; + public static String ACTION_PACKAGE_ADDED = null; + public static String ACTION_PACKAGE_CHANGED = null; + public static String ACTION_PACKAGE_DATA_CLEARED = null; + public static String ACTION_PACKAGE_FIRST_LAUNCH = null; + public static String ACTION_PACKAGE_FULLY_REMOVED = null; + public static String ACTION_PACKAGE_INSTALL = null; + public static String ACTION_PACKAGE_NEEDS_VERIFICATION = null; + public static String ACTION_PACKAGE_REMOVED = null; + public static String ACTION_PACKAGE_REPLACED = null; + public static String ACTION_PACKAGE_RESTARTED = null; + public static String ACTION_PACKAGE_VERIFIED = null; + public static String ACTION_PASTE = null; + public static String ACTION_PICK = null; + public static String ACTION_PICK_ACTIVITY = null; + public static String ACTION_POWER_CONNECTED = null; + public static String ACTION_POWER_DISCONNECTED = null; + public static String ACTION_POWER_USAGE_SUMMARY = null; + public static String ACTION_PROCESS_TEXT = null; + public static String ACTION_PROVIDER_CHANGED = null; + public static String ACTION_QUICK_CLOCK = null; + public static String ACTION_QUICK_VIEW = null; + public static String ACTION_REBOOT = null; + public static String ACTION_RUN = null; + public static String ACTION_SCREEN_OFF = null; + public static String ACTION_SCREEN_ON = null; + public static String ACTION_SEARCH = null; + public static String ACTION_SEARCH_LONG_PRESS = null; + public static String ACTION_SEND = null; + public static String ACTION_SENDTO = null; + public static String ACTION_SEND_MULTIPLE = null; + public static String ACTION_SET_WALLPAPER = null; + public static String ACTION_SHOW_APP_INFO = null; + public static String ACTION_SHUTDOWN = null; + public static String ACTION_SYNC = null; + public static String ACTION_SYSTEM_TUTORIAL = null; + public static String ACTION_TIMEZONE_CHANGED = null; + public static String ACTION_TIME_CHANGED = null; + public static String ACTION_TIME_TICK = null; + public static String ACTION_TRANSLATE = null; + public static String ACTION_UID_REMOVED = null; + public static String ACTION_UMS_CONNECTED = null; + public static String ACTION_UMS_DISCONNECTED = null; + public static String ACTION_UNINSTALL_PACKAGE = null; + public static String ACTION_USER_BACKGROUND = null; + public static String ACTION_USER_FOREGROUND = null; + public static String ACTION_USER_INITIALIZE = null; + public static String ACTION_USER_PRESENT = null; + public static String ACTION_USER_UNLOCKED = null; + public static String ACTION_VIEW = null; + public static String ACTION_VIEW_LOCUS = null; + public static String ACTION_VIEW_PERMISSION_USAGE = null; + public static String ACTION_VOICE_COMMAND = null; + public static String ACTION_WALLPAPER_CHANGED = null; + public static String ACTION_WEB_SEARCH = null; + public static String CATEGORY_ALTERNATIVE = null; + public static String CATEGORY_APP_BROWSER = null; + public static String CATEGORY_APP_CALCULATOR = null; + public static String CATEGORY_APP_CALENDAR = null; + public static String CATEGORY_APP_CONTACTS = null; + public static String CATEGORY_APP_EMAIL = null; + public static String CATEGORY_APP_FILES = null; + public static String CATEGORY_APP_GALLERY = null; + public static String CATEGORY_APP_MAPS = null; + public static String CATEGORY_APP_MARKET = null; + public static String CATEGORY_APP_MESSAGING = null; + public static String CATEGORY_APP_MUSIC = null; + public static String CATEGORY_BROWSABLE = null; + public static String CATEGORY_CAR_DOCK = null; + public static String CATEGORY_CAR_MODE = null; + public static String CATEGORY_DEFAULT = null; + public static String CATEGORY_DESK_DOCK = null; + public static String CATEGORY_DEVELOPMENT_PREFERENCE = null; + public static String CATEGORY_EMBED = null; + public static String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST = null; + public static String CATEGORY_HE_DESK_DOCK = null; + public static String CATEGORY_HOME = null; + public static String CATEGORY_INFO = null; + public static String CATEGORY_LAUNCHER = null; + public static String CATEGORY_LEANBACK_LAUNCHER = null; + public static String CATEGORY_LE_DESK_DOCK = null; + public static String CATEGORY_MONKEY = null; + public static String CATEGORY_OPENABLE = null; + public static String CATEGORY_PREFERENCE = null; + public static String CATEGORY_SAMPLE_CODE = null; + public static String CATEGORY_SECONDARY_HOME = null; + public static String CATEGORY_SELECTED_ALTERNATIVE = null; + public static String CATEGORY_TAB = null; + public static String CATEGORY_TEST = null; + public static String CATEGORY_TYPED_OPENABLE = null; + public static String CATEGORY_UNIT_TEST = null; + public static String CATEGORY_VOICE = null; + public static String CATEGORY_VR_HOME = null; + public static String EXTRA_ALARM_COUNT = null; + public static String EXTRA_ALLOW_MULTIPLE = null; + public static String EXTRA_ALLOW_REPLACE = null; + public static String EXTRA_ALTERNATE_INTENTS = null; + public static String EXTRA_ASSIST_CONTEXT = null; + public static String EXTRA_ASSIST_INPUT_DEVICE_ID = null; + public static String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = null; + public static String EXTRA_ASSIST_PACKAGE = null; + public static String EXTRA_ASSIST_UID = null; + public static String EXTRA_AUTO_LAUNCH_SINGLE_CHOICE = null; + public static String EXTRA_BCC = null; + public static String EXTRA_BUG_REPORT = null; + public static String EXTRA_CC = null; + public static String EXTRA_CHANGED_COMPONENT_NAME = null; + public static String EXTRA_CHANGED_COMPONENT_NAME_LIST = null; + public static String EXTRA_CHANGED_PACKAGE_LIST = null; + public static String EXTRA_CHANGED_UID_LIST = null; + public static String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = null; + public static String EXTRA_CHOOSER_TARGETS = null; + public static String EXTRA_CHOSEN_COMPONENT = null; + public static String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = null; + public static String EXTRA_COMPONENT_NAME = null; + public static String EXTRA_CONTENT_ANNOTATIONS = null; + public static String EXTRA_CONTENT_QUERY = null; + public static String EXTRA_DATA_REMOVED = null; + public static String EXTRA_DOCK_STATE = null; + public static String EXTRA_DONT_KILL_APP = null; + public static String EXTRA_DURATION_MILLIS = null; + public static String EXTRA_EMAIL = null; + public static String EXTRA_EXCLUDE_COMPONENTS = null; + public static String EXTRA_FROM_STORAGE = null; + public static String EXTRA_HTML_TEXT = null; + public static String EXTRA_INDEX = null; + public static String EXTRA_INITIAL_INTENTS = null; + public static String EXTRA_INSTALLER_PACKAGE_NAME = null; + public static String EXTRA_INTENT = null; + public static String EXTRA_KEY_EVENT = null; + public static String EXTRA_LOCAL_ONLY = null; + public static String EXTRA_LOCUS_ID = null; + public static String EXTRA_MIME_TYPES = null; + public static String EXTRA_NOT_UNKNOWN_SOURCE = null; + public static String EXTRA_ORIGINATING_URI = null; + public static String EXTRA_PACKAGE_NAME = null; + public static String EXTRA_PHONE_NUMBER = null; + public static String EXTRA_PROCESS_TEXT = null; + public static String EXTRA_PROCESS_TEXT_READONLY = null; + public static String EXTRA_QUICK_VIEW_FEATURES = null; + public static String EXTRA_QUIET_MODE = null; + public static String EXTRA_REFERRER = null; + public static String EXTRA_REFERRER_NAME = null; + public static String EXTRA_REMOTE_INTENT_TOKEN = null; + public static String EXTRA_REPLACEMENT_EXTRAS = null; + public static String EXTRA_REPLACING = null; + public static String EXTRA_RESTRICTIONS_BUNDLE = null; + public static String EXTRA_RESTRICTIONS_INTENT = null; + public static String EXTRA_RESTRICTIONS_LIST = null; + public static String EXTRA_RESULT_RECEIVER = null; + public static String EXTRA_RETURN_RESULT = null; + public static String EXTRA_SHORTCUT_ICON = null; + public static String EXTRA_SHORTCUT_ICON_RESOURCE = null; + public static String EXTRA_SHORTCUT_ID = null; + public static String EXTRA_SHORTCUT_INTENT = null; + public static String EXTRA_SHORTCUT_NAME = null; + public static String EXTRA_SHUTDOWN_USERSPACE_ONLY = null; + public static String EXTRA_SPLIT_NAME = null; + public static String EXTRA_STREAM = null; + public static String EXTRA_SUBJECT = null; + public static String EXTRA_SUSPENDED_PACKAGE_EXTRAS = null; + public static String EXTRA_TEMPLATE = null; + public static String EXTRA_TEXT = null; + public static String EXTRA_TITLE = null; + public static String EXTRA_UID = null; + public static String EXTRA_USER = null; + public static String METADATA_DOCK_HOME = null; + public static String normalizeMimeType(String p0){ return null; } + public static int EXTRA_DOCK_STATE_CAR = 0; + public static int EXTRA_DOCK_STATE_DESK = 0; + public static int EXTRA_DOCK_STATE_HE_DESK = 0; + public static int EXTRA_DOCK_STATE_LE_DESK = 0; + public static int EXTRA_DOCK_STATE_UNDOCKED = 0; + public static int FILL_IN_ACTION = 0; + public static int FILL_IN_CATEGORIES = 0; + public static int FILL_IN_CLIP_DATA = 0; + public static int FILL_IN_COMPONENT = 0; + public static int FILL_IN_DATA = 0; + public static int FILL_IN_IDENTIFIER = 0; + public static int FILL_IN_PACKAGE = 0; + public static int FILL_IN_SELECTOR = 0; + public static int FILL_IN_SOURCE_BOUNDS = 0; + public static int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 0; + public static int FLAG_ACTIVITY_CLEAR_TASK = 0; + public static int FLAG_ACTIVITY_CLEAR_TOP = 0; + public static int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0; + public static int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 0; + public static int FLAG_ACTIVITY_FORWARD_RESULT = 0; + public static int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 0; + public static int FLAG_ACTIVITY_LAUNCH_ADJACENT = 0; + public static int FLAG_ACTIVITY_MATCH_EXTERNAL = 0; + public static int FLAG_ACTIVITY_MULTIPLE_TASK = 0; + public static int FLAG_ACTIVITY_NEW_DOCUMENT = 0; + public static int FLAG_ACTIVITY_NEW_TASK = 0; + public static int FLAG_ACTIVITY_NO_ANIMATION = 0; + public static int FLAG_ACTIVITY_NO_HISTORY = 0; + public static int FLAG_ACTIVITY_NO_USER_ACTION = 0; + public static int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 0; + public static int FLAG_ACTIVITY_REORDER_TO_FRONT = 0; + public static int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 0; + public static int FLAG_ACTIVITY_RETAIN_IN_RECENTS = 0; + public static int FLAG_ACTIVITY_SINGLE_TOP = 0; + public static int FLAG_ACTIVITY_TASK_ON_HOME = 0; + public static int FLAG_DEBUG_LOG_RESOLUTION = 0; + public static int FLAG_DIRECT_BOOT_AUTO = 0; + public static int FLAG_EXCLUDE_STOPPED_PACKAGES = 0; + public static int FLAG_FROM_BACKGROUND = 0; + public static int FLAG_GRANT_PERSISTABLE_URI_PERMISSION = 0; + public static int FLAG_GRANT_PREFIX_URI_PERMISSION = 0; + public static int FLAG_GRANT_READ_URI_PERMISSION = 0; + public static int FLAG_GRANT_WRITE_URI_PERMISSION = 0; + public static int FLAG_INCLUDE_STOPPED_PACKAGES = 0; + public static int FLAG_RECEIVER_FOREGROUND = 0; + public static int FLAG_RECEIVER_NO_ABORT = 0; + public static int FLAG_RECEIVER_REGISTERED_ONLY = 0; + public static int FLAG_RECEIVER_REPLACE_PENDING = 0; + public static int FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS = 0; + public static int URI_ALLOW_UNSAFE = 0; + public static int URI_ANDROID_APP_SCHEME = 0; + public static int URI_INTENT_SCHEME = 0; + public void readFromParcel(Parcel p0){} + public void removeCategory(String p0){} + public void removeExtra(String p0){} + public void removeFlags(int p0){} + public void setClipData(ClipData p0){} + public void setExtrasClassLoader(ClassLoader p0){} + public void setSelector(Intent p0){} + public void setSourceBounds(Rect p0){} + public void writeToParcel(Parcel p0, int p1){} } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/SharedPreferences.java b/java/ql/test/stubs/google-android-9.0.0/android/content/SharedPreferences.java index faac2f1d41e..90cdc242501 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/SharedPreferences.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/SharedPreferences.java @@ -1,362 +1,38 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Generated automatically from android.content.SharedPreferences for testing purposes + package android.content; import java.util.Map; import java.util.Set; -/** - * Interface for accessing and modifying preference data returned by {@link - * Context#getSharedPreferences}. For any particular set of preferences, - * there is a single instance of this class that all clients share. - * Modifications to the preferences must go through an {@link Editor} object - * to ensure the preference values remain in a consistent state and control - * when they are committed to storage. Objects that are returned from the - * various <code>get</code> methods must be treated as immutable by the application. - * - * <p><em>Note: currently this class does not support use across multiple - * processes. This will be added later.</em> - * - * <div class="special reference"> - * <h3>Developer Guides</h3> - * <p>For more information about using SharedPreferences, read the - * <a href="{@docRoot}guide/topics/data/data-storage.html#pref">Data Storage</a> - * developer guide.</p></div> - * - * @see Context#getSharedPreferences - */ -public interface SharedPreferences { - /** - * Interface definition for a callback to be invoked when a shared - * preference is changed. - */ - public interface OnSharedPreferenceChangeListener { - /** - * Called when a shared preference is changed, added, or removed. This - * may be called even if a preference is set to its existing value. - * - * <p>This callback will be run on your main thread. - * - * @param sharedPreferences The {@link SharedPreferences} that received - * the change. - * @param key The key of the preference that was changed, added, or - * removed. - */ - void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key); - } - - /** - * Interface used for modifying values in a {@link SharedPreferences} - * object. All changes you make in an editor are batched, and not copied - * back to the original {@link SharedPreferences} until you call {@link #commit} - * or {@link #apply} - */ - public interface Editor { - /** - * Set a String value in the preferences editor, to be written back once - * {@link #commit} or {@link #apply} are called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. Supplying {@code null} - * as the value is equivalent to calling {@link #remove(String)} with - * this key. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putString(String key, String value); - - /** - * Set a set of String values in the preferences editor, to be written - * back once {@link #commit} is called. - * - * @param key The name of the preference to modify. - * @param values The set of new values for the preference. Passing {@code null} - * for this argument is equivalent to calling {@link #remove(String)} with - * this key. - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putStringSet(String key, Set<String> values); - - /** - * Set an int value in the preferences editor, to be written back once - * {@link #commit} or {@link #apply} are called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putInt(String key, int value); - - /** - * Set a long value in the preferences editor, to be written back once - * {@link #commit} or {@link #apply} are called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putLong(String key, long value); - - /** - * Set a float value in the preferences editor, to be written back once - * {@link #commit} or {@link #apply} are called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putFloat(String key, float value); - - /** - * Set a boolean value in the preferences editor, to be written back - * once {@link #commit} or {@link #apply} are called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putBoolean(String key, boolean value); - /** - * Mark in the editor that a preference value should be removed, which - * will be done in the actual preferences once {@link #commit} is - * called. - * - * <p>Note that when committing back to the preferences, all removals - * are done first, regardless of whether you called remove before - * or after put methods on this editor. - * - * @param key The name of the preference to remove. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor remove(String key); - /** - * Mark in the editor to remove <em>all</em> values from the - * preferences. Once commit is called, the only remaining preferences - * will be any that you have defined in this editor. - * - * <p>Note that when committing back to the preferences, the clear - * is done first, regardless of whether you called clear before - * or after put methods on this editor. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor clear(); - /** - * Commit your preferences changes back from this Editor to the - * {@link SharedPreferences} object it is editing. This atomically - * performs the requested modifications, replacing whatever is currently - * in the SharedPreferences. - * - * <p>Note that when two editors are modifying preferences at the same - * time, the last one to call commit wins. - * - * <p>If you don't care about the return value and you're - * using this from your application's main thread, consider - * using {@link #apply} instead. - * - * @return Returns true if the new values were successfully written - * to persistent storage. - */ + +public interface SharedPreferences +{ + Map<String, ? extends Object> getAll(); + Set<String> getStringSet(String p0, Set<String> p1); + SharedPreferences.Editor edit(); + String getString(String p0, String p1); + boolean contains(String p0); + boolean getBoolean(String p0, boolean p1); + float getFloat(String p0, float p1); + int getInt(String p0, int p1); + long getLong(String p0, long p1); + static public interface Editor + { + SharedPreferences.Editor clear(); + SharedPreferences.Editor putBoolean(String p0, boolean p1); + SharedPreferences.Editor putFloat(String p0, float p1); + SharedPreferences.Editor putInt(String p0, int p1); + SharedPreferences.Editor putLong(String p0, long p1); + SharedPreferences.Editor putString(String p0, String p1); + SharedPreferences.Editor putStringSet(String p0, Set<String> p1); + SharedPreferences.Editor remove(String p0); boolean commit(); - /** - * Commit your preferences changes back from this Editor to the - * {@link SharedPreferences} object it is editing. This atomically - * performs the requested modifications, replacing whatever is currently - * in the SharedPreferences. - * - * <p>Note that when two editors are modifying preferences at the same - * time, the last one to call apply wins. - * - * <p>Unlike {@link #commit}, which writes its preferences out - * to persistent storage synchronously, {@link #apply} - * commits its changes to the in-memory - * {@link SharedPreferences} immediately but starts an - * asynchronous commit to disk and you won't be notified of - * any failures. If another editor on this - * {@link SharedPreferences} does a regular {@link #commit} - * while a {@link #apply} is still outstanding, the - * {@link #commit} will block until all async commits are - * completed as well as the commit itself. - * - * <p>As {@link SharedPreferences} instances are singletons within - * a process, it's safe to replace any instance of {@link #commit} with - * {@link #apply} if you were already ignoring the return value. - * - * <p>You don't need to worry about Android component - * lifecycles and their interaction with <code>apply()</code> - * writing to disk. The framework makes sure in-flight disk - * writes from <code>apply()</code> complete before switching - * states. - * - * <p class='note'>The SharedPreferences.Editor interface - * isn't expected to be implemented directly. However, if you - * previously did implement it and are now getting errors - * about missing <code>apply()</code>, you can simply call - * {@link #commit} from <code>apply()</code>. - */ void apply(); } - /** - * Retrieve all values from the preferences. - * - * <p>Note that you <em>must not</em> modify the collection returned - * by this method, or alter any of its contents. The consistency of your - * stored data is not guaranteed if you do. - * - * @return Returns a map containing a list of pairs key/value representing - * the preferences. - * - * @throws NullPointerException - */ - Map<String, ?> getAll(); - /** - * Retrieve a String value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * a String. - * - * @throws ClassCastException - */ - String getString(String key, String defValue); - - /** - * Retrieve a set of String values from the preferences. - * - * <p>Note that you <em>must not</em> modify the set instance returned - * by this call. The consistency of the stored data is not guaranteed - * if you do, nor is your ability to modify the instance at all. - * - * @param key The name of the preference to retrieve. - * @param defValues Values to return if this preference does not exist. - * - * @return Returns the preference values if they exist, or defValues. - * Throws ClassCastException if there is a preference with this name - * that is not a Set. - * - * @throws ClassCastException - */ - Set<String> getStringSet(String key, Set<String> defValues); - - /** - * Retrieve an int value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * an int. - * - * @throws ClassCastException - */ - int getInt(String key, int defValue); - - /** - * Retrieve a long value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * a long. - * - * @throws ClassCastException - */ - long getLong(String key, long defValue); - - /** - * Retrieve a float value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * a float. - * - * @throws ClassCastException - */ - float getFloat(String key, float defValue); - - /** - * Retrieve a boolean value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * a boolean. - * - * @throws ClassCastException - */ - boolean getBoolean(String key, boolean defValue); - /** - * Checks whether the preferences contains a preference. - * - * @param key The name of the preference to check. - * @return Returns true if the preference exists in the preferences, - * otherwise false. - */ - boolean contains(String key); - - /** - * Create a new Editor for these preferences, through which you can make - * modifications to the data in the preferences and atomically commit those - * changes back to the SharedPreferences object. - * - * <p>Note that you <em>must</em> call {@link Editor#commit} to have any - * changes you perform in the Editor actually show up in the - * SharedPreferences. - * - * @return Returns a new instance of the {@link Editor} interface, allowing - * you to modify the values in this SharedPreferences object. - */ - Editor edit(); - - /** - * Registers a callback to be invoked when a change happens to a preference. - * - * @param listener The callback that will run. - * @see #unregisterOnSharedPreferenceChangeListener - */ - void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener); - - /** - * Unregisters a previous callback. - * - * @param listener The callback that should be unregistered. - * @see #registerOnSharedPreferenceChangeListener - */ - void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener); + static public interface OnSharedPreferenceChangeListener + { + void onSharedPreferenceChanged(SharedPreferences p0, String p1); + } + void registerOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener p0); + void unregisterOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener p0); } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/view/ContextThemeWrapper.java b/java/ql/test/stubs/google-android-9.0.0/android/view/ContextThemeWrapper.java new file mode 100644 index 00000000000..e1a65acf681 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/view/ContextThemeWrapper.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.annotation.StyleRes; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.Resources; + +/** + * A context wrapper that allows you to modify or replace the theme of the + * wrapped context. + */ +public class ContextThemeWrapper extends ContextWrapper { + /** + * Creates a new context wrapper with no theme and no base context. + * <p class="note"> + * <strong>Note:</strong> A base context <strong>must</strong> be attached + * using {@link #attachBaseContext(Context)} before calling any other + * method on the newly constructed context wrapper. + */ + public ContextThemeWrapper() { + super(null); + } + + /** + * Creates a new context wrapper with the specified theme. + * <p> + * The specified theme will be applied on top of the base context's theme. + * Any attributes not explicitly defined in the theme identified by + * <var>themeResId</var> will retain their original values. + * + * @param base the base context + * @param themeResId the resource ID of the theme to be applied on top of + * the base context's theme + */ + public ContextThemeWrapper(Context base, @StyleRes int themeResId) { + super(base); + } + + /** + * Creates a new context wrapper with the specified theme. + * <p> + * Unlike {@link #ContextThemeWrapper(Context, int)}, the theme passed to + * this constructor will completely replace the base context's theme. + * + * @param base the base context + * @param theme the theme against which resources should be inflated + */ + public ContextThemeWrapper(Context base, Resources.Theme theme) { + super(base); + } + + /** + * Call to set an "override configuration" on this context -- this is + * a configuration that replies one or more values of the standard + * configuration that is applied to the context. See + * {@link Context#createConfigurationContext(Configuration)} for more + * information. + * + * <p>This method can only be called once, and must be called before any + * calls to {@link #getResources()} or {@link #getAssets()} are made. + */ + public void applyOverrideConfiguration(Configuration overrideConfiguration) { + } + + /** + * Used by ActivityThread to apply the overridden configuration to onConfigurationChange + * callbacks. + * @hide + */ + public Configuration getOverrideConfiguration() { + return null; + } + + @Override + public AssetManager getAssets() { + return null; + } + + @Override + public Resources getResources() { + return null; + } + + private Resources getResourcesInternal() { + return null; + } + + @Override + public void setTheme(int resid) { + } + + @Override + public Resources.Theme getTheme() { + return null; + } + + @Override + public Object getSystemService(String name) { + return null; + } + + /** + * Called by {@link #setTheme} and {@link #getTheme} to apply a theme + * resource to the current Theme object. May be overridden to change the + * default (simple) behavior. This method will not be called in multiple + * threads simultaneously. + * + * @param theme the theme being modified + * @param resId the style resource being applied to <var>theme</var> + * @param first {@code true} if this is the first time a style is being + * applied to <var>theme</var> + */ + protected void onApplyThemeResource(Resources.Theme theme, int resId, boolean first) {} +} From 3c96e62be7e4733ab89f4f9618dfd2ab2a2ae49c Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 12 Oct 2021 12:34:32 +0100 Subject: [PATCH 240/361] Remove duplicate declaration --- .../ql/lib/semmle/code/java/frameworks/android/Intent.qll | 8 -------- 1 file changed, 8 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 94c95c3bcad..3798d91d99a 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -75,14 +75,6 @@ class IntentGetParcelableExtraMethod extends Method { } } -/** - * Specifies that if an `Intent` is tainted, then so are its synthetic fields. - */ -private class IntentFieldsInheritTaint extends DataFlow::SyntheticFieldContent, - TaintInheritingContent { - IntentFieldsInheritTaint() { this.getField().matches("android.content.Intent.%") } -} - private class IntentBundleFlowSteps extends SummaryModelCsv { override predicate row(string row) { row = From 296e268339df8a8e4aaf07bcf0abb202cff9b01f Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 12 Oct 2021 14:28:32 +0200 Subject: [PATCH 241/361] Apply suggestions from code review Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com> --- .../semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll | 1 - java/ql/test/library-tests/dataflow/callback-dispatch/A.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 5c65570c5a6..83076558ec4 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -958,7 +958,6 @@ module Private { query predicate edges(NodeOrCall a, NodeOrCall b, string key, string value) { key = "semmle.label" and - edgesComponent(a, b, _) and value = strictconcat(string s | edgesComponent(a, b, s) | s, " / ") } } diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java index d9d5ddc9d67..193e67fd38f 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java @@ -179,7 +179,7 @@ public class A { void foo3() { A a1 = new A(); - a1.field1 = source(1); + a1.field1 = source(20); A a2 = new A(); applyConsumer1Field1Field2(a1, a2, p -> { sink(p); // MISSING FLOW From cc305ed76654ed096618cd354d4bd59369934b20 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 12 Oct 2021 14:37:33 +0200 Subject: [PATCH 242/361] Data flow: Sync --- .../lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 5c65570c5a6..83076558ec4 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -958,7 +958,6 @@ module Private { query predicate edges(NodeOrCall a, NodeOrCall b, string key, string value) { key = "semmle.label" and - edgesComponent(a, b, _) and value = strictconcat(string s | edgesComponent(a, b, s) | s, " / ") } } From 83c6406167dce2702a8c4ba5108f13c035f05876 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 12 Oct 2021 13:51:02 +0100 Subject: [PATCH 243/361] Update javadoc --- java/ql/lib/semmle/code/java/frameworks/google/Gson.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/google/Gson.qll b/java/ql/lib/semmle/code/java/frameworks/google/Gson.qll index b0cb99bb5f8..b9329182ec9 100644 --- a/java/ql/lib/semmle/code/java/frameworks/google/Gson.qll +++ b/java/ql/lib/semmle/code/java/frameworks/google/Gson.qll @@ -22,7 +22,8 @@ class GsonDeserializeMethod extends Method { /** * Holds if `intentNode` is an `Intent` used in the context `(T)intentNode.getParcelableExtra(...)` and - * `parcelNode` is the corresponding parameter of `Parcelable.Creator<T> { public T createFromParcel(Parcel parcelNode) { }`. + * `parcelNode` is the corresponding parameter of `Parcelable.Creator<T> { public T createFromParcel(Parcel parcelNode) { }`, + * where `T` is a concrete type implementing `Parcelable`. */ predicate intentFlowsToParcel(DataFlow::Node intentNode, DataFlow::Node parcelNode) { exists(MethodAccess getParcelableExtraCall, CreateFromParcelMethod cfpm, Type createdType | From cf92e1eee7cee14cac6603c4f4f93fc4e06a4efe Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Oct 2021 15:11:00 +0200 Subject: [PATCH 244/361] Python: move getStringArgIndex --- .../lib/semmle/python/frameworks/Stdlib.qll | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 2bf198a807e..e1edb8a047b 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1584,15 +1584,15 @@ private module StdlibPrivate { RegexExecutionMethod() { this in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"] } - } - /** Gets the index of the argument representing the string to be searched by a regex. */ - int getStringArgIndex(RegexExecutionMethod method) { - method in ["match", "fullmatch", "search", "split", "findall", "finditer"] and - result = 1 - or - method in ["sub", "subn"] and - result = 2 + /** Gets the index of the argument representing the string to be searched by a regex. */ + int getStringArgIndex() { + this in ["match", "fullmatch", "search", "split", "findall", "finditer"] and + result = 1 + or + this in ["sub", "subn"] and + result = 2 + } } /** @@ -1608,7 +1608,7 @@ private module StdlibPrivate { override DataFlow::Node getRegex() { result in [this.getArg(0), this.getArgByName("pattern")] } override DataFlow::Node getString() { - result in [this.getArg(getStringArgIndex(method)), this.getArgByName("string")] + result in [this.getArg(method.getStringArgIndex()), this.getArgByName("string")] } override string getName() { result = "re." + method } @@ -1656,17 +1656,17 @@ private module StdlibPrivate { */ private class CompiledRegexExecution extends DataFlow::MethodCallNode, RegexExecution::Range { DataFlow::Node regexNode; - RegexExecutionMethod methodName; + RegexExecutionMethod method; - CompiledRegexExecution() { this.calls(compiledRegex(regexNode), methodName) } + CompiledRegexExecution() { this.calls(compiledRegex(regexNode), method) } override DataFlow::Node getRegex() { result = regexNode } override DataFlow::Node getString() { - result in [this.getArg(getStringArgIndex(methodName) - 1), this.getArgByName("string")] + result in [this.getArg(method.getStringArgIndex() - 1), this.getArgByName("string")] } - override string getName() { result = "re." + methodName } + override string getName() { result = "re." + method } } /** From 6c108e43d988afb0d08572a43eb95b7ab37d1d4e Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Oct 2021 15:16:48 +0200 Subject: [PATCH 245/361] Python: address review --- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 04f3bdf8d7b..e6a85b62b72 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -246,15 +246,16 @@ private module StdlibPrivate { // Functions with non-standard arguments: // - os.path.join(path, *paths) // - os.path.relpath(path, start=os.curdir) - // Functions that need summaries: + // these functions need special treatment when computing `getPathArg`. + // + // Functions that excluded because they can act as sanitizers: // - os.path.commonpath(paths): takes a sequence // - os.path.commonprefix(list): takes a list argument - // - os.path.splitdrive: retunrs a tuple - // - os.path.splittext: returns a tuple + // unless the user control all arguments, we are comparing with a known value. private string pathComputation() { result in [ "abspath", "basename", "commonpath", "dirname", "expanduser", "expandvars", "join", - "normcase", "normpath", "realpath", "relpath", "split" + "normcase", "normpath", "realpath", "relpath", "split", "splitdrive", "splitext" ] } From 30a00b22c92c6c7282bbb16622df82bcd0cebd67 Mon Sep 17 00:00:00 2001 From: Calum Grant <calumgrant@github.com> Date: Tue, 5 Oct 2021 14:59:40 +0100 Subject: [PATCH 246/361] CodeQL library for Ruby --- .../codeql-library-for-ruby.rst | 622 ++++++++++++++++++ .../codeql/reusables/ruby-further-reading.rst | 4 +- 2 files changed, 624 insertions(+), 2 deletions(-) create mode 100644 docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst new file mode 100644 index 00000000000..146b4eb1d90 --- /dev/null +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -0,0 +1,622 @@ +.. codeql-library-for-ruby: + +CodeQL library for Ruby +======================= + +When you're analyzing a Ruby program, you can make use of the large collection of classes in the CodeQL library for Ruby. + +Overview +-------- + +CodeQL ships with an extensive library for analyzing Ruby code. The classes in this library present +the data from a CodeQL database in an object-oriented form and provide abstractions and predicates +to help you with common analysis tasks. + +The library is implemented as a set of CodeQL modules, that is, files with the extension ``.qll``. The +module `ruby.qll <https://github.com/github/codeql/blob/main/ruby/ql/lib/ruby.qll>`__ imports most other standard library modules, so you can include the complete +library by beginning your query with: + +.. code-block:: ql + + import ruby + +The CodeQL libraries model various aspects of Ruby code, depending on the type of query you want to write. +For example the abstract syntax tree (AST) library is used for locating program elements, to match syntactic +elements in the source code. This can be used to find values, patterns and structures. + +The control flow graph (CFG) is imported using + +.. code-block:: ql + + import codeql.ruby.CFG + +The CFG reasons about the control flow between statements and expressions, for example whether one expression can +flow to another expression, or whether an expression "dominates" another one, meaning that all paths to an +expression must flow through another expression first. + +The data flow library is imported using + +.. code-block:: ql + + import codeql.ruby.DataFlow + +Data flow tracks the flow of data through the program, including through function calls (interprocedural data flow). +Data flow is particularly useful for security queries, where untrusted data flow to vulnerable parts of the program +to exploit it. Related to data flow, is the taint-tracking library, which finds how data can *influence* other values +in a program, even when it is not copied exactly. + +The API graphs library is used to locate methods in libraries. This is particuarly useful when locating +particular functions or parameters that could be used as a source or sink of data in a security query. + +To summarise, the main Ruby modules are: + +.. list-table:: Main Ruby modules + :header-rows: 1 + + * - Import + - Description + * - ``ruby`` + - The standard Ruby library + * - ``codeql.ruby.AST`` + - The abstract syntax tree library (also imported by `ruby.qll`) + * - ``codeql.ruby.ApiGraphs`` + - The API graphs library + * - ``codeql.ruby.CFG`` + - The control flow graph library + * - ``codeql.ruby.DataFlow`` + - The data flow library + * - ``codeql.ruby.TaintTracking`` + - The taint tracking library + +The CodeQL examples are only excerpts and are not meant to represent complete queries. + +Abstract syntax +--------------- + +The abstract syntax tree (AST) represents the elements of the source code organised into a tree. The AST viewer +feature of Visual Studio Code shows the AST nodes, including the relevant CodeQL classes and predicates. + +All CodeQL AST classes inherit from the `AstNode` class, which provides the following member predicates +to all AST classes: + +.. list-table:: Main predicates in ``AstNode`` + :header-rows: 1 + + * - Predicate + - Description + * - ``getEnclosingModule()`` + - Gets the enclosing module, if any. + * - ``getEnclosingMethod()`` + - Gets the enclosing method, if any. + * - ``getLocation()`` + - Gets the location of this node. + * - ``getAChild()`` + - Gets a child node of this node. + * - ``getParent()`` + - Gets the parent of this `AstNode`, if this node is not a root node. + * - ``getDesugared`` + - Gets the desugared version of this AST node, if any. + * - ``isSynthesized()`` + - Holds if this node was synthesized to represent an implicit AST node not + present in the source code. + +Modules +~~~~~~~ + +Modules represent the main structural elements of Ruby programs, and include modules (``Module``), +namespaces (``Namespace``) and classes (``ClassDeclaration``). + +.. list-table:: Callable classes + :header-rows: 1 + + * - CodeQL class + - Description and selected predicates + * - ``Module`` + - A representation of a run-time `module` or `class` value. + + - `getADeclaration()` - Gets a declaration + - `getSuperClass()` - Gets the super class fo this module, if any. + - `getAPrependedModule()` - Gets a prepended module. + - `getAnIncludedModule()` - Gets an included module. + * - ``Namespace`` + - A class or module definition. + + - `getName()` - Gets the name of the module/class. + - `getAMethod()`, `getMethod(name)` - Gets a method in this namespace. + - `getAClass()`, `getClass(name)` - Gets a class in this namespace. + - `getAModule()`, `getModule(name)` - Gets a module in this namespace. + * - ``ClassDeclaration`` + - A class definition. + * - ``SingletonClass`` + - A definition of a singleton class on an object. + * - ``ModuleDeclaration`` + - A module definition. + * - ``Toplevel`` + - The node representing the entire Ruby source file. + +The following example lists all methods in the class `ApiController`: + +.. code-block:: ql + + import ruby + + from ClassDeclaration m + where m.getName() = "ApiController" + select m, m.getAMethod() + +Callables +~~~~~~~~~ + +`Callables` are elements that can be called, including methods and blocks. + +.. list-table:: Callable classes + :header-rows: 1 + + * - CodeQL class + - Description and main predicates + * - ``Callable`` + - A callable. + + - `getAParameter()` - gets a parameter of this callable. + - `getParameter(n)` - gets the nth parameter of this callable. + * - ``Private`` + - A call to ``private``. + * - ``Method`` + - A method. + + - `getName()` - gets the name of this method + * - ``SingletonMethod`` + - A singleton method. + * - ``Lambda`` + - A lambda (anonymous method). + * - ``Block`` + - A block. + * - ``DoBlock`` + - A block enclosed within `do` and `end`. + * - ``BraceBlock`` + - A block defined using curly braces. + +*Parameters* are the values that are passed into callables. Unlike other CodeQL language models, +parameters in Ruby are not variables themselves, but can introduce variables into the +callable. The variables of a parameter are given by the `getAVariable()` predicate. + +.. list-table:: Parameter classes + :header-rows: 1 + + * - CodeQL class + - Description and main predicates + * - ``Parameter`` + - A parameter. + + - `getCallable()` - Gets the callable that this parameter belongs to. + - `getPosition()` - Gets the zero-based position of this parameter. + - `getAVariable()`, `getVariable(name)` - Gets a variable introduced by this parameter. + * - ``PatternParameter`` + - A parameter defined using a pattern. + * - ``TuplePatternParameter`` + - A parameter defined using a tuple pattern. + * - ``NamedParameter`` + - A named parameter. + + - `getName()`, `hasName(name)` - Gets the name of this parameter. + - `getAnAccess()` - Gets an access to this parameter. + - `getDefiningAccess()` - Gets the access that defines the underlying local variable. + * - ``SimpleParameter`` + - A simple (normal) parameter. + * - ``BlockParameter`` + - A parameter that is a block. + * - ``HashSplatParameter`` + - A hash-splat (or double-splat) parameter. + * - ``KeywordParameter`` + - A keyword parameter, including a default value if the parameter is optional. + + - `getDefaultValue()` - Gets the default value, i.e. the value assigned to the parameter when one is not provided by the caller. + * - ``OptionalParameter`` + - An optional parameter. + + - `getDefaultValue()` - Gets the default value, i.e. the value assigned to the parameter when one is not provided by the caller. + * - ``SplatParameter`` + - A splat parameter. + + +Example + +.. code-block:: ql + + import ruby + + from Method m + where m.getName() = "show" + select m.getParameter(0) + +Statements +~~~~~~~~~~ + +Statements are the elements of code blocks. Statements that produce a value are called *expressions* +and have CodeQL class `Expr`. The remaining statement types (that do not produce values) are listed below. + +.. list-table:: Statement classes + :header-rows: 1 + + * - CodeQL class + - Description and main predicates + * - ``Stmt`` + - The base class for all statements. + + - `getAControlFlowNode()` - Gets a control-flow node for this statement, if any. + - `getEnclosingCallable()` - Gets the enclosing callable, if any. + * - ``EmptyStmt`` + - An empty statement. + * - ``BeginExpr`` + - A `begin` statement. + * - ``BeginBlock`` + - A `BEGIN` block. + * - ``EndBlock`` + - An `END` block. + * - ``UndefStmt`` + - An `undef` statement. + * - ``AliasStmt`` + - An `alias` statement. + * - ``ReturningStmt`` + - A statement that may return a value: `return`, `break` and `next`. + * - ``ReturnStmt`` + - A `return` statement. + * - ``BreakStmt`` + - A `break` statement. + * - ``NextStmt`` + - A `next` statement. + * - ``RedoStmt`` + - A `redo` statement. + * - ``RetryStmt`` + - A `retry` statement. + +The following example finds all literals that are returned by a `return` statement. + +.. code-block:: ql + + import ruby + + from ReturnStmt return, Literal lit + where lit.getParent() = return + select lit, "Returning a literal " + lit.getValueText() + +Expressions +~~~~~~~~~~~ + +Expressions are types of statement that evaluate to a value. The CodeQL class `Expr` is the base class of all expression types. + +.. list-table:: Expressions + :header-rows: 1 + + * - CodeQL class + - Description and main predicates + * - ``Expr`` + - An expression. + + This is the root class for all expressions. + + - `getValueText()` - Gets the textual (constant) value of this expression, if any. + * - ``Self`` + - A reference to the current object. + * - ``Pair`` + - A pair expression. + * - ``RescueClause`` + - A `rescue` clause. + * - ``RescueModifierExpr`` + - An expression with a `rescue` modifier. + * - ``StringConcatenation`` + - A concatenation of string literals. + + - `getConcatenatedValueText()` - Gets the result of concatenating all the string literals, if and only if they do not contain any interpolations. + +.. list-table:: Statement sequences + :header-rows: 1 + + * - CodeQL class + - Description + * - ``StmtSequence`` + - A sequence of expressions. + + - `getAStmt()`, `getStmt(n)` - Gets a statement in this sequence. + - `isEmpty()` - Holds if this sequence has no statements. + - `getNumberOfStatements()` - Gets the number of statements in this sequence. + * - ``BodyStmt`` + - A sequence of statements representing the body of a method, class, module, or do-block. + + - `getARescue()`, `getRescue(n)` - Gets a rescue clause in this block. + - `getElse()` - Gets the `else` clause in this block, if any. + - `getEnsure()` - Gets the `ensure` clause in this block, if any. + * - ``ParenthesizedExpr`` + - A parenthesized expression sequence, typically containing a single expression. + + +Literals are expressions that evaluate directly to the given value. The CodeQL Ruby library models all types of +Ruby literal. + +.. list-table:: Literals + :header-rows: 1 + + * - CodeQL class + - Description + * - ``Literal`` + - A literal. This is the base class for all literals. + + - `getValueText()` - Gets the source text for this literal, if this is a simple literal. + * - ``NumericLiteral`` + - A numerical literal. The literal types are ``IntegerLiteral``, ``FloatLiteral``, ``RationalLiteral``, and ``ComplexLiteral``. + * - ``NilLiteral`` + - A `nil` literal. + * - ``BooleanLiteral`` + - A Boolean value. The classes ``TrueLiteral`` and ``FalseLiteral`` match `true` and `false` respectively. + * - ``StringComponent`` + - A component of a string. Either a ``StringTextComponent``, ``StringEscapeSequenceComponent``, or ``StringInterpolationComponent``. + * - ``RegExpLiteral`` + - A regular expression literal. + * - ``SymbolLiteral`` + - A symbol literal. + * - ``SubshellLiteral`` + - A subshell literal. + * - ``CharacterLiteral`` + - A character literal. + * - ``ArrayLiteral`` + - An array literal. + * - ``HashLiteral`` + - A hash literal. + * - ``RangeLiteral`` + - A range literal. + * - ``MethodName`` + - A method name literal. + +The following example defines a string literal class containing the text "username": + +.. code-block:: ql + + class UsernameLiteral extends Literal + { + UsernameLiteral() { this.getValueText().toLowerCase().matches("%username%") } + } + + +*Operations* are types of expression that typically perform some sort of calculation. Most operations are ``MethodCalls`` because often +there is an underlying call to the operation. + +.. list-table:: Operations + :header-rows: 1 + + * - CodeQL class + - Description + * - ``Operation`` + - An operation. + * - ``UnaryOperation`` + - A unary operation. + + Types of unary operation include ``UnaryLogicalOperation``, ``NotExpr``, ``UnaryPlusExpr``, ``UnaryMinusExpr``, ``SplatExpr``, + ``HashSplatExpr``, ``UnaryBitwiseOperation``, and ``ComplementExpr``. + * - ``DefinedExpr`` + - A call to the special `defined?` operator + * - ``BinaryOperation`` + - A binary operation, that includes many other operation categories such as ``BinaryArithmeticOperation``, ``BinaryBitwiseOperation``, ``ComparisonOperation``, ``SpaceshipExpr``, and ``Assignment``. + * - ``BinaryArithmeticOperation`` + - A binary arithmetic operation. Includes: ``AddExpr``, ``SubExpr``, ``MulExpr``, ``DivExpr``, ``ModuloExpr``, and ``ExponentExpr``. + * - ``BinaryLogicalOperation`` + - A binary logical operation. Includes: ``LogicalAndExpr`` and ``LogicalOrExpr``. + * - ``BinaryBitwiseOperation`` + - A binary bitwise operation. Includes: ``LShiftExpr``, ``RShiftExpr``, ``BitwiseAndExpr``, ``BitwiseOrExpr``, and ``BitwiseXorExpr``. + * - ``ComparisonOperation`` + - A comparison operation, including the classes ``EqualityOperation``, ``EqExpr``, ``NEExpr``, ``CaseEqExpr``, ``RelationalOperation``, ``GTExpr``, ``GEExpr``, ``LTExpr``, and ``LEExpr``. + * - ``RegExpMatchExpr`` + - A regexp match expression. + * - ``NoRegExpMatchExpr`` + - A regexp-doesn't-match expression. + * - ``Assignment`` + - An assignment. Assignments are simple assignments (``AssignExpr``), or assignment operations (``AssignOperation``). + + The assignment arithmetic operations (``AssignArithmeticOperation``) are ``AssignAddExpr``, ``AssignSubExpr``, ``AssignMulExpr``, ``AssignDivExpr``, ``AssignModuloExpr``, and ``AssignExponentExpr``. + + The assignment logical operations (``AssignLogicalOperation``) are ``AssignLogicalAndExpr`` and ``AssignLogicalOrExpr``. + + The assignment bitwise operations (``AssignBitwiseOperation``) are ``AssignLShiftExpr``, ``AssignRShiftExpr``, ``AssignBitwiseAndExpr``, ``AssignBitwiseOrExpr``, and ``AssignBitwiseXorExpr``. + +The following example finds "chained assignments" (of the form ``A=B=C``): + +.. code-block:: ql + + import ruby + + from Assignment op + where op.getRightOperand() instanceof Assignment + select op, "This is a chained assignment." + +Calls pass control to another function, include explicit method calls (``MethodCall``), but also include other types of call such as `super` calls or `yield` calls. + +.. list-table:: Calls + :header-rows: 1 + + * - CodeQL class + - Description and main predicates + * - ``Call`` + - A call. + + - `getArgument(n)`, `getAnArgument()`, `getKeywordArgument(keyword)` - Gets an argument of this call. + - `getATarget()` - Gets a potential target of this call, if any. + * - ``MethodCall`` + - A method call. + + - `getReceiver()` - Gets the receiver of this call, if any. This is the object being invoked. + - `getMethodName()` - Gets the name of the method being called. + - `getBlock()` - Gets the block of this method call, if any. + * - ``SetterMethodCall`` + - A call to a setter method. + * - ``ElementReference`` + - An element reference; a call to the `[]` method. + * - ``YieldCall`` + - A call to `yield`. + * - ``SuperCall`` + - A call to `super`. + * - ``BlockArgument`` + - A block argument in a method call. + +The following example finds all method calls to a method called `delete`. + +.. code-block:: ql + + import ruby + + from MethodCall call + where call.getMethodName() = "delete" + select call, "Call to 'delete'." + +Control expressions are expressions used for control flow. They are classed as expressions because they can produce a value. + +.. list-table:: Control expressions + :header-rows: 1 + + * - CodeQL class + - Description and main predicates + * - ``ControlExpr`` + - A control expression, such as a `case`, `if`, `unless`, ternary-if (`?:`), `while`, `until` (including expression-modifier variants), and `for`. + * - ``ConditionalExpr`` + - A conditional expression. + + - `getCondition()` - Gets the condition expression. + * - ``IfExpr`` + - An `if` or `elsif` expression. + + - `getThen()` - Gets the `then` branch. + - `getElse()` - Gets the `elseif` or `else` branch. + * - ``UnlessExpr`` + - An `unless` expression. + * - ``IfModifierExpr`` + - An expression modified using `if`. + * - ``UnlessModifierExpr`` + - An expression modified using `unless`. + * - ``TernaryIfExpr`` + - A conditional expression using the ternary (`?:`) operator. + * - ``CaseExpr`` + - A `case` expression. + * - ``WhenExpr`` + - A `when` branch of a `case` expression. + * - ``Loop`` + - A loop. That is, a `for` loop, a `while` or `until` loop, or their expression-modifier variants. + * - ``ConditionalLoop`` + - A loop using a condition expression. That is, a `while` or `until` loop, or their expression-modifier variants. + + - `getCondition()` - Gets the condition expression of this loop. + * - ``WhileExpr`` + - A `while` loop. + * - ``UntilExpr`` + - An `until` loop. + * - ``WhileModifierExpr`` + - An expression looped using the `while` modifier. + * - ``UntilModifierExpr`` + - An expression looped using the `until` modifier. + * - ``ForExpr`` + - A `for` loop. + +The following example finds `if`-expressions that are missing a `then` branch. + +.. code-block:: ql + + import ruby + + from IfExpr expr + where not exists(expr.getThen()) + select expr, "This if-expression is redundant." + +Variables +~~~~~~~~~ + +*Variables* are names that hold values in a Ruby program. If you want to query *any* type +of variable, then use the ``Variable`` class, otherwise use one of the subclasses +``LocalVariable``, ``InstanceVariable``, ``ClassVariable`` or ``GlobalVariable``. + +Local variables have the scope of a single function or block, instance variables have the +scope of an object (like member variables), *class* variables have the scope of a class and are +shared between all instances of that class (like static variables), and *global* variables +have the scope of the entire program. + +.. list-table:: Variable classes + :header-rows: 1 + + * - CodeQL class + - Description and main predicates + * - ``Variable`` + - A variable declared in a scope. + + - `getName()`, `hasName(name)` - Gets the name of this variable. + - `getDeclaringScope()` - Gets the scope this variable is declared in. + - `getAnAccess()` - Gets an access to this variable. + * - ``LocalVariable`` + - A local variable. + * - ``InstanceVariable`` + - An instance variable. + * - ``ClassVariable`` + - A class variable. + * - ``GlobalVariable`` + - A global variable. + +The following example finds all class variables in the class `StaticController`: + +.. code-block:: ql + + import ruby + + from ClassDeclaration cd, ClassVariable v + where + v.getDeclaringScope() = cd and + cd.getName() = "StaticController" + select v, "This is a static variable in 'StaticController'." + +Variable accesses are the uses of a variable in the source code. Note that variables, and *uses* of variables are different concepts. +Variables are modelled using the ``Variable`` class, whereas uses of the variable are modelled using the ``VariableAccess`` class. +``Variable.getAnAccess()`` gets the accesses of a variable. + +Variable accesses come in two types: *reads* of the variable (a ``ReadAccess``), and *writes* to the variable (a ``WriteAccess``). +Accesses are a type of expression, so extend the ``Expr`` class. + +.. list-table:: Variable access classes + :header-rows: 1 + + * - CodeQL class + - Description and main predicates + * - ``VariableAccess`` + - An access to a variable. + + - `getVariable()` - Gets the variable that is accessed. + * - ``VariableReadAccess`` + - An access to a variable where the value is read. + * - ``VariableWriteAccess`` + - An access to a variable where the value is updated. + * - ``LocalVariableAccess`` + - An access to a local variable. + * - ``LocalVariableWriteAccess`` + - An access to a local variable where the value is updated. + * - ``LocalVariableReadAccess`` + - An access to a local variable where the value is read. + * - ``GlobalVariableAccess`` + - An access to a global variable where the value is updated. + * - ``InstanceVariableAccess`` + - An access to a global variable where the value is read. + * - ``InstanceVariableReadAccess`` + - An access to an instance variable. + * - ``InstanceVariableWriteAccess`` + - An access to an instance variable where the value is updated. + * - ``ClassVariableAccess`` + - An access to a class variable. + * - ``ClassVariableWriteAccess`` + - An access to a class variable where the value is updated. + * - ``ClassVariableReadAccess`` + - An access to a class variable where the value is read. + +The following example finds writes to class variables in the class `StaticController`: + +.. code-block:: ql + + import ruby + + from ClassVariableWriteAccess write, ClassDeclaration cd, ClassVariable v + where + v.getDeclaringScope() = cd and + cd.getName() = "StaticController" and + write.getVariable() = v + select write, "'StaticController' class variable is written here." \ No newline at end of file diff --git a/docs/codeql/reusables/ruby-further-reading.rst b/docs/codeql/reusables/ruby-further-reading.rst index 032eaff5112..2f12e7dfb74 100644 --- a/docs/codeql/reusables/ruby-further-reading.rst +++ b/docs/codeql/reusables/ruby-further-reading.rst @@ -1,3 +1,3 @@ -- `CodeQL queries for Ruby <https://github.com/github/codeql-ruby/tree/main/ql/src>`__ -- `Example queries for Ruby <https://github.com/github/codeql-ruby/tree/main/ql/examples>`__ +- `CodeQL queries for Ruby <https://github.com/github/codeql/tree/main/ruby/ql/src>`__ +- `Example queries for Ruby <https://github.com/github/codeql/tree/main/ruby/ql/examples>`__ - `CodeQL library reference for Ruby <https://codeql.github.com/codeql-standard-libraries/ruby/>`__ From 83490e9a03c98a2de6deb5b079e124f10fb3c26e Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Oct 2021 19:27:27 +0200 Subject: [PATCH 247/361] Python: update change note --- python/change-notes/2021-09-14-promote-regex-injection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/change-notes/2021-09-14-promote-regex-injection.md b/python/change-notes/2021-09-14-promote-regex-injection.md index 5443f2f03ad..0141251dea8 100644 --- a/python/change-notes/2021-09-14-promote-regex-injection.md +++ b/python/change-notes/2021-09-14-promote-regex-injection.md @@ -1,2 +1,2 @@ lgtm,codescanning -* The externally contributed query `py/regex-injection` has been promoted out of the experimental area. Results from this query are now available by default. +* The query "Regular expression injection" (`py/regex-injection`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @jorgectf](https://github.com/github/codeql/pull/5442). From bbb2637bccdfd3320c192f85208b5257574be0c2 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg <aeisenberg@github.com> Date: Tue, 12 Oct 2021 11:54:50 -0700 Subject: [PATCH 248/361] QlPacks: Add the defaultSuite to query packs that are missing it Also, change some examples pack names from `codeql-lang-examples` to `codeql/lang-examples`. This doesn't affect behaviour since internally, the legacy name is converted to the modern name. --- csharp/ql/examples/qlpack.yml | 2 +- csharp/ql/src/qlpack.yml | 1 + java/ql/examples/qlpack.yml | 2 +- java/ql/src/qlpack.yml | 1 + javascript/ql/examples/qlpack.yml | 2 +- javascript/ql/src/qlpack.yml | 1 + 6 files changed, 6 insertions(+), 3 deletions(-) diff --git a/csharp/ql/examples/qlpack.yml b/csharp/ql/examples/qlpack.yml index 573e7a673d0..fd3bccb2005 100644 --- a/csharp/ql/examples/qlpack.yml +++ b/csharp/ql/examples/qlpack.yml @@ -1,4 +1,4 @@ -name: codeql-csharp-examples +name: codeql/csharp-examples version: 0.0.2 dependencies: codeql/csharp-all: "*" diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index fc9ac2f6895..7c00298a638 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -2,6 +2,7 @@ name: codeql/csharp-queries version: 0.0.2 suites: codeql-suites extractor: csharp +defaultSuiteFile: codeql-suites/csharp-code-scanning.qls dependencies: codeql/csharp-all: "*" codeql/suite-helpers: "*" diff --git a/java/ql/examples/qlpack.yml b/java/ql/examples/qlpack.yml index 37542a63150..8033757261f 100644 --- a/java/ql/examples/qlpack.yml +++ b/java/ql/examples/qlpack.yml @@ -1,4 +1,4 @@ -name: codeql-java-examples +name: codeql/java-examples version: 0.0.2 dependencies: codeql/java-all: "*" diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 8632ff9df4e..b943646a906 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -2,6 +2,7 @@ name: codeql/java-queries version: 0.0.2 suites: codeql-suites extractor: java +defaultSuiteFile: codeql-suites/java-code-scanning.qls dependencies: codeql/java-all: "*" codeql/suite-helpers: "*" diff --git a/javascript/ql/examples/qlpack.yml b/javascript/ql/examples/qlpack.yml index 039f203982c..0a688278528 100644 --- a/javascript/ql/examples/qlpack.yml +++ b/javascript/ql/examples/qlpack.yml @@ -1,4 +1,4 @@ -name: codeql-javascript-examples +name: codeql/javascript-examples version: 0.0.3 dependencies: codeql/javascript-all: "*" diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 51ae6649bb3..e69cb686fe0 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -2,6 +2,7 @@ name: codeql/javascript-queries version: 0.0.3 suites: codeql-suites extractor: javascript +defaultSuiteFile: codeql-suites/javascript-code-scanning.qls dependencies: codeql/javascript-all: "*" codeql/suite-helpers: "*" From 2f27a0c9f9898dfbe477594a4ec86c807e68384b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 13 Oct 2021 00:09:35 +0000 Subject: [PATCH 249/361] Add changed framework coverage reports --- java/documentation/library-coverage/coverage.csv | 2 +- java/documentation/library-coverage/coverage.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index 2c187b90265..7a2caf11045 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -2,7 +2,7 @@ package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,si android.content,8,27,73,,,,,,,,,,,,,8,,,,,,27,,8,65 android.database,59,,30,,,,,,,,,,,,,59,,,,,,,,30, android.net,,,60,,,,,,,,,,,,,,,,,,,,,45,15 -android.os,,,82,,,,,,,,,,,,,,,,,,,,,2,80 +android.os,,,122,,,,,,,,,,,,,,,,,,,,,41,81 android.util,,16,,,,,,,,,,,,,,,,,,,,,16,, android.webkit,3,2,,,,,,,,,,,,,,,,,,,3,,2,, cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,1, diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index 68d9a911fe4..a8cc4868602 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -7,7 +7,7 @@ Java framework & library support :widths: auto Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :sub:`Cleartext transmission` - Android,``android.*``,45,245,70,,,3,67,,, + Android,``android.*``,45,285,70,,,3,67,,, `Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,, `Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,22,,,,,,,, `Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,423,,,,,,,, @@ -19,5 +19,5 @@ Java framework & library support Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2 `Spring <https://spring.io/>`_,``org.springframework.*``,29,469,91,,,,19,14,,29 Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,28,151,,,,14,18,, - Totals,,143,5217,408,13,6,10,107,33,1,66 + Totals,,143,5257,408,13,6,10,107,33,1,66 From 306388a6bc44abec62f6e971fdcee8941d0e5fc5 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@users.noreply.github.com> Date: Wed, 13 Oct 2021 08:57:31 +0200 Subject: [PATCH 250/361] Update java/ql/src/Likely Bugs/Comparison/StringComparison.ql --- java/ql/src/Likely Bugs/Comparison/StringComparison.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/src/Likely Bugs/Comparison/StringComparison.ql b/java/ql/src/Likely Bugs/Comparison/StringComparison.ql index fc6e8dce7b5..1f33ece559d 100644 --- a/java/ql/src/Likely Bugs/Comparison/StringComparison.ql +++ b/java/ql/src/Likely Bugs/Comparison/StringComparison.ql @@ -41,6 +41,7 @@ class StringValue extends Expr { } } +pragma[noinline] predicate candidateVariable(Variable v) { v.fromSource() and // For parameters, assume they could be non-interned. From f575139180ff586ade1352773c15ee206d65daa0 Mon Sep 17 00:00:00 2001 From: Calum Grant <calumgrant@github.com> Date: Wed, 13 Oct 2021 09:10:46 +0100 Subject: [PATCH 251/361] Add Ruby to toctree --- docs/codeql/codeql-for-ruby.rst | 16 ++++++++++++++++ docs/codeql/codeql-language-guides/index.rst | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 docs/codeql/codeql-for-ruby.rst diff --git a/docs/codeql/codeql-for-ruby.rst b/docs/codeql/codeql-for-ruby.rst new file mode 100644 index 00000000000..eaf5e8c94e1 --- /dev/null +++ b/docs/codeql/codeql-for-ruby.rst @@ -0,0 +1,16 @@ +.. _codeql-for-ruby: + +CodeQL for Ruby +=============== + +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Ruby codebases. + +.. toctree:: + :hidden: + + basic-query-for-ruby-code + codeql-library-for-ruby + +- :doc:`Basic query for Ruby code <basic-query-for-ruby-code>`: Learn to write and run a simple CodeQL query using LGTM. + +- :doc:`CodeQL library for Ruby <codeql-library-for-ruby>`: When you're analyzing a Ruby program, you can make use of the large collection of classes in the CodeQL library for Ruby. diff --git a/docs/codeql/codeql-language-guides/index.rst b/docs/codeql/codeql-language-guides/index.rst index 440b706a02a..79f3f79ac54 100644 --- a/docs/codeql/codeql-language-guides/index.rst +++ b/docs/codeql/codeql-language-guides/index.rst @@ -13,4 +13,4 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat codeql-for-java codeql-for-javascript codeql-for-python - \ No newline at end of file + codeql-for-ruby From 59e4a6ff7b84d82e9224647a0736fe36957feb09 Mon Sep 17 00:00:00 2001 From: Calum Grant <calumgrant@github.com> Date: Wed, 13 Oct 2021 09:23:04 +0100 Subject: [PATCH 252/361] Move file to correct location --- docs/codeql/{ => codeql-language-guides}/codeql-for-ruby.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/codeql/{ => codeql-language-guides}/codeql-for-ruby.rst (100%) diff --git a/docs/codeql/codeql-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-for-ruby.rst similarity index 100% rename from docs/codeql/codeql-for-ruby.rst rename to docs/codeql/codeql-language-guides/codeql-for-ruby.rst From d0ecabad195951dcfe746a52fb6835c89848da73 Mon Sep 17 00:00:00 2001 From: Philip Ginsbach <ginsbach@github.com> Date: Wed, 13 Oct 2021 11:39:25 +0100 Subject: [PATCH 253/361] DataFlowCall non-extending subtype of Call --- .../semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 986197bb0ce..7767b644cbd 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -219,15 +219,13 @@ class DataFlowExpr = Expr; class DataFlowType = Type; /** A function call relevant for data flow. */ -class DataFlowCall extends Expr { - DataFlowCall() { this instanceof Call } - +class DataFlowCall extends Expr instanceof Call { /** * Gets the nth argument for this call. * * The range of `n` is from `0` to `getNumberOfArguments() - 1`. */ - Expr getArgument(int n) { result = this.(Call).getArgument(n) } + Expr getArgument(int n) { result = super.getArgument(n) } /** Gets the data flow node corresponding to this call. */ ExprNode getNode() { result.getExpr() = this } From 4a0aac85054132cc65370bfca6c6725c74134250 Mon Sep 17 00:00:00 2001 From: Philip Ginsbach <ginsbach@github.com> Date: Wed, 13 Oct 2021 11:40:32 +0100 Subject: [PATCH 254/361] SuppressionScope non-extending subtype of SuppressionComment --- cpp/ql/src/AlertSuppression.ql | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/AlertSuppression.ql b/cpp/ql/src/AlertSuppression.ql index 7239398e8c1..9a3983ed515 100644 --- a/cpp/ql/src/AlertSuppression.ql +++ b/cpp/ql/src/AlertSuppression.ql @@ -60,9 +60,7 @@ class SuppressionComment extends Comment { /** * The scope of an alert suppression comment. */ -class SuppressionScope extends ElementBase { - SuppressionScope() { this instanceof SuppressionComment } - +class SuppressionScope extends ElementBase instanceof SuppressionComment { /** * Holds if this element is at the specified location. * The location spans column `startcolumn` of line `startline` to @@ -73,7 +71,7 @@ class SuppressionScope extends ElementBase { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn) + super.covers(filepath, startline, startcolumn, endline, endcolumn) } } From aa656f754202c3b1a235357ac4639631140a20ac Mon Sep 17 00:00:00 2001 From: Philip Ginsbach <ginsbach@github.com> Date: Wed, 13 Oct 2021 11:41:40 +0100 Subject: [PATCH 255/361] ArgumentNode non-extending subtype of ArgumentNodeImpl --- .../code/csharp/dataflow/internal/DataFlowPrivate.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index d75afd20b6c..e4763801e2d 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -940,12 +940,10 @@ private module ParameterNodes { import ParameterNodes /** A data-flow node that represents a call argument. */ -class ArgumentNode extends Node { - ArgumentNode() { this instanceof ArgumentNodeImpl } - +class ArgumentNode extends Node instanceof ArgumentNodeImpl { /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, int pos) { - this.(ArgumentNodeImpl).argumentOf(call, pos) + super.argumentOf(call, pos) } } From e3e741251f24758f8c355ccdcb6b17218fd2f0dc Mon Sep 17 00:00:00 2001 From: Philip Ginsbach <ginsbach@github.com> Date: Wed, 13 Oct 2021 11:42:41 +0100 Subject: [PATCH 256/361] ParameterNode non-extending subtype of ParameterNodeImpl --- .../semmle/code/csharp/dataflow/internal/DataFlowPublic.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll index 56286903951..64a862640e8 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll @@ -98,9 +98,7 @@ class ExprNode extends Node, TExprNode_ { * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParameterNode extends Node { - ParameterNode() { this instanceof ParameterNodeImpl } - +class ParameterNode extends Node instanceof ParameterNodeImpl { /** Gets the parameter corresponding to this node, if any. */ DotNet::Parameter getParameter() { exists(DataFlowCallable c, int i | this.isParameterOf(c, i) and result = c.getParameter(i)) @@ -111,7 +109,7 @@ class ParameterNode extends Node { * (zero-based) position. */ predicate isParameterOf(DataFlowCallable c, int i) { - this.(ParameterNodeImpl).isParameterOf(c, i) + super.isParameterOf(c, i) } } From 6b9ddf1f65fb7a66fc3096225f8a8235b98c87b2 Mon Sep 17 00:00:00 2001 From: Philip Ginsbach <ginsbach@github.com> Date: Wed, 13 Oct 2021 11:44:22 +0100 Subject: [PATCH 257/361] Guard non-extending subtype of G::Guard --- .../csharp/dataflow/internal/rangeanalysis/RangeUtils.qll | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll index 2f8e93a4b75..f007ba939e8 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll @@ -89,14 +89,12 @@ private module Impl { } /** An expression whose value may control the execution of another element. */ - class Guard extends Expr { - Guard() { this instanceof G::Guard } - + class Guard extends Expr instanceof G::Guard { /** * Holds if basic block `bb` is guarded by this guard having value `v`. */ predicate controlsBasicBlock(ControlFlow::BasicBlock bb, G::AbstractValue v) { - this.(G::Guard).controlsBasicBlock(bb, v) + super.controlsBasicBlock(bb, v) } /** @@ -108,7 +106,7 @@ private module Impl { exists(Expr e1_, Expr e2_ | e1 = unique(ExprNode cfn | hasChild(this, e1_, _, cfn) | cfn) and e2 = unique(ExprNode cfn | hasChild(this, e2_, _, cfn) | cfn) and - this.(G::Guard).isEquality(e1_, e2_, polarity) + super.isEquality(e1_, e2_, polarity) ) } } From ba981c525b80dbfd30e570b7b0139d6d8a53c293 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 13 Oct 2021 11:32:21 +0100 Subject: [PATCH 258/361] C++: Replace 'if p() then q() else none()' with a conjunction. --- cpp/ql/lib/semmle/code/cpp/Declaration.qll | 5 ++--- .../cpp/controlflow/internal/ConstantExprs.qll | 9 ++++----- .../code/cpp/ir/internal/IntegerInterval.qll | 9 +++++---- .../lib/semmle/code/cpp/security/BufferWrite.qll | 2 +- .../Arithmetic/PointlessComparison.ql | 5 +---- .../CWE-468/IncorrectPointerScalingCommon.qll | 16 +++++++--------- 6 files changed, 20 insertions(+), 26 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/Declaration.qll b/cpp/ql/lib/semmle/code/cpp/Declaration.qll index 7ac79fd99c1..b1422aa6342 100644 --- a/cpp/ql/lib/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/lib/semmle/code/cpp/Declaration.qll @@ -275,9 +275,8 @@ class Declaration extends Locatable, @declaration { * `getTemplateArgumentKind(0)`. */ final Locatable getTemplateArgumentKind(int index) { - if exists(getTemplateArgumentValue(index)) - then result = getTemplateArgumentType(index) - else none() + exists(getTemplateArgumentValue(index)) and + result = getTemplateArgumentType(index) } /** Gets the number of template arguments for this declaration. */ diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll index 476f626e874..ff27baae965 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll @@ -344,14 +344,13 @@ private int convertIntToType(int val, IntegralType t) { then if val = 0 then result = 0 else result = 1 else if t.isUnsigned() - then if val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 then result = val else none() + then val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 and result = val else if val >= 0 and val.bitShiftRight(t.getSize() * 8 - 1) = 0 then result = val - else - if (-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0 - then result = val - else none() + else ( + (-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0 and result = val + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerInterval.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerInterval.qll index cd12b9b627a..4f8f4b4e672 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerInterval.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerInterval.qll @@ -18,10 +18,11 @@ Overlap getOverlap(IntValue defStart, IntValue defEnd, IntValue useStart, IntVal else if isLE(defStart, useStart) and isGE(defEnd, useEnd) then result instanceof MustTotallyOverlap - else - if isLE(defEnd, useStart) or isGE(defStart, useEnd) - then none() - else result instanceof MayPartiallyOverlap + else ( + not isLE(defEnd, useStart) and + not isGE(defStart, useEnd) and + result instanceof MayPartiallyOverlap + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll b/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll index 2726b2eca00..e5d892eb4cd 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll @@ -365,7 +365,7 @@ class GetsBW extends BufferWriteCall { /** * Gets the index of the parameter that is the maximum number of characters to be read. */ - int getParamSize() { if exists(getArgument(1)) then result = 1 else none() } + int getParamSize() { exists(getArgument(1)) and result = 1 } override Type getBufferType() { result = this.getTarget().getParameter(0).getUnspecifiedType() } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql index 94a6c403937..e2fe02be867 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql @@ -50,10 +50,7 @@ where // If either of the operands is constant, then don't include it. ( if cmp.getLeftOperand().isConstant() - then - if cmp.getRightOperand().isConstant() - then none() // Both operands are constant so don't create a message. - else reason = rightReason + then not cmp.getRightOperand().isConstant() and reason = rightReason else if cmp.getRightOperand().isConstant() then reason = leftReason diff --git a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingCommon.qll b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingCommon.qll index 4854c1dc38e..9978d9ece0b 100644 --- a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingCommon.qll +++ b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingCommon.qll @@ -121,16 +121,14 @@ predicate exprSourceType(Expr use, Type sourceType, Location sourceLoc) { else if use instanceof CrementOperation then exprSourceType(use.(CrementOperation).getOperand(), sourceType, sourceLoc) - else + else ( // Conversions are not in the AST, so ignore them. - if use instanceof Conversion - then none() - else ( - // Source expressions - sourceType = use.getUnspecifiedType() and - isPointerType(sourceType) and - sourceLoc = use.getLocation() - ) + not use instanceof Conversion and + // Source expressions + sourceType = use.getUnspecifiedType() and + isPointerType(sourceType) and + sourceLoc = use.getLocation() + ) } /** From 76906251143add17fc6162360f030f61351594e6 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 13 Oct 2021 11:32:37 +0100 Subject: [PATCH 259/361] C#: Replace 'if p() then q() else none()' with a conjunction. --- .../ql/src/experimental/ir/internal/IntegerInterval.qll | 9 +++++---- .../ql/src/experimental/ir/rangeanalysis/RangeUtils.qll | 5 +---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/csharp/ql/src/experimental/ir/internal/IntegerInterval.qll b/csharp/ql/src/experimental/ir/internal/IntegerInterval.qll index cd12b9b627a..4f8f4b4e672 100644 --- a/csharp/ql/src/experimental/ir/internal/IntegerInterval.qll +++ b/csharp/ql/src/experimental/ir/internal/IntegerInterval.qll @@ -18,10 +18,11 @@ Overlap getOverlap(IntValue defStart, IntValue defEnd, IntValue useStart, IntVal else if isLE(defStart, useStart) and isGE(defEnd, useEnd) then result instanceof MustTotallyOverlap - else - if isLE(defEnd, useStart) or isGE(defStart, useEnd) - then none() - else result instanceof MayPartiallyOverlap + else ( + not isLE(defEnd, useStart) and + not isGE(defStart, useEnd) and + result instanceof MayPartiallyOverlap + ) } /** diff --git a/csharp/ql/src/experimental/ir/rangeanalysis/RangeUtils.qll b/csharp/ql/src/experimental/ir/rangeanalysis/RangeUtils.qll index 4a7f1d69840..b7fdfc3546f 100644 --- a/csharp/ql/src/experimental/ir/rangeanalysis/RangeUtils.qll +++ b/csharp/ql/src/experimental/ir/rangeanalysis/RangeUtils.qll @@ -52,10 +52,7 @@ IntValue getArrayDim(Variable arr) { arr.getInitializer() = ac and if exists(ac.getLengthArgument(0)) then result = ac.getLengthArgument(0).getValue().toInt() - else - if exists(ac.getInitializer()) - then result = ac.getInitializer().getNumberOfElements() - else none() + else result = ac.getInitializer().getNumberOfElements() ) } From 887849857db84661c692f53282e1de16afeed4cd Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 13 Oct 2021 11:33:56 +0100 Subject: [PATCH 260/361] JS: Replace 'if p() then q() else none()' with a conjunction. --- javascript/ql/lib/semmle/javascript/RangeAnalysis.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll b/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll index 28f8b59c3fe..d1e9b48a6d0 100644 --- a/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll +++ b/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll @@ -236,10 +236,9 @@ module RangeAnalysis { ) { if exists(r.getImmediatePredecessor()) then linearDefinitionSum(r.getImmediatePredecessor(), xroot, xsign, yroot, ysign, bias) - else - if exists(r.asExpr().getIntValue()) - then none() // do not model constants as sums - else ( + else ( + not exists(r.asExpr().getIntValue()) and // do not model constants as sums + ( exists(AddExpr add, int bias1, int bias2 | r.asExpr() = add | // r = r1 + r2 linearDefinition(add.getLeftOperand().flow(), xroot, xsign, bias1) and @@ -257,6 +256,7 @@ module RangeAnalysis { linearDefinitionSum(r.asExpr().(NegExpr).getOperand().flow(), xroot, -xsign, yroot, -ysign, -bias) ) + ) } /** From bdc54bcda7ab475b3f93e858fd7762641bcbe3f0 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 13 Oct 2021 11:34:03 +0100 Subject: [PATCH 261/361] Python: Replace 'if p() then q() else none()' with a conjunction. --- python/ql/src/Functions/SignatureSpecialMethods.ql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ql/src/Functions/SignatureSpecialMethods.ql b/python/ql/src/Functions/SignatureSpecialMethods.ql index 87aeeae51ff..f240f0e5087 100644 --- a/python/ql/src/Functions/SignatureSpecialMethods.ql +++ b/python/ql/src/Functions/SignatureSpecialMethods.ql @@ -132,12 +132,12 @@ predicate incorrect_special_method_defn( else if required < func.minParameters() then message = "Too many parameters" and show_counts = true - else - if func.minParameters() < required and not func.getScope().hasVarArg() - then - message = (required - func.minParameters()) + " default values(s) will never be used" and - show_counts = false - else none() + else ( + func.minParameters() < required and + not func.getScope().hasVarArg() and + message = (required - func.minParameters()) + " default values(s) will never be used" and + show_counts = false + ) ) } From c9c0c7f24f4ee1e9c41dbc48c03bdeba381d4c75 Mon Sep 17 00:00:00 2001 From: Philip Ginsbach <ginsbach@github.com> Date: Wed, 13 Oct 2021 13:10:37 +0100 Subject: [PATCH 262/361] fix formatting --- .../semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll | 4 +--- .../semmle/code/csharp/dataflow/internal/DataFlowPublic.qll | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index e4763801e2d..6776025d172 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -942,9 +942,7 @@ import ParameterNodes /** A data-flow node that represents a call argument. */ class ArgumentNode extends Node instanceof ArgumentNodeImpl { /** Holds if this argument occurs at the given position in the given call. */ - final predicate argumentOf(DataFlowCall call, int pos) { - super.argumentOf(call, pos) - } + final predicate argumentOf(DataFlowCall call, int pos) { super.argumentOf(call, pos) } } abstract private class ArgumentNodeImpl extends Node { diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll index 64a862640e8..fa99d518bbd 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll @@ -108,9 +108,7 @@ class ParameterNode extends Node instanceof ParameterNodeImpl { * Holds if this node is the parameter of callable `c` at the specified * (zero-based) position. */ - predicate isParameterOf(DataFlowCallable c, int i) { - super.isParameterOf(c, i) - } + predicate isParameterOf(DataFlowCallable c, int i) { super.isParameterOf(c, i) } } /** A definition, viewed as a node in a data flow graph. */ From 955344e1756842440fbc761f4002dc0998911c5b Mon Sep 17 00:00:00 2001 From: Jonas Jensen <jbj@github.com> Date: Wed, 13 Oct 2021 14:11:47 +0200 Subject: [PATCH 263/361] C++: Inline a predicate that contains CPs The `overflows` predicate had quite severe Cartesian products. We didn't see them in practice because magic saved us, but we can't rely on magic in the future, so it seems better to inline this predicate. Tuple counts and speed look good both before and after. --- cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql b/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql index 03ad085b6d3..ba7a6b58aa0 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql @@ -166,6 +166,7 @@ class VarAnalyzableExpr extends AnalyzableExpr, VariableAccess { * Holds if `t` is not an instance of `IntegralType`, * or if `me` cannot be proven to not overflow */ +pragma[inline] predicate overflows(MulExpr me, Type t) { t instanceof IntegralType implies From d85d009a54b1f33b2ba6373a5080aa853feaf6c2 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 13 Oct 2021 13:19:06 +0100 Subject: [PATCH 264/361] Java: Replace '.prefix'/'.suffix' with '.matches'. --- .../semmle/code/java/frameworks/gigaspaces/GigaSpaces.qll | 6 +++--- .../semmle/code/java/frameworks/spring/SpringProfile.qll | 2 +- java/ql/lib/semmle/code/xml/MavenPom.qll | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/gigaspaces/GigaSpaces.qll b/java/ql/lib/semmle/code/java/frameworks/gigaspaces/GigaSpaces.qll index 6b70770b70e..b7596ebab49 100644 --- a/java/ql/lib/semmle/code/java/frameworks/gigaspaces/GigaSpaces.qll +++ b/java/ql/lib/semmle/code/java/frameworks/gigaspaces/GigaSpaces.qll @@ -37,7 +37,7 @@ predicate isGigaSpacesEventMethod(Method eventMethod) { class GigaSpacesSpaceIdGetterMethod extends Method { GigaSpacesSpaceIdGetterMethod() { getAnAnnotation().getType().hasQualifiedName("com.gigaspaces.annotation.pojo", "SpaceId") and - getName().prefix(3) = "get" + getName().matches("get%") } } @@ -48,7 +48,7 @@ class GigaSpacesSpaceIdSetterMethod extends Method { GigaSpacesSpaceIdSetterMethod() { exists(GigaSpacesSpaceIdGetterMethod getterMethod | getterMethod.getDeclaringType() = getDeclaringType() and - getName().prefix(3) = "set" + getName().matches("set%") | getterMethod.getName().suffix(3) = getName().suffix(3) ) @@ -62,6 +62,6 @@ class GigaSpacesSpaceIdSetterMethod extends Method { class GigaSpacesSpaceRoutingMethod extends Method { GigaSpacesSpaceRoutingMethod() { getAnAnnotation().getType().hasQualifiedName("com.gigaspaces.annotation.pojo", "SpaceRouting") and - getName().prefix(3) = "get" + getName().matches("get%") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringProfile.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringProfile.qll index 32ee55723b2..17fedacdefe 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringProfile.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringProfile.qll @@ -37,7 +37,7 @@ class SpringProfileExpr extends string { * A Spring profile expression that begins with "!", indicating a negated expression. */ class NotSpringProfileExpr extends SpringProfileExpr { - NotSpringProfileExpr() { this.prefix(1) = "!" } + NotSpringProfileExpr() { this.matches("!%") } /** * Gets the profile described in this profile expression. diff --git a/java/ql/lib/semmle/code/xml/MavenPom.qll b/java/ql/lib/semmle/code/xml/MavenPom.qll index fe6985ba811..921f9be0bff 100644 --- a/java/ql/lib/semmle/code/xml/MavenPom.qll +++ b/java/ql/lib/semmle/code/xml/MavenPom.qll @@ -129,7 +129,7 @@ class Pom extends ProtoPom { * occurs by considering the properties defined by this project or an ancestor project. */ string resolvePlaceholder(string name) { - if name.prefix(8) = "project." + if name.matches("project.%") then exists(PomElement p | p = getProjectProperty() and From f3bb0a676e06fa7be402f3354d75e7655a22bea0 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 13 Oct 2021 13:19:45 +0100 Subject: [PATCH 265/361] JS: Replace '.prefix'/'.suffix' with '.matches'. --- .../ql/lib/semmle/javascript/frameworks/NodeJSLib.qll | 2 +- .../javascript/frameworks/SystemCommandExecutors.qll | 4 +--- .../ql/lib/semmle/javascript/security/UselessUseOfCat.qll | 7 ++----- javascript/ql/src/Security/CWE-730/ServerCrash.ql | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll index 43fde9639c2..7a88b3f94c3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll @@ -727,7 +727,7 @@ module NodeJSLib { result = getParameter(1).getARhs() } - override predicate isSync() { "Sync" = methodName.suffix(methodName.length() - 4) } + override predicate isSync() { methodName.matches("%Sync") } override DataFlow::Node getOptionsArg() { not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll b/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll index ce445cfd174..89eb8c9e9ea 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll @@ -107,9 +107,7 @@ private class SystemCommandExecutors extends SystemCommandExecution, DataFlow::I */ bindingset[name] private boolean getSync(string name) { - if name.suffix(name.length() - 4) = "Sync" or name.suffix(name.length() - 4) = "sync" - then result = true - else result = false + if name.matches("%Sync") or name.matches("%sync") then result = true else result = false } private class RemoteCommandExecutor extends SystemCommandExecution, DataFlow::InvokeNode { diff --git a/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll index 604a8182e96..eda163f053f 100644 --- a/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll +++ b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll @@ -303,14 +303,11 @@ module PrettyPrintCatCall { bindingset[str] private string createSimplifiedStringConcat(string str) { // Remove an initial ""+ (e.g. in `""+file`) - if str.prefix(5) = "\"\" + " + if str.matches("\"\" + %") then result = str.suffix(5) else // prettify `${newpath}` to just newpath - if - str.prefix(3) = "`${" and - str.suffix(str.length() - 2) = "}`" and - not str.suffix(3).matches("%{%") + if str.matches("`${%") and str.matches("}`%") and not str.suffix(3).matches("%{%") then result = str.prefix(str.length() - 2).suffix(3) else result = str } diff --git a/javascript/ql/src/Security/CWE-730/ServerCrash.ql b/javascript/ql/src/Security/CWE-730/ServerCrash.ql index 7c16287d48c..336cc2abf70 100644 --- a/javascript/ql/src/Security/CWE-730/ServerCrash.ql +++ b/javascript/ql/src/Security/CWE-730/ServerCrash.ql @@ -104,7 +104,7 @@ class AsyncSentinelCall extends DataFlow::CallNode { exists(DataFlow::FunctionNode node | node.getAstNode() = asyncCallee | // manual models exists(string memberName | - not "Sync" = memberName.suffix(memberName.length() - 4) and + not memberName.matches("%Sync") and this = NodeJSLib::FS::moduleMember(memberName).getACall() and node = this.getCallback([1 .. 2]) ) From a80860cdc6b06b363b0d0919600ab383a470b449 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 13 Oct 2021 13:19:58 +0100 Subject: [PATCH 266/361] Python: Replace '.prefix'/'.suffix' with '.matches'. --- python/ql/lib/semmle/python/templates/PyxlTags.qll | 2 +- python/ql/lib/semmle/python/web/Http.qll | 2 +- python/ql/src/Security/CWE-798/HardcodedCredentials.ql | 2 +- python/ql/src/analysis/Consistency.ql | 2 +- python/ql/test/library-tests/PointsTo/customise/test.ql | 4 ++-- python/ql/test/library-tests/PointsTo/new/Consistency.ql | 2 +- .../ql/test/library-tests/taint/extensions/ExtensionsLib.qll | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/python/ql/lib/semmle/python/templates/PyxlTags.qll b/python/ql/lib/semmle/python/templates/PyxlTags.qll index f0e663cdad0..abfef070d78 100644 --- a/python/ql/lib/semmle/python/templates/PyxlTags.qll +++ b/python/ql/lib/semmle/python/templates/PyxlTags.qll @@ -29,7 +29,7 @@ private predicate pyxl_tag(Call c, string name) { } class PyxlHtmlTag extends PyxlTag { - PyxlHtmlTag() { this.getPyxlTagName().prefix(2) = "x_" } + PyxlHtmlTag() { this.getPyxlTagName().matches("x\\_%") } string getTagName() { result = this.getPyxlTagName().suffix(2) } diff --git a/python/ql/lib/semmle/python/web/Http.qll b/python/ql/lib/semmle/python/web/Http.qll index 527a050d814..fc1b1bc5756 100644 --- a/python/ql/lib/semmle/python/web/Http.qll +++ b/python/ql/lib/semmle/python/web/Http.qll @@ -33,7 +33,7 @@ class WsgiEnvironment extends TaintKind { ( text = "QUERY_STRING" or text = "PATH_INFO" or - text.prefix(5) = "HTTP_" + text.matches("HTTP\\_%") ) ) } diff --git a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql index cd00908fe05..895352be75c 100644 --- a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql +++ b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql @@ -88,7 +88,7 @@ class CredentialSink extends TaintSink { CredentialSink() { exists(string name | name.regexpMatch(getACredentialRegex()) and - not name.suffix(name.length() - 4) = "file" + not name.matches("%file") | any(FunctionValue func).getNamedArgumentForCall(_, name) = this or diff --git a/python/ql/src/analysis/Consistency.ql b/python/ql/src/analysis/Consistency.ql index a504216a252..698a3d95b3a 100644 --- a/python/ql/src/analysis/Consistency.ql +++ b/python/ql/src/analysis/Consistency.ql @@ -141,7 +141,7 @@ predicate builtin_object_consistency(string clsname, string problem, string what or not exists(o.toString()) and problem = "no toString" and - not exists(string name | name.prefix(7) = "_semmle" | py_special_objects(o, name)) and + not exists(string name | name.matches("\\_semmle%") | py_special_objects(o, name)) and not o = unknownValue() ) } diff --git a/python/ql/test/library-tests/PointsTo/customise/test.ql b/python/ql/test/library-tests/PointsTo/customise/test.ql index c2fceb95225..f101e4f2a5d 100644 --- a/python/ql/test/library-tests/PointsTo/customise/test.ql +++ b/python/ql/test/library-tests/PointsTo/customise/test.ql @@ -11,7 +11,7 @@ class HasTypeFact extends CustomPointsToOriginFact { exists(FunctionObject func, string name | func.getACall() = this and name = func.getName() and - name.prefix("has_type_".length()) = "has_type_" + name.matches("has\\_type\\_%") ) } @@ -19,7 +19,7 @@ class HasTypeFact extends CustomPointsToOriginFact { exists(FunctionObject func, string name | func.getACall() = this and name = func.getName() and - name.prefix("has_type_".length()) = "has_type_" + name.matches("has\\_type\\_%") | cls.getName() = name.suffix("has_type_".length()) ) and diff --git a/python/ql/test/library-tests/PointsTo/new/Consistency.ql b/python/ql/test/library-tests/PointsTo/new/Consistency.ql index 282b96fc541..0ee1a392ef2 100644 --- a/python/ql/test/library-tests/PointsTo/new/Consistency.ql +++ b/python/ql/test/library-tests/PointsTo/new/Consistency.ql @@ -104,7 +104,7 @@ predicate ssa_consistency(string clsname, string problem, string what) { or exists(EssaDefinition def | clsname = def.getAQlClass() and - clsname.prefix(4) = "Essa" and + clsname.matches("Essa%") and what = " at " + def.getLocation() and problem = "not covered by Python-specific subclass." ) diff --git a/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll b/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll index 08ba0ce6e40..4ae53e94a38 100644 --- a/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll +++ b/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll @@ -28,7 +28,7 @@ class SimpleSource extends TaintSource { predicate visit_call(CallNode call, FunctionObject func) { exists(AttrNode attr, ClassObject cls, string name | - name.prefix(6) = "visit_" and + name.matches("visit\\_%") and func = cls.lookupAttribute(name) and attr.getObject("visit").refersTo(_, cls, _) and attr = call.getFunction() From e80c1ad91f4f094318c62ad2d762f10b6a6ac62e Mon Sep 17 00:00:00 2001 From: Jonas Jensen <jbj@github.com> Date: Wed, 13 Oct 2021 14:24:26 +0200 Subject: [PATCH 267/361] C++: Fix resource-not-released-in-destructor CP By moving a disjunct outside the scope of an `exists(Function f` variable it doens't use, the code becomes clearer and can be optimized better. The CP in the QL code did not lead to a CP at evaluation time since the optimizer was smart enough to compensate for it: 376161 ~37597630% {0} r1 = SCAN functions OUTPUT {} 1 ~0% {0} r2 = STREAM DEDUP r1 Before this change, the largest tuple count in `leakedInSameMethod` on bitcoin/bitcoin was 2M. Now it's 400k. --- cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql index 3ae7bc65b45..adeb54746df 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql @@ -230,13 +230,13 @@ predicate leakedInSameMethod(Resource r, Expr acquire) { ) ) ) - or - exists(FunctionAccess fa, string kind | - // the address of a function that releases `r` is taken (and likely - // used to release `r` at some point). - r.acquisitionWithRequiredKind(acquire, kind) and - fa.getTarget() = r.getAReleaseExpr(kind).getEnclosingFunction() - ) + ) + or + exists(FunctionAccess fa, string kind | + // the address of a function that releases `r` is taken (and likely + // used to release `r` at some point). + r.acquisitionWithRequiredKind(acquire, kind) and + fa.getTarget() = r.getAReleaseExpr(kind).getEnclosingFunction() ) } From a9c8163ab3c2e7b685a12cf632c6be1939fffc6e Mon Sep 17 00:00:00 2001 From: Taus <tausbn@gmail.com> Date: Wed, 13 Oct 2021 13:24:46 +0000 Subject: [PATCH 268/361] Python: Fix uses of implicit `this` Quoting the style guide: "14. _Always_ qualify _calls_ to predicates of the same class with `this`." --- python/ql/lib/semmle/python/ApiGraphs.qll | 30 ++++++++++--------- python/ql/lib/semmle/python/Exprs.qll | 2 +- python/ql/lib/semmle/python/Files.qll | 10 +++++-- python/ql/lib/semmle/python/Flow.qll | 6 ++-- python/ql/lib/semmle/python/Import.qll | 18 +++++------ python/ql/lib/semmle/python/Module.qll | 4 +-- python/ql/lib/semmle/python/RegexTreeView.qll | 26 ++++++++-------- .../dataflow/new/internal/DataFlowPrivate.qll | 4 +-- .../dataflow/new/internal/LocalSources.qll | 8 ++--- 9 files changed, 57 insertions(+), 51 deletions(-) diff --git a/python/ql/lib/semmle/python/ApiGraphs.qll b/python/ql/lib/semmle/python/ApiGraphs.qll index 62afe4ef865..9ab510d0ee5 100644 --- a/python/ql/lib/semmle/python/ApiGraphs.qll +++ b/python/ql/lib/semmle/python/ApiGraphs.qll @@ -55,7 +55,7 @@ module API { /** * Gets a call to the function represented by this API component. */ - DataFlow::CallCfgNode getACall() { result = getReturn().getAnImmediateUse() } + DataFlow::CallCfgNode getACall() { result = this.getReturn().getAnImmediateUse() } /** * Gets a node representing member `m` of this API component. @@ -67,21 +67,21 @@ module API { */ bindingset[m] bindingset[result] - Node getMember(string m) { result = getASuccessor(Label::member(m)) } + Node getMember(string m) { result = this.getASuccessor(Label::member(m)) } /** * Gets a node representing a member of this API component where the name of the member is * not known statically. */ - Node getUnknownMember() { result = getASuccessor(Label::unknownMember()) } + Node getUnknownMember() { result = this.getASuccessor(Label::unknownMember()) } /** * Gets a node representing a member of this API component where the name of the member may * or may not be known statically. */ Node getAMember() { - result = getASuccessor(Label::member(_)) or - result = getUnknownMember() + result = this.getASuccessor(Label::member(_)) or + result = this.getUnknownMember() } /** @@ -90,23 +90,25 @@ module API { * This predicate may have multiple results when there are multiple invocations of this API component. * Consider using `getACall()` if there is a need to distinguish between individual calls. */ - Node getReturn() { result = getASuccessor(Label::return()) } + Node getReturn() { result = this.getASuccessor(Label::return()) } /** * Gets a node representing a subclass of the class represented by this node. */ - Node getASubclass() { result = getASuccessor(Label::subclass()) } + Node getASubclass() { result = this.getASuccessor(Label::subclass()) } /** * Gets a node representing the result from awaiting this node. */ - Node getAwaited() { result = getASuccessor(Label::await()) } + Node getAwaited() { result = this.getASuccessor(Label::await()) } /** * Gets a string representation of the lexicographically least among all shortest access paths * from the root to this node. */ - string getPath() { result = min(string p | p = getAPath(Impl::distanceFromRoot(this)) | p) } + string getPath() { + result = min(string p | p = this.getAPath(Impl::distanceFromRoot(this)) | p) + } /** * Gets a node such that there is an edge in the API graph between this node and the other @@ -124,13 +126,13 @@ module API { * Gets a node such that there is an edge in the API graph between this node and the other * one. */ - Node getAPredecessor() { result = getAPredecessor(_) } + Node getAPredecessor() { result = this.getAPredecessor(_) } /** * Gets a node such that there is an edge in the API graph between that other node and * this one. */ - Node getASuccessor() { result = getASuccessor(_) } + Node getASuccessor() { result = this.getASuccessor(_) } /** * Gets the data-flow node that gives rise to this node, if any. @@ -147,11 +149,11 @@ module API { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - getInducingNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + this.getInducingNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or // For nodes that do not have a meaningful location, `path` is the empty string and all other // parameters are zero. - not exists(getInducingNode()) and + not exists(this.getInducingNode()) and filepath = "" and startline = 0 and startcolumn = 0 and @@ -202,7 +204,7 @@ module API { or this = Impl::MkModuleImport(_) and type = "ModuleImport " | - result = type + getPath() + result = type + this.getPath() or not exists(this.getPath()) and result = type + "with no path" ) diff --git a/python/ql/lib/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll index 98c24b126a4..5a56a704b6f 100644 --- a/python/ql/lib/semmle/python/Exprs.qll +++ b/python/ql/lib/semmle/python/Exprs.qll @@ -240,7 +240,7 @@ class Call extends Call_ { /** Gets the tuple (*) argument of this call, provided there is exactly one. */ Expr getStarArg() { count(this.getStarargs()) < 2 and - result = getStarargs() + result = this.getStarargs() } } diff --git a/python/ql/lib/semmle/python/Files.qll b/python/ql/lib/semmle/python/Files.qll index 66dfca681cc..99570fc4d7a 100644 --- a/python/ql/lib/semmle/python/Files.qll +++ b/python/ql/lib/semmle/python/Files.qll @@ -256,7 +256,7 @@ abstract class Container extends @container { * </table> */ string getBaseName() { - result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) + result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) } /** @@ -282,7 +282,9 @@ abstract class Container extends @container { * <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr> * </table> */ - string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } + string getExtension() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) + } /** * Gets the stem of this container, that is, the prefix of its base name up to @@ -301,7 +303,9 @@ abstract class Container extends @container { * <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr> * </table> */ - string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } + string getStem() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) + } File getFile(string baseName) { result = this.getAFile() and diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index 65246927872..ab3d0a5f393 100755 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -851,9 +851,9 @@ class ForNode extends ControlFlowNode { /** Holds if this `for` statement causes iteration over `sequence` storing each step of the iteration in `target` */ predicate iterates(ControlFlowNode target, ControlFlowNode sequence) { - sequence = getSequence() and - target = possibleTarget() and - not target = unrolledSuffix().possibleTarget() + sequence = this.getSequence() and + target = this.possibleTarget() and + not target = this.unrolledSuffix().possibleTarget() } /** Gets the sequence node for this `for` statement. */ diff --git a/python/ql/lib/semmle/python/Import.qll b/python/ql/lib/semmle/python/Import.qll index 40c1c27a851..9620b01e4c6 100644 --- a/python/ql/lib/semmle/python/Import.qll +++ b/python/ql/lib/semmle/python/Import.qll @@ -31,7 +31,7 @@ class ImportExpr extends ImportExpr_ { // relative imports are no longer allowed in Python 3 major_version() < 3 and // and can be explicitly turned off in later versions of Python 2 - not getEnclosingModule().hasFromFuture("absolute_import") + not this.getEnclosingModule().hasFromFuture("absolute_import") } /** @@ -53,8 +53,8 @@ class ImportExpr extends ImportExpr_ { * the name of the topmost module that will be imported. */ private string relativeTopName() { - getLevel() = -1 and - result = basePackageName(1) + "." + this.getTopName() and + this.getLevel() = -1 and + result = this.basePackageName(1) + "." + this.getTopName() and valid_module_name(result) } @@ -62,7 +62,7 @@ class ImportExpr extends ImportExpr_ { if this.getLevel() <= 0 then result = this.getTopName() else ( - result = basePackageName(this.getLevel()) and + result = this.basePackageName(this.getLevel()) and valid_module_name(result) ) } @@ -73,17 +73,17 @@ class ImportExpr extends ImportExpr_ { * which may not be the name of the module. */ string bottomModuleName() { - result = relativeTopName() + this.remainderOfName() + result = this.relativeTopName() + this.remainderOfName() or - not exists(relativeTopName()) and + not exists(this.relativeTopName()) and result = this.qualifiedTopName() + this.remainderOfName() } /** Gets the name of topmost module or package being imported */ string topModuleName() { - result = relativeTopName() + result = this.relativeTopName() or - not exists(relativeTopName()) and + not exists(this.relativeTopName()) and result = this.qualifiedTopName() } @@ -94,7 +94,7 @@ class ImportExpr extends ImportExpr_ { */ string getImportedModuleName() { exists(string bottomName | bottomName = this.bottomModuleName() | - if this.isTop() then result = topModuleName() else result = bottomName + if this.isTop() then result = this.topModuleName() else result = bottomName ) } diff --git a/python/ql/lib/semmle/python/Module.qll b/python/ql/lib/semmle/python/Module.qll index 8f9344f60c0..6baf41b4a03 100644 --- a/python/ql/lib/semmle/python/Module.qll +++ b/python/ql/lib/semmle/python/Module.qll @@ -86,13 +86,13 @@ class Module extends Module_, Scope, AstNode { /** Gets the package containing this module (or parent package if this is a package) */ Module getPackage() { this.getName().matches("%.%") and - result.getName() = getName().regexpReplaceAll("\\.[^.]*$", "") + result.getName() = this.getName().regexpReplaceAll("\\.[^.]*$", "") } /** Gets the name of the package containing this module */ string getPackageName() { this.getName().matches("%.%") and - result = getName().regexpReplaceAll("\\.[^.]*$", "") + result = this.getName().regexpReplaceAll("\\.[^.]*$", "") } /** Gets the metrics for this module */ diff --git a/python/ql/lib/semmle/python/RegexTreeView.qll b/python/ql/lib/semmle/python/RegexTreeView.qll index ad1949e4bc4..833abf41e09 100644 --- a/python/ql/lib/semmle/python/RegexTreeView.qll +++ b/python/ql/lib/semmle/python/RegexTreeView.qll @@ -55,10 +55,10 @@ class RegExpParent extends TRegExpParent { abstract RegExpTerm getChild(int i); /** Gets a child term . */ - RegExpTerm getAChild() { result = getChild(_) } + RegExpTerm getAChild() { result = this.getChild(_) } /** Gets the number of child terms. */ - int getNumChild() { result = count(getAChild()) } + int getNumChild() { result = count(this.getAChild()) } /** Gets the associated regex. */ abstract Regex getRegex(); @@ -117,7 +117,7 @@ class RegExpTerm extends RegExpParent { RegExpTerm getRootTerm() { this.isRootTerm() and result = this or - result = getParent().(RegExpTerm).getRootTerm() + result = this.getParent().(RegExpTerm).getRootTerm() } /** @@ -196,7 +196,7 @@ class RegExpTerm extends RegExpParent { /** Gets the regular expression term that is matched (textually) before this one, if any. */ RegExpTerm getPredecessor() { - exists(RegExpTerm parent | parent = getParent() | + exists(RegExpTerm parent | parent = this.getParent() | result = parent.(RegExpSequence).previousElement(this) or not exists(parent.(RegExpSequence).previousElement(this)) and @@ -207,7 +207,7 @@ class RegExpTerm extends RegExpParent { /** Gets the regular expression term that is matched (textually) after this one, if any. */ RegExpTerm getSuccessor() { - exists(RegExpTerm parent | parent = getParent() | + exists(RegExpTerm parent | parent = this.getParent() | result = parent.(RegExpSequence).nextElement(this) or not exists(parent.(RegExpSequence).nextElement(this)) and @@ -358,7 +358,7 @@ class RegExpSequence extends RegExpTerm, TRegExpSequence { override RegExpTerm getChild(int i) { result = seqChild(re, start, end, i) } /** Gets the element preceding `element` in this sequence. */ - RegExpTerm previousElement(RegExpTerm element) { element = nextElement(result) } + RegExpTerm previousElement(RegExpTerm element) { element = this.nextElement(result) } /** Gets the element following `element` in this sequence. */ RegExpTerm nextElement(RegExpTerm element) { @@ -461,8 +461,8 @@ class RegExpEscape extends RegExpNormalChar { // TODO: Find a way to include a formfeed character // this.getUnescaped() = "f" and result = " " // or - isUnicode() and - result = getUnicode() + this.isUnicode() and + result = this.getUnicode() } predicate isIdentityEscape() { not this.getUnescaped() in ["n", "r", "t", "f"] } @@ -479,7 +479,7 @@ class RegExpEscape extends RegExpNormalChar { /** * Holds if this is a unicode escape. */ - private predicate isUnicode() { getText().prefix(2) = ["\\u", "\\U"] } + private predicate isUnicode() { this.getText().prefix(2) = ["\\u", "\\U"] } /** * Gets the unicode char for this escape. @@ -569,13 +569,13 @@ class RegExpCharacterClass extends RegExpTerm, TRegExpCharacterClass { predicate isUniversalClass() { // [^] - isInverted() and not exists(getAChild()) + this.isInverted() and not exists(this.getAChild()) or // [\w\W] and similar - not isInverted() and + not this.isInverted() and exists(string cce1, string cce2 | - cce1 = getAChild().(RegExpCharacterClassEscape).getValue() and - cce2 = getAChild().(RegExpCharacterClassEscape).getValue() + cce1 = this.getAChild().(RegExpCharacterClassEscape).getValue() and + cce2 = this.getAChild().(RegExpCharacterClassEscape).getValue() | cce1 != cce2 and cce1.toLowerCase() = cce2.toLowerCase() ) 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 169ebd191ba..b41edd28898 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -610,11 +610,11 @@ class DataFlowLambda extends DataFlowCallable, TLambda { override string toString() { result = lambda.toString() } - override CallNode getACall() { result = getCallableValue().getACall() } + override CallNode getACall() { result = this.getCallableValue().getACall() } override Scope getScope() { result = lambda.getEvaluatingScope() } - override NameNode getParameter(int n) { result = getParameter(getCallableValue(), n) } + override NameNode getParameter(int n) { result = getParameter(this.getCallableValue(), n) } override string getName() { result = "Lambda callable" } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll b/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll index df1ee7bba16..76cc1573b24 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll @@ -62,12 +62,12 @@ class LocalSourceNode extends Node { /** * Gets a read of attribute `attrName` on this node. */ - AttrRead getAnAttributeRead(string attrName) { result = getAnAttributeReference(attrName) } + AttrRead getAnAttributeRead(string attrName) { result = this.getAnAttributeReference(attrName) } /** * Gets a write of attribute `attrName` on this node. */ - AttrWrite getAnAttributeWrite(string attrName) { result = getAnAttributeReference(attrName) } + AttrWrite getAnAttributeWrite(string attrName) { result = this.getAnAttributeReference(attrName) } /** * Gets a reference (read or write) of any attribute on this node. @@ -81,12 +81,12 @@ class LocalSourceNode extends Node { /** * Gets a read of any attribute on this node. */ - AttrRead getAnAttributeRead() { result = getAnAttributeReference() } + AttrRead getAnAttributeRead() { result = this.getAnAttributeReference() } /** * Gets a write of any attribute on this node. */ - AttrWrite getAnAttributeWrite() { result = getAnAttributeReference() } + AttrWrite getAnAttributeWrite() { result = this.getAnAttributeReference() } /** * Gets a call to this node. From a6115687aa712f0f3d12f1af7baf27445d38d33a Mon Sep 17 00:00:00 2001 From: Taus <tausbn@gmail.com> Date: Wed, 13 Oct 2021 13:31:27 +0000 Subject: [PATCH 269/361] Python: More implicit `this` --- python/ql/lib/semmle/python/essa/Definitions.qll | 4 ++-- python/ql/lib/semmle/python/essa/Essa.qll | 4 ++-- python/ql/lib/semmle/python/frameworks/Django.qll | 10 ++++++---- python/ql/lib/semmle/python/frameworks/Flask.qll | 4 ++-- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 4 ++-- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/python/ql/lib/semmle/python/essa/Definitions.qll b/python/ql/lib/semmle/python/essa/Definitions.qll index 752ff9da329..e4e4bba747f 100644 --- a/python/ql/lib/semmle/python/essa/Definitions.qll +++ b/python/ql/lib/semmle/python/essa/Definitions.qll @@ -225,9 +225,9 @@ class ModuleVariable extends SsaSourceVariable { } override ControlFlowNode getAnImplicitUse() { - result = global_variable_callnode() + result = this.global_variable_callnode() or - result = global_variable_import() + result = this.global_variable_import() or exists(ImportTimeScope scope | scope.entryEdge(result, _) | this = scope.getOuterVariable(_) or diff --git a/python/ql/lib/semmle/python/essa/Essa.qll b/python/ql/lib/semmle/python/essa/Essa.qll index d703b72242a..2d403070c4c 100644 --- a/python/ql/lib/semmle/python/essa/Essa.qll +++ b/python/ql/lib/semmle/python/essa/Essa.qll @@ -41,7 +41,7 @@ class EssaVariable extends TEssaDefinition { */ ControlFlowNode getASourceUse() { exists(SsaSourceVariable var | - result = use_for_var(var) and + result = this.use_for_var(var) and result = var.getASourceUse() ) } @@ -258,7 +258,7 @@ class PhiFunction extends EssaDefinition, TPhiFunction { /** Gets another definition of the same source variable that reaches this definition. */ private EssaDefinition reachingDefinition(BasicBlock pred) { result.getScope() = this.getScope() and - result.getSourceVariable() = pred_var(pred) and + result.getSourceVariable() = this.pred_var(pred) and result.reachesEndOfBlock(pred) } diff --git a/python/ql/lib/semmle/python/frameworks/Django.qll b/python/ql/lib/semmle/python/frameworks/Django.qll index 08afa55635a..89ff0537c97 100644 --- a/python/ql/lib/semmle/python/frameworks/Django.qll +++ b/python/ql/lib/semmle/python/frameworks/Django.qll @@ -1844,11 +1844,13 @@ private module PrivateDjango { t.start() and result.asCfgNode().(CallNode).getFunction() = this.asViewRef().asCfgNode() or - exists(DataFlow::TypeTracker t2 | result = asViewResult(t2).track(t2, t)) + exists(DataFlow::TypeTracker t2 | result = this.asViewResult(t2).track(t2, t)) } /** Gets a reference to the result of calling the `as_view` classmethod of this class. */ - DataFlow::Node asViewResult() { asViewResult(DataFlow::TypeTracker::end()).flowsTo(result) } + DataFlow::Node asViewResult() { + this.asViewResult(DataFlow::TypeTracker::end()).flowsTo(result) + } } /** A class that we consider a django View class. */ @@ -1944,10 +1946,10 @@ private module PrivateDjango { abstract DataFlow::Node getViewArg(); final override DjangoRouteHandler getARequestHandler() { - poorMansFunctionTracker(result) = getViewArg() + poorMansFunctionTracker(result) = this.getViewArg() or exists(DjangoViewClass vc | - getViewArg() = vc.asViewResult() and + this.getViewArg() = vc.asViewResult() and result = vc.getARequestHandler() ) } diff --git a/python/ql/lib/semmle/python/frameworks/Flask.qll b/python/ql/lib/semmle/python/frameworks/Flask.qll index e854e07658b..3c2cc5af5ec 100644 --- a/python/ql/lib/semmle/python/frameworks/Flask.qll +++ b/python/ql/lib/semmle/python/frameworks/Flask.qll @@ -292,12 +292,12 @@ module Flask { override Function getARequestHandler() { exists(DataFlow::LocalSourceNode func_src | - func_src.flowsTo(getViewArg()) and + func_src.flowsTo(this.getViewArg()) and func_src.asExpr().(CallableExpr) = result.getDefinition() ) or exists(FlaskViewClass vc | - getViewArg() = vc.asViewResult().getAUse() and + this.getViewArg() = vc.asViewResult().getAUse() and result = vc.getARequestHandler() ) } diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index f89f74f3c34..0267d2a80b9 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -397,8 +397,8 @@ private module StdlibPrivate { result = this.get_executable_arg() or exists(DataFlow::Node arg_args, boolean shell | - arg_args = get_args_arg() and - shell = get_shell_arg_value() + arg_args = this.get_args_arg() and + shell = this.get_shell_arg_value() | // When "executable" argument is set, and "shell" argument is `False`, the // "args" argument will only be used to set the program name and arguments to From 2e61ae244ad7d3774275551f8724be121140ce51 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 13 Oct 2021 15:55:58 +0100 Subject: [PATCH 270/361] C++: Set literals. --- .../semmle/code/cpp/security/PrivateData.qll | 39 +++++----- cpp/ql/lib/semmle/code/cpp/Specifier.qll | 14 +--- .../code/cpp/security/CommandExecution.qll | 76 +++++-------------- .../semmle/code/cpp/security/OutputWrite.qll | 19 ++--- .../code/cpp/security/SensitiveExprs.qll | 13 +--- .../Magic Constants/MagicConstants.qll | 10 +-- .../Conversion/NonzeroValueCastToPointer.ql | 17 +++-- .../Memory Management/StrncpyFlippedArgs.ql | 28 +++---- cpp/ql/src/Power of 10/Rule 1/UseOfJmp.ql | 5 +- .../src/Security/CWE/CWE-022/TaintedPath.ql | 13 +--- .../CWE-170/ImproperNullTerminationTainted.ql | 6 +- cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql | 9 +-- .../library-tests/access/noPublic/noPublic.ql | 2 +- .../library-tests/ir/points_to/points_to.ql | 7 +- 14 files changed, 83 insertions(+), 175 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateData.qll b/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateData.qll index 621e8aad707..ec37e8ce86c 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateData.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateData.qll @@ -13,26 +13,25 @@ import cpp /** A string for `match` that identifies strings that look like they represent private data. */ private string privateNames() { - // Inspired by the list on https://cwe.mitre.org/data/definitions/359.html - // Government identifiers, such as Social Security Numbers - result = "%social%security%number%" or - // Contact information, such as home addresses and telephone numbers - result = "%postcode%" or - result = "%zipcode%" or - // result = "%telephone%" or - // Geographic location - where the user is (or was) - result = "%latitude%" or - result = "%longitude%" or - // Financial data - such as credit card numbers, salary, bank accounts, and debts - result = "%creditcard%" or - result = "%salary%" or - result = "%bankaccount%" or - // Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc. - // result = "%email%" or - // result = "%mobile%" or - result = "%employer%" or - // Health - medical conditions, insurance status, prescription records - result = "%medical%" + result = + [ + // Inspired by the list on https://cwe.mitre.org/data/definitions/359.html + // Government identifiers, such as Social Security Numbers + "%social%security%number%", + // Contact information, such as home addresses and telephone numbers + "%postcode%", "%zipcode%", + // result = "%telephone%" or + // Geographic location - where the user is (or was) + "%latitude%", "%longitude%", + // Financial data - such as credit card numbers, salary, bank accounts, and debts + "%creditcard%", "%salary%", "%bankaccount%", + // Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc. + // result = "%email%" or + // result = "%mobile%" or + "%employer%", + // Health - medical conditions, insurance status, prescription records + "%medical%" + ] } /** An expression that might contain private data. */ diff --git a/cpp/ql/lib/semmle/code/cpp/Specifier.qll b/cpp/ql/lib/semmle/code/cpp/Specifier.qll index 4a425b690f4..a60726252a1 100644 --- a/cpp/ql/lib/semmle/code/cpp/Specifier.qll +++ b/cpp/ql/lib/semmle/code/cpp/Specifier.qll @@ -32,9 +32,7 @@ class Specifier extends Element, @specifier { */ class FunctionSpecifier extends Specifier { FunctionSpecifier() { - this.hasName("inline") or - this.hasName("virtual") or - this.hasName("explicit") + this.hasName(["inline", "virtual", "explicit"]) } override string getAPrimaryQlClass() { result = "FunctionSpecifier" } @@ -46,11 +44,7 @@ class FunctionSpecifier extends Specifier { */ class StorageClassSpecifier extends Specifier { StorageClassSpecifier() { - this.hasName("auto") or - this.hasName("register") or - this.hasName("static") or - this.hasName("extern") or - this.hasName("mutable") + this.hasName(["auto", "register", "static", "extern", "mutable"]) } override string getAPrimaryQlClass() { result = "StorageClassSpecifier" } @@ -61,9 +55,7 @@ class StorageClassSpecifier extends Specifier { */ class AccessSpecifier extends Specifier { AccessSpecifier() { - this.hasName("public") or - this.hasName("protected") or - this.hasName("private") + this.hasName(["public", "protected", "private"]) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/security/CommandExecution.qll b/cpp/ql/lib/semmle/code/cpp/security/CommandExecution.qll index f8f7c6c476f..063c7300031 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/CommandExecution.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/CommandExecution.qll @@ -28,35 +28,19 @@ class SystemFunction extends FunctionWithWrappers instanceof CommandExecutionFun */ class VarargsExecFunctionCall extends FunctionCall { VarargsExecFunctionCall() { - getTarget().hasGlobalName("execl") or - getTarget().hasGlobalName("execle") or - getTarget().hasGlobalName("execlp") or - // Windows - getTarget().hasGlobalName("_execl") or - getTarget().hasGlobalName("_execle") or - getTarget().hasGlobalName("_execlp") or - getTarget().hasGlobalName("_execlpe") or - getTarget().hasGlobalName("_spawnl") or - getTarget().hasGlobalName("_spawnle") or - getTarget().hasGlobalName("_spawnlp") or - getTarget().hasGlobalName("_spawnlpe") or - getTarget().hasGlobalName("_wexecl") or - getTarget().hasGlobalName("_wexecle") or - getTarget().hasGlobalName("_wexeclp") or - getTarget().hasGlobalName("_wexeclpe") or - getTarget().hasGlobalName("_wspawnl") or - getTarget().hasGlobalName("_wspawnle") or - getTarget().hasGlobalName("_wspawnlp") or - getTarget().hasGlobalName("_wspawnlpe") + getTarget() + .hasGlobalName([ + "execl", "execle", "execlp", + // Windows + "_execl", "_execle", "_execlp", "_execlpe", "_spawnl", "_spawnle", "_spawnlp", + "_spawnlpe", "_wexecl", "_wexecle", "_wexeclp", "_wexeclpe", "_wspawnl", "_wspawnle", + "_wspawnlp", "_wspawnlpe" + ]) } /** Whether the last argument to the function is an environment pointer */ predicate hasEnvironmentArgument() { - getTarget().hasGlobalName("execle") or - getTarget().hasGlobalName("_execle") or - getTarget().hasGlobalName("_execlpe") or - getTarget().hasGlobalName("_wexecle") or - getTarget().hasGlobalName("_wexeclpe") + getTarget().hasGlobalName(["execle", "_execle", "_execlpe", "_wexecle", "_wexeclpe"]) } /** @@ -83,11 +67,7 @@ class VarargsExecFunctionCall extends FunctionCall { * all the other ones start with the command. */ private int getCommandIdx() { - if - getTarget().getName().matches("\\_spawn%") or - getTarget().getName().matches("\\_wspawn%") - then result = 1 - else result = 0 + if getTarget().getName().matches(["\\_spawn%", "\\_wspawn%"]) then result = 1 else result = 0 } } @@ -98,28 +78,14 @@ class VarargsExecFunctionCall extends FunctionCall { */ class ArrayExecFunctionCall extends FunctionCall { ArrayExecFunctionCall() { - getTarget().hasGlobalName("execv") or - getTarget().hasGlobalName("execvp") or - getTarget().hasGlobalName("execvpe") or - getTarget().hasGlobalName("execve") or - getTarget().hasGlobalName("fexecve") or - // Windows variants - getTarget().hasGlobalName("_execv") or - getTarget().hasGlobalName("_execve") or - getTarget().hasGlobalName("_execvp") or - getTarget().hasGlobalName("_execvpe") or - getTarget().hasGlobalName("_spawnv") or - getTarget().hasGlobalName("_spawnve") or - getTarget().hasGlobalName("_spawnvp") or - getTarget().hasGlobalName("_spawnvpe") or - getTarget().hasGlobalName("_wexecv") or - getTarget().hasGlobalName("_wexecve") or - getTarget().hasGlobalName("_wexecvp") or - getTarget().hasGlobalName("_wexecvpe") or - getTarget().hasGlobalName("_wspawnv") or - getTarget().hasGlobalName("_wspawnve") or - getTarget().hasGlobalName("_wspawnvp") or - getTarget().hasGlobalName("_wspawnvpe") + getTarget() + .hasGlobalName([ + "execv", "execvp", "execvpe", "execve", "fexecve", + // Windows variants + "_execv", "_execve", "_execvp", "_execvpe", "_spawnv", "_spawnve", "_spawnvp", + "_spawnvpe", "_wexecv", "_wexecve", "_wexecvp", "_wexecvpe", "_wspawnv", "_wspawnve", + "_wspawnvp", "_wspawnvpe" + ]) } /** The argument with the array of command arguments */ @@ -133,11 +99,7 @@ class ArrayExecFunctionCall extends FunctionCall { * all the other ones start with the command. */ private int getCommandIdx() { - if - getTarget().getName().matches("\\_spawn%") or - getTarget().getName().matches("\\_wspawn%") - then result = 1 - else result = 0 + if getTarget().getName().matches(["\\_spawn%", "\\_wspawn%"]) then result = 1 else result = 0 } } diff --git a/cpp/ql/lib/semmle/code/cpp/security/OutputWrite.qll b/cpp/ql/lib/semmle/code/cpp/security/OutputWrite.qll index 9ed22aa970f..affb9954926 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/OutputWrite.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/OutputWrite.qll @@ -21,14 +21,12 @@ class OutputWrite extends Expr { * A standard output or standard error variable. */ private predicate outputVariable(Variable v) { - // standard output - v.hasName("cout") or - v.hasName("wcout") or - // standard error - v.hasName("cerr") or - v.hasName("clog") or - v.hasName("wcerr") or - v.hasName("wclog") + v.hasName([ + // standard output + "cout", "wcout", + // standard error + "cerr", "clog", "wcerr", "wclog" + ]) } /** @@ -64,10 +62,7 @@ private predicate outputWrite(Expr write, Expr source) { arg >= f.(FormattingFunction).getFormatParameterIndex() or // puts, putchar - ( - f.hasGlobalOrStdName("puts") or - f.hasGlobalOrStdName("putchar") - ) and + f.hasGlobalOrStdName(["puts", "putchar"]) and arg = 0 or exists(Call wrappedCall, Expr wrappedSource | diff --git a/cpp/ql/lib/semmle/code/cpp/security/SensitiveExprs.qll b/cpp/ql/lib/semmle/code/cpp/security/SensitiveExprs.qll index 22e0ee71b66..f46c5b279a5 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/SensitiveExprs.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/SensitiveExprs.qll @@ -11,17 +11,8 @@ import cpp */ bindingset[s] private predicate suspicious(string s) { - ( - s.matches("%password%") or - s.matches("%passwd%") or - s.matches("%trusted%") - ) and - not ( - s.matches("%hash%") or - s.matches("%crypt%") or - s.matches("%file%") or - s.matches("%path%") - ) + s.matches(["%password%", "%passwd%", "%trusted%"]) and + not s.matches(["%hash%", "%crypt%", "%file%", "%path%"]) } /** diff --git a/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll b/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll index 587b64b60b3..fce3d286a5f 100644 --- a/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll +++ b/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll @@ -58,15 +58,7 @@ predicate intTrivial(Literal lit) { exists(string v | trivialIntValue(v) and v = predicate longTrivial(Literal lit) { exists(string v | trivialLongValue(v) and v = lit.getValue()) } predicate powerOfTen(float f) { - f = 10 or - f = 100 or - f = 1000 or - f = 10000 or - f = 100000 or - f = 1000000 or - f = 10000000 or - f = 100000000 or - f = 1000000000 + f = [10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000] } predicate floatTrivial(Literal lit) { diff --git a/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql b/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql index 87f52198b0d..47842118874 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql @@ -13,14 +13,15 @@ import cpp predicate commonErrorCode(string value) { - value = "0" or - value = "1" or - value = "-1" or - value = "18446744073709551615" or // 2^64-1, i.e. -1 as an unsigned int64 - value = "4294967295" or // 2^32-1, i.e. -1 as an unsigned int32 - value = "3735928559" or // 0xdeadbeef - value = "3735929054" or // 0xdeadc0de - value = "3405691582" // 0xcafebabe + value = + [ + "0", "1", "-1", // common error codes + "18446744073709551615", // 2^64-1, i.e. -1 as an unsigned int64 + "4294967295", // 2^32-1, i.e. -1 as an unsigned int32 + "3735928559", // 0xdeadbeef + "3735929054", // 0xdeadc0de + "3405691582" // 0xcafebabe + ] } from Expr e diff --git a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql index 8e7bc5bfcf4..f7eca2304b3 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql @@ -43,23 +43,25 @@ predicate isSizePlus(Expr e, BufferSizeExpr baseSize, int plus) { predicate strncpyFunction(Function f, int argDest, int argSrc, int argLimit) { exists(string name | name = f.getName() | - ( - name = "strcpy_s" or // strcpy_s(dst, max_amount, src) - name = "wcscpy_s" or // wcscpy_s(dst, max_amount, src) - name = "_mbscpy_s" // _mbscpy_s(dst, max_amount, src) - ) and + name = + [ + "strcpy_s", // strcpy_s(dst, max_amount, src) + "wcscpy_s", // wcscpy_s(dst, max_amount, src) + "_mbscpy_s" // _mbscpy_s(dst, max_amount, src) + ] and argDest = 0 and argSrc = 2 and argLimit = 1 or - ( - name = "strncpy" or // strncpy(dst, src, max_amount) - name = "strncpy_l" or // strncpy_l(dst, src, max_amount, locale) - name = "wcsncpy" or // wcsncpy(dst, src, max_amount) - name = "_wcsncpy_l" or // _wcsncpy_l(dst, src, max_amount, locale) - name = "_mbsncpy" or // _mbsncpy(dst, src, max_amount) - name = "_mbsncpy_l" // _mbsncpy_l(dst, src, max_amount, locale) - ) and + name = + [ + "strncpy", // strncpy(dst, src, max_amount) + "strncpy_l", // strncpy_l(dst, src, max_amount, locale) + "wcsncpy", // wcsncpy(dst, src, max_amount) + "_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale) + "_mbsncpy", // _mbsncpy(dst, src, max_amount) + "_mbsncpy_l" // _mbsncpy_l(dst, src, max_amount, locale) + ] and argDest = 0 and argSrc = 1 and argLimit = 2 diff --git a/cpp/ql/src/Power of 10/Rule 1/UseOfJmp.ql b/cpp/ql/src/Power of 10/Rule 1/UseOfJmp.ql index 9a6d143bfb6..0a98eafc70f 100644 --- a/cpp/ql/src/Power of 10/Rule 1/UseOfJmp.ql +++ b/cpp/ql/src/Power of 10/Rule 1/UseOfJmp.ql @@ -15,10 +15,7 @@ import cpp class ForbiddenFunction extends Function { ForbiddenFunction() { exists(string name | name = this.getName() | - name = "setjmp" or - name = "longjmp" or - name = "sigsetjmp" or - name = "siglongjmp" + name = ["setjmp", "longjmp", "sigsetjmp", "siglongjmp"] ) } } diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 5e22506d03a..fc8023053b0 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -26,12 +26,8 @@ import TaintedWithPath class FileFunction extends FunctionWithWrappers { FileFunction() { exists(string nme | this.hasGlobalName(nme) | - nme = "fopen" or - nme = "_fopen" or - nme = "_wfopen" or - nme = "open" or - nme = "_open" or - nme = "_wopen" or + nme = ["fopen", "_fopen", "_wfopen", "open", "_open", "_wopen"] + or // create file function on windows nme.matches("CreateFile%") ) @@ -40,10 +36,7 @@ class FileFunction extends FunctionWithWrappers { or // on any of the fstream classes, or filebuf exists(string nme | this.getDeclaringType().hasQualifiedName("std", nme) | - nme = "basic_fstream" or - nme = "basic_ifstream" or - nme = "basic_ofstream" or - nme = "basic_filebuf" + nme = ["basic_fstream", "basic_ifstream", "basic_ofstream", "basic_filebuf"] ) and // we look for either the open method or the constructor (this.getName() = "open" or this instanceof Constructor) diff --git a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql index 31ce1037b27..597a762a2bb 100644 --- a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql @@ -22,11 +22,7 @@ class TaintSource extends VariableAccess { this.getTarget() instanceof SemanticStackVariable and x.isUserInput(this, cause) | - cause = "read" or - cause = "fread" or - cause = "recv" or - cause = "recvfrom" or - cause = "recvmsg" + cause = ["read", "fread", "recv", "recvfrom", "recvmsg"] ) } diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql index 608374b241c..91b5e4e8b98 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql @@ -14,12 +14,5 @@ import cpp from Include i, string name where name = i.getIncludeText() and - ( - name.matches("%'%") or - name.matches("%\\\\%") or - name.matches("%/*%") or - name.matches("%//%") or - name.matches("%\"%\"%\"%") or - name.matches("%<%\"%>%") - ) + name.matches(["%'%", "%\\\\%", "%/*%", "%//%", "%\"%\"%\"%", "%<%\"%>%"]) select i, "AV Rule 53.1: Invalid character sequence in header file name '" + name + "'" diff --git a/cpp/ql/test/library-tests/access/noPublic/noPublic.ql b/cpp/ql/test/library-tests/access/noPublic/noPublic.ql index e6d78dcfd5a..c249ea45d74 100644 --- a/cpp/ql/test/library-tests/access/noPublic/noPublic.ql +++ b/cpp/ql/test/library-tests/access/noPublic/noPublic.ql @@ -3,5 +3,5 @@ import cpp from AccessSpecifier spec // There is no way to create "protected" access without writing the keyword // `protected` in the source, so we don't need to test for that. -where spec.hasName("private") or spec.hasName("public") +where spec.hasName(["private", "public"]) select spec diff --git a/cpp/ql/test/library-tests/ir/points_to/points_to.ql b/cpp/ql/test/library-tests/ir/points_to/points_to.ql index da090c5552e..b639a235ee8 100644 --- a/cpp/ql/test/library-tests/ir/points_to/points_to.ql +++ b/cpp/ql/test/library-tests/ir/points_to/points_to.ql @@ -3,12 +3,7 @@ private import TestUtilities.InlineExpectationsTest private import semmle.code.cpp.ir.internal.IntegerConstant as Ints private predicate ignoreAllocation(string name) { - name = "i" or - name = "p" or - name = "q" or - name = "s" or - name = "t" or - name = "?{AllAliased}" + name = ["i", "p", "q", "s", "t", "?{AllAliased}"] } private predicate ignoreFile(File file) { From 0d1632a5d2838f687304519eb5fe05c295d832ab Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg <aeisenberg@github.com> Date: Tue, 12 Oct 2021 14:34:02 -0700 Subject: [PATCH 271/361] Move tutorial directly into each qlpack Previously, the tutorial was injected during build time. This is much simpler. --- config/identical-files.json | 9 +- cpp/ql/lib/tutorial.qll | 1207 ++++++++++++++++++++++++++++++++ csharp/ql/lib/tutorial.qll | 1207 ++++++++++++++++++++++++++++++++ java/ql/lib/tutorial.qll | 1207 ++++++++++++++++++++++++++++++++ javascript/ql/lib/tutorial.qll | 1207 ++++++++++++++++++++++++++++++++ python/ql/lib/tutorial.qll | 1207 ++++++++++++++++++++++++++++++++ 6 files changed, 6043 insertions(+), 1 deletion(-) create mode 100644 cpp/ql/lib/tutorial.qll create mode 100644 csharp/ql/lib/tutorial.qll create mode 100644 java/ql/lib/tutorial.qll create mode 100644 javascript/ql/lib/tutorial.qll create mode 100644 python/ql/lib/tutorial.qll diff --git a/config/identical-files.json b/config/identical-files.json index 74ef7b82323..f968690fc49 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -461,5 +461,12 @@ "ReDoS Polynomial Python/JS": [ "javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll", "python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll" + ], + "CodeQL Tutorial": [ + "cpp/ql/lib/tutorial.qll", + "csharp/ql/lib/tutorial.qll", + "java/ql/lib/tutorial.qll", + "javascript/ql/lib/tutorial.qll", + "python/ql/lib/tutorial.qll" ] -} \ No newline at end of file +} diff --git a/cpp/ql/lib/tutorial.qll b/cpp/ql/lib/tutorial.qll new file mode 100644 index 00000000000..8cb1797a532 --- /dev/null +++ b/cpp/ql/lib/tutorial.qll @@ -0,0 +1,1207 @@ +/** + * This library is used in the QL detective tutorials. + * + * Note: Data is usually stored in a separate database and the QL libraries only contain predicates, + * but for this tutorial both the data and the predicates are stored in the library. + */ +class Person extends string { + Person() { + this = "Ronil" or + this = "Dina" or + this = "Ravi" or + this = "Bruce" or + this = "Jo" or + this = "Aida" or + this = "Esme" or + this = "Charlie" or + this = "Fred" or + this = "Meera" or + this = "Maya" or + this = "Chad" or + this = "Tiana" or + this = "Laura" or + this = "George" or + this = "Will" or + this = "Mary" or + this = "Almira" or + this = "Susannah" or + this = "Rhoda" or + this = "Cynthia" or + this = "Eunice" or + this = "Olive" or + this = "Virginia" or + this = "Angeline" or + this = "Helen" or + this = "Cornelia" or + this = "Harriet" or + this = "Mahala" or + this = "Abby" or + this = "Margaret" or + this = "Deb" or + this = "Minerva" or + this = "Severus" or + this = "Lavina" or + this = "Adeline" or + this = "Cath" or + this = "Elisa" or + this = "Lucretia" or + this = "Anne" or + this = "Eleanor" or + this = "Joanna" or + this = "Adam" or + this = "Agnes" or + this = "Rosanna" or + this = "Clara" or + this = "Melissa" or + this = "Amy" or + this = "Isabel" or + this = "Jemima" or + this = "Cordelia" or + this = "Melinda" or + this = "Delila" or + this = "Jeremiah" or + this = "Elijah" or + this = "Hester" or + this = "Walter" or + this = "Oliver" or + this = "Hugh" or + this = "Aaron" or + this = "Reuben" or + this = "Eli" or + this = "Amos" or + this = "Augustus" or + this = "Theodore" or + this = "Ira" or + this = "Timothy" or + this = "Cyrus" or + this = "Horace" or + this = "Simon" or + this = "Asa" or + this = "Frank" or + this = "Nelson" or + this = "Leonard" or + this = "Harrison" or + this = "Anthony" or + this = "Louis" or + this = "Milton" or + this = "Noah" or + this = "Cornelius" or + this = "Abdul" or + this = "Warren" or + this = "Harvey" or + this = "Dennis" or + this = "Wesley" or + this = "Sylvester" or + this = "Gilbert" or + this = "Sullivan" or + this = "Edmund" or + this = "Wilson" or + this = "Perry" or + this = "Matthew" or + this = "Simba" or + this = "Nala" or + this = "Rafiki" or + this = "Shenzi" or + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Edwin" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" or + this = "Stephen" + } + + /** Gets the hair color of the person. If the person is bald, there is no result. */ + string getHairColor() { + this = "Ronil" and result = "black" + or + this = "Dina" and result = "black" + or + this = "Ravi" and result = "black" + or + this = "Bruce" and result = "brown" + or + this = "Jo" and result = "red" + or + this = "Aida" and result = "blond" + or + this = "Esme" and result = "blond" + or + this = "Fred" and result = "gray" + or + this = "Meera" and result = "brown" + or + this = "Maya" and result = "brown" + or + this = "Chad" and result = "brown" + or + this = "Tiana" and result = "black" + or + this = "Laura" and result = "blond" + or + this = "George" and result = "blond" + or + this = "Will" and result = "blond" + or + this = "Mary" and result = "blond" + or + this = "Almira" and result = "black" + or + this = "Susannah" and result = "blond" + or + this = "Rhoda" and result = "blond" + or + this = "Cynthia" and result = "gray" + or + this = "Eunice" and result = "white" + or + this = "Olive" and result = "brown" + or + this = "Virginia" and result = "brown" + or + this = "Angeline" and result = "red" + or + this = "Helen" and result = "white" + or + this = "Cornelia" and result = "gray" + or + this = "Harriet" and result = "white" + or + this = "Mahala" and result = "black" + or + this = "Abby" and result = "red" + or + this = "Margaret" and result = "brown" + or + this = "Deb" and result = "brown" + or + this = "Minerva" and result = "brown" + or + this = "Severus" and result = "black" + or + this = "Lavina" and result = "brown" + or + this = "Adeline" and result = "brown" + or + this = "Cath" and result = "brown" + or + this = "Elisa" and result = "brown" + or + this = "Lucretia" and result = "gray" + or + this = "Anne" and result = "black" + or + this = "Eleanor" and result = "brown" + or + this = "Joanna" and result = "brown" + or + this = "Adam" and result = "black" + or + this = "Agnes" and result = "black" + or + this = "Rosanna" and result = "gray" + or + this = "Clara" and result = "blond" + or + this = "Melissa" and result = "brown" + or + this = "Amy" and result = "brown" + or + this = "Isabel" and result = "black" + or + this = "Jemima" and result = "red" + or + this = "Cordelia" and result = "red" + or + this = "Melinda" and result = "gray" + or + this = "Delila" and result = "white" + or + this = "Jeremiah" and result = "gray" + or + this = "Hester" and result = "black" + or + this = "Walter" and result = "black" + or + this = "Aaron" and result = "gray" + or + this = "Reuben" and result = "gray" + or + this = "Eli" and result = "gray" + or + this = "Amos" and result = "white" + or + this = "Augustus" and result = "white" + or + this = "Theodore" and result = "white" + or + this = "Timothy" and result = "brown" + or + this = "Cyrus" and result = "brown" + or + this = "Horace" and result = "brown" + or + this = "Simon" and result = "brown" + or + this = "Asa" and result = "brown" + or + this = "Frank" and result = "brown" + or + this = "Nelson" and result = "black" + or + this = "Leonard" and result = "black" + or + this = "Harrison" and result = "black" + or + this = "Anthony" and result = "black" + or + this = "Louis" and result = "black" + or + this = "Milton" and result = "blond" + or + this = "Noah" and result = "blond" + or + this = "Cornelius" and result = "red" + or + this = "Abdul" and result = "brown" + or + this = "Warren" and result = "red" + or + this = "Harvey" and result = "blond" + or + this = "Dennis" and result = "blond" + or + this = "Wesley" and result = "brown" + or + this = "Sylvester" and result = "brown" + or + this = "Gilbert" and result = "brown" + or + this = "Sullivan" and result = "brown" + or + this = "Edmund" and result = "brown" + or + this = "Wilson" and result = "blond" + or + this = "Perry" and result = "black" + or + this = "Simba" and result = "brown" + or + this = "Nala" and result = "brown" + or + this = "Rafiki" and result = "red" + or + this = "Shenzi" and result = "gray" + or + this = "Ernest" and result = "blond" + or + this = "Gertrude" and result = "brown" + or + this = "Oscar" and result = "blond" + or + this = "Lilian" and result = "brown" + or + this = "Raymond" and result = "brown" + or + this = "Elgar" and result = "brown" + or + this = "Elmer" and result = "brown" + or + this = "Herbert" and result = "brown" + or + this = "Maude" and result = "brown" + or + this = "Mae" and result = "brown" + or + this = "Otto" and result = "black" + or + this = "Edwin" and result = "black" + or + this = "Ophelia" and result = "brown" + or + this = "Parsley" and result = "brown" + or + this = "Sage" and result = "brown" + or + this = "Rosemary" and result = "brown" + or + this = "Thyme" and result = "brown" + or + this = "Garfunkel" and result = "brown" + or + this = "King Basil" and result = "brown" + or + this = "Stephen" and result = "black" + or + this = "Stephen" and result = "gray" + } + + /** Gets the age of the person (in years). If the person is deceased, there is no result. */ + int getAge() { + this = "Ronil" and result = 21 + or + this = "Dina" and result = 53 + or + this = "Ravi" and result = 16 + or + this = "Bruce" and result = 35 + or + this = "Jo" and result = 47 + or + this = "Aida" and result = 26 + or + this = "Esme" and result = 25 + or + this = "Charlie" and result = 31 + or + this = "Fred" and result = 68 + or + this = "Meera" and result = 62 + or + this = "Maya" and result = 29 + or + this = "Chad" and result = 49 + or + this = "Tiana" and result = 18 + or + this = "Laura" and result = 2 + or + this = "George" and result = 3 + or + this = "Will" and result = 41 + or + this = "Mary" and result = 51 + or + this = "Almira" and result = 1 + or + this = "Susannah" and result = 97 + or + this = "Rhoda" and result = 39 + or + this = "Cynthia" and result = 89 + or + this = "Eunice" and result = 83 + or + this = "Olive" and result = 25 + or + this = "Virginia" and result = 52 + or + this = "Angeline" and result = 22 + or + this = "Helen" and result = 79 + or + this = "Cornelia" and result = 59 + or + this = "Harriet" and result = 57 + or + this = "Mahala" and result = 61 + or + this = "Abby" and result = 24 + or + this = "Margaret" and result = 59 + or + this = "Deb" and result = 31 + or + this = "Minerva" and result = 72 + or + this = "Severus" and result = 61 + or + this = "Lavina" and result = 33 + or + this = "Adeline" and result = 17 + or + this = "Cath" and result = 22 + or + this = "Elisa" and result = 9 + or + this = "Lucretia" and result = 56 + or + this = "Anne" and result = 11 + or + this = "Eleanor" and result = 80 + or + this = "Joanna" and result = 43 + or + this = "Adam" and result = 37 + or + this = "Agnes" and result = 47 + or + this = "Rosanna" and result = 61 + or + this = "Clara" and result = 31 + or + this = "Melissa" and result = 37 + or + this = "Amy" and result = 12 + or + this = "Isabel" and result = 6 + or + this = "Jemima" and result = 16 + or + this = "Cordelia" and result = 21 + or + this = "Melinda" and result = 55 + or + this = "Delila" and result = 66 + or + this = "Jeremiah" and result = 54 + or + this = "Elijah" and result = 42 + or + this = "Hester" and result = 68 + or + this = "Walter" and result = 66 + or + this = "Oliver" and result = 33 + or + this = "Hugh" and result = 51 + or + this = "Aaron" and result = 49 + or + this = "Reuben" and result = 58 + or + this = "Eli" and result = 70 + or + this = "Amos" and result = 65 + or + this = "Augustus" and result = 56 + or + this = "Theodore" and result = 69 + or + this = "Ira" and result = 1 + or + this = "Timothy" and result = 54 + or + this = "Cyrus" and result = 78 + or + this = "Horace" and result = 34 + or + this = "Simon" and result = 23 + or + this = "Asa" and result = 28 + or + this = "Frank" and result = 59 + or + this = "Nelson" and result = 38 + or + this = "Leonard" and result = 58 + or + this = "Harrison" and result = 7 + or + this = "Anthony" and result = 2 + or + this = "Louis" and result = 34 + or + this = "Milton" and result = 36 + or + this = "Noah" and result = 48 + or + this = "Cornelius" and result = 41 + or + this = "Abdul" and result = 67 + or + this = "Warren" and result = 47 + or + this = "Harvey" and result = 31 + or + this = "Dennis" and result = 39 + or + this = "Wesley" and result = 13 + or + this = "Sylvester" and result = 19 + or + this = "Gilbert" and result = 16 + or + this = "Sullivan" and result = 17 + or + this = "Edmund" and result = 29 + or + this = "Wilson" and result = 27 + or + this = "Perry" and result = 31 + or + this = "Matthew" and result = 55 + or + this = "Simba" and result = 8 + or + this = "Nala" and result = 7 + or + this = "Rafiki" and result = 76 + or + this = "Shenzi" and result = 67 + } + + /** Gets the height of the person (in cm). If the person is deceased, there is no result. */ + float getHeight() { + this = "Ronil" and result = 183.0 + or + this = "Dina" and result = 155.1 + or + this = "Ravi" and result = 175.2 + or + this = "Bruce" and result = 191.3 + or + this = "Jo" and result = 163.4 + or + this = "Aida" and result = 182.6 + or + this = "Esme" and result = 176.9 + or + this = "Charlie" and result = 189.7 + or + this = "Fred" and result = 179.4 + or + this = "Meera" and result = 160.1 + or + this = "Maya" and result = 153.0 + or + this = "Chad" and result = 168.5 + or + this = "Tiana" and result = 149.7 + or + this = "Laura" and result = 87.5 + or + this = "George" and result = 96.4 + or + this = "Will" and result = 167.1 + or + this = "Mary" and result = 159.8 + or + this = "Almira" and result = 62.1 + or + this = "Susannah" and result = 145.8 + or + this = "Rhoda" and result = 180.1 + or + this = "Cynthia" and result = 161.8 + or + this = "Eunice" and result = 153.2 + or + this = "Olive" and result = 179.9 + or + this = "Virginia" and result = 165.1 + or + this = "Angeline" and result = 172.3 + or + this = "Helen" and result = 163.1 + or + this = "Cornelia" and result = 160.8 + or + this = "Harriet" and result = 163.2 + or + this = "Mahala" and result = 157.7 + or + this = "Abby" and result = 174.5 + or + this = "Margaret" and result = 165.6 + or + this = "Deb" and result = 171.6 + or + this = "Minerva" and result = 168.7 + or + this = "Severus" and result = 188.8 + or + this = "Lavina" and result = 155.1 + or + this = "Adeline" and result = 165.5 + or + this = "Cath" and result = 147.8 + or + this = "Elisa" and result = 129.4 + or + this = "Lucretia" and result = 153.6 + or + this = "Anne" and result = 140.4 + or + this = "Eleanor" and result = 151.1 + or + this = "Joanna" and result = 167.2 + or + this = "Adam" and result = 155.5 + or + this = "Agnes" and result = 156.8 + or + this = "Rosanna" and result = 162.4 + or + this = "Clara" and result = 158.6 + or + this = "Melissa" and result = 182.3 + or + this = "Amy" and result = 147.1 + or + this = "Isabel" and result = 121.4 + or + this = "Jemima" and result = 149.8 + or + this = "Cordelia" and result = 151.7 + or + this = "Melinda" and result = 154.4 + or + this = "Delila" and result = 163.4 + or + this = "Jeremiah" and result = 167.5 + or + this = "Elijah" and result = 184.5 + or + this = "Hester" and result = 152.7 + or + this = "Walter" and result = 159.6 + or + this = "Oliver" and result = 192.4 + or + this = "Hugh" and result = 173.1 + or + this = "Aaron" and result = 176.6 + or + this = "Reuben" and result = 169.9 + or + this = "Eli" and result = 180.4 + or + this = "Amos" and result = 167.4 + or + this = "Augustus" and result = 156.5 + or + this = "Theodore" and result = 176.6 + or + this = "Ira" and result = 54.1 + or + this = "Timothy" and result = 172.2 + or + this = "Cyrus" and result = 157.9 + or + this = "Horace" and result = 169.3 + or + this = "Simon" and result = 157.1 + or + this = "Asa" and result = 149.4 + or + this = "Frank" and result = 167.2 + or + this = "Nelson" and result = 173.0 + or + this = "Leonard" and result = 172.0 + or + this = "Harrison" and result = 126.0 + or + this = "Anthony" and result = 98.4 + or + this = "Louis" and result = 186.8 + or + this = "Milton" and result = 157.8 + or + this = "Noah" and result = 190.5 + or + this = "Cornelius" and result = 183.1 + or + this = "Abdul" and result = 182.0 + or + this = "Warren" and result = 175.0 + or + this = "Harvey" and result = 169.3 + or + this = "Dennis" and result = 160.4 + or + this = "Wesley" and result = 139.8 + or + this = "Sylvester" and result = 188.2 + or + this = "Gilbert" and result = 177.6 + or + this = "Sullivan" and result = 168.3 + or + this = "Edmund" and result = 159.2 + or + this = "Wilson" and result = 167.6 + or + this = "Perry" and result = 189.1 + or + this = "Matthew" and result = 167.2 + or + this = "Simba" and result = 140.1 + or + this = "Nala" and result = 138.0 + or + this = "Rafiki" and result = 139.3 + or + this = "Shenzi" and result = 171.1 + } + + /** Gets the location of the person's home ("north", "south", "east", or "west"). If the person is deceased, there is no result. */ + string getLocation() { + this = "Ronil" and result = "north" + or + this = "Dina" and result = "north" + or + this = "Ravi" and result = "north" + or + this = "Bruce" and result = "south" + or + this = "Jo" and result = "west" + or + this = "Aida" and result = "east" + or + this = "Esme" and result = "east" + or + this = "Charlie" and result = "south" + or + this = "Fred" and result = "west" + or + this = "Meera" and result = "south" + or + this = "Maya" and result = "south" + or + this = "Chad" and result = "south" + or + this = "Tiana" and result = "west" + or + this = "Laura" and result = "south" + or + this = "George" and result = "south" + or + this = "Will" and result = "south" + or + this = "Mary" and result = "south" + or + this = "Almira" and result = "south" + or + this = "Susannah" and result = "north" + or + this = "Rhoda" and result = "north" + or + this = "Cynthia" and result = "north" + or + this = "Eunice" and result = "north" + or + this = "Olive" and result = "west" + or + this = "Virginia" and result = "west" + or + this = "Angeline" and result = "west" + or + this = "Helen" and result = "west" + or + this = "Cornelia" and result = "east" + or + this = "Harriet" and result = "east" + or + this = "Mahala" and result = "east" + or + this = "Abby" and result = "east" + or + this = "Margaret" and result = "east" + or + this = "Deb" and result = "east" + or + this = "Minerva" and result = "south" + or + this = "Severus" and result = "north" + or + this = "Lavina" and result = "east" + or + this = "Adeline" and result = "west" + or + this = "Cath" and result = "east" + or + this = "Elisa" and result = "east" + or + this = "Lucretia" and result = "north" + or + this = "Anne" and result = "north" + or + this = "Eleanor" and result = "south" + or + this = "Joanna" and result = "south" + or + this = "Adam" and result = "east" + or + this = "Agnes" and result = "east" + or + this = "Rosanna" and result = "east" + or + this = "Clara" and result = "east" + or + this = "Melissa" and result = "west" + or + this = "Amy" and result = "west" + or + this = "Isabel" and result = "west" + or + this = "Jemima" and result = "west" + or + this = "Cordelia" and result = "west" + or + this = "Melinda" and result = "west" + or + this = "Delila" and result = "south" + or + this = "Jeremiah" and result = "north" + or + this = "Elijah" and result = "north" + or + this = "Hester" and result = "east" + or + this = "Walter" and result = "east" + or + this = "Oliver" and result = "east" + or + this = "Hugh" and result = "south" + or + this = "Aaron" and result = "south" + or + this = "Reuben" and result = "west" + or + this = "Eli" and result = "west" + or + this = "Amos" and result = "east" + or + this = "Augustus" and result = "south" + or + this = "Theodore" and result = "west" + or + this = "Ira" and result = "south" + or + this = "Timothy" and result = "north" + or + this = "Cyrus" and result = "north" + or + this = "Horace" and result = "east" + or + this = "Simon" and result = "east" + or + this = "Asa" and result = "east" + or + this = "Frank" and result = "west" + or + this = "Nelson" and result = "west" + or + this = "Leonard" and result = "west" + or + this = "Harrison" and result = "north" + or + this = "Anthony" and result = "north" + or + this = "Louis" and result = "north" + or + this = "Milton" and result = "south" + or + this = "Noah" and result = "south" + or + this = "Cornelius" and result = "east" + or + this = "Abdul" and result = "east" + or + this = "Warren" and result = "west" + or + this = "Harvey" and result = "west" + or + this = "Dennis" and result = "west" + or + this = "Wesley" and result = "west" + or + this = "Sylvester" and result = "south" + or + this = "Gilbert" and result = "east" + or + this = "Sullivan" and result = "east" + or + this = "Edmund" and result = "north" + or + this = "Wilson" and result = "north" + or + this = "Perry" and result = "west" + or + this = "Matthew" and result = "east" + or + this = "Simba" and result = "south" + or + this = "Nala" and result = "south" + or + this = "Rafiki" and result = "north" + or + this = "Shenzi" and result = "west" + } + + /** Holds if the person is deceased. */ + predicate isDeceased() { + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Edwin" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" + } + + /** Gets a parent of the person (alive or deceased). */ + Person getAParent() { + this = "Stephen" and result = "Edmund" + or + this = "Edmund" and result = "Augustus" + or + this = "Augustus" and result = "Stephen" + or + this = "Abby" and result = "Cornelia" + or + this = "Abby" and result = "Amos" + or + this = "Abdul" and result = "Susannah" + or + this = "Adam" and result = "Amos" + or + this = "Adeline" and result = "Melinda" + or + this = "Adeline" and result = "Frank" + or + this = "Agnes" and result = "Abdul" + or + this = "Aida" and result = "Agnes" + or + this = "Almira" and result = "Sylvester" + or + this = "Amos" and result = "Eunice" + or + this = "Amy" and result = "Noah" + or + this = "Amy" and result = "Chad" + or + this = "Angeline" and result = "Reuben" + or + this = "Angeline" and result = "Lucretia" + or + this = "Anne" and result = "Rhoda" + or + this = "Anne" and result = "Louis" + or + this = "Anthony" and result = "Lavina" + or + this = "Anthony" and result = "Asa" + or + this = "Asa" and result = "Cornelia" + or + this = "Cath" and result = "Harriet" + or + this = "Charlie" and result = "Matthew" + or + this = "Clara" and result = "Ernest" + or + this = "Cornelia" and result = "Cynthia" + or + this = "Cornelius" and result = "Eli" + or + this = "Deb" and result = "Margaret" + or + this = "Dennis" and result = "Fred" + or + this = "Eli" and result = "Susannah" + or + this = "Elijah" and result = "Delila" + or + this = "Elisa" and result = "Deb" + or + this = "Elisa" and result = "Horace" + or + this = "Esme" and result = "Margaret" + or + this = "Frank" and result = "Eleanor" + or + this = "Frank" and result = "Cyrus" + or + this = "George" and result = "Maya" + or + this = "George" and result = "Wilson" + or + this = "Gilbert" and result = "Cornelius" + or + this = "Harriet" and result = "Cynthia" + or + this = "Harrison" and result = "Louis" + or + this = "Harvey" and result = "Fred" + or + this = "Helen" and result = "Susannah" + or + this = "Hester" and result = "Edwin" + or + this = "Hugh" and result = "Cyrus" + or + this = "Hugh" and result = "Helen" + or + this = "Ira" and result = "Maya" + or + this = "Ira" and result = "Wilson" + or + this = "Isabel" and result = "Perry" + or + this = "Isabel" and result = "Harvey" + or + this = "Jemima" and result = "Melinda" + or + this = "Jemima" and result = "Frank" + or + this = "Ernest" and result = "Lilian" + or + this = "Ernest" and result = "Oscar" + or + this = "Gertrude" and result = "Ophelia" + or + this = "Gertrude" and result = "Raymond" + or + this = "Lilian" and result = "Elgar" + or + this = "Lilian" and result = "Mae" + or + this = "Raymond" and result = "Elgar" + or + this = "Raymond" and result = "Mae" + or + this = "Elmer" and result = "Ophelia" + or + this = "Elmer" and result = "Raymond" + or + this = "Herbert" and result = "Ophelia" + or + this = "Herbert" and result = "Raymond" + or + this = "Maude" and result = "Ophelia" + or + this = "Maude" and result = "Raymond" + or + this = "Otto" and result = "Elgar" + or + this = "Otto" and result = "Mae" + or + this = "Edwin" and result = "Otto" + or + this = "Parsley" and result = "Simon" + or + this = "Parsley" and result = "Garfunkel" + or + this = "Sage" and result = "Simon" + or + this = "Sage" and result = "Garfunkel" + or + this = "Rosemary" and result = "Simon" + or + this = "Rosemary" and result = "Garfunkel" + or + this = "Thyme" and result = "Simon" + or + this = "Thyme" and result = "Garfunkel" + or + this = "King Basil" and result = "Ophelia" + or + this = "King Basil" and result = "Raymond" + or + this = "Jo" and result = "Theodore" + or + this = "Joanna" and result = "Shenzi" + or + this = "Laura" and result = "Maya" + or + this = "Laura" and result = "Wilson" + or + this = "Lavina" and result = "Mahala" + or + this = "Lavina" and result = "Walter" + or + this = "Leonard" and result = "Cyrus" + or + this = "Leonard" and result = "Helen" + or + this = "Lucretia" and result = "Eleanor" + or + this = "Lucretia" and result = "Cyrus" + or + this = "Mahala" and result = "Eunice" + or + this = "Margaret" and result = "Cynthia" + or + this = "Matthew" and result = "Cyrus" + or + this = "Matthew" and result = "Helen" + or + this = "Maya" and result = "Meera" + or + this = "Melinda" and result = "Rafiki" + or + this = "Melissa" and result = "Mahala" + or + this = "Melissa" and result = "Walter" + or + this = "Nala" and result = "Bruce" + or + this = "Nelson" and result = "Mahala" + or + this = "Nelson" and result = "Walter" + or + this = "Noah" and result = "Eli" + or + this = "Olive" and result = "Reuben" + or + this = "Olive" and result = "Lucretia" + or + this = "Oliver" and result = "Matthew" + or + this = "Perry" and result = "Leonard" + or + this = "Ravi" and result = "Dina" + or + this = "Simba" and result = "Will" + or + this = "Simon" and result = "Margaret" + or + this = "Sullivan" and result = "Cornelius" + or + this = "Sylvester" and result = "Timothy" + or + this = "Theodore" and result = "Susannah" + or + this = "Tiana" and result = "Jo" + or + this = "Virginia" and result = "Helen" + or + this = "Warren" and result = "Shenzi" + or + this = "Wesley" and result = "Warren" + or + this = "Wesley" and result = "Jo" + or + this = "Will" and result = "Eli" + } + + /** Holds if the person is allowed in the region. Initially, all villagers are allowed in every region. */ + predicate isAllowedIn(string region) { + region = "north" or + region = "south" or + region = "east" or + region = "west" + } +} + +/** Returns a parent of the person. */ +Person parentOf(Person p) { result = p.getAParent() } diff --git a/csharp/ql/lib/tutorial.qll b/csharp/ql/lib/tutorial.qll new file mode 100644 index 00000000000..8cb1797a532 --- /dev/null +++ b/csharp/ql/lib/tutorial.qll @@ -0,0 +1,1207 @@ +/** + * This library is used in the QL detective tutorials. + * + * Note: Data is usually stored in a separate database and the QL libraries only contain predicates, + * but for this tutorial both the data and the predicates are stored in the library. + */ +class Person extends string { + Person() { + this = "Ronil" or + this = "Dina" or + this = "Ravi" or + this = "Bruce" or + this = "Jo" or + this = "Aida" or + this = "Esme" or + this = "Charlie" or + this = "Fred" or + this = "Meera" or + this = "Maya" or + this = "Chad" or + this = "Tiana" or + this = "Laura" or + this = "George" or + this = "Will" or + this = "Mary" or + this = "Almira" or + this = "Susannah" or + this = "Rhoda" or + this = "Cynthia" or + this = "Eunice" or + this = "Olive" or + this = "Virginia" or + this = "Angeline" or + this = "Helen" or + this = "Cornelia" or + this = "Harriet" or + this = "Mahala" or + this = "Abby" or + this = "Margaret" or + this = "Deb" or + this = "Minerva" or + this = "Severus" or + this = "Lavina" or + this = "Adeline" or + this = "Cath" or + this = "Elisa" or + this = "Lucretia" or + this = "Anne" or + this = "Eleanor" or + this = "Joanna" or + this = "Adam" or + this = "Agnes" or + this = "Rosanna" or + this = "Clara" or + this = "Melissa" or + this = "Amy" or + this = "Isabel" or + this = "Jemima" or + this = "Cordelia" or + this = "Melinda" or + this = "Delila" or + this = "Jeremiah" or + this = "Elijah" or + this = "Hester" or + this = "Walter" or + this = "Oliver" or + this = "Hugh" or + this = "Aaron" or + this = "Reuben" or + this = "Eli" or + this = "Amos" or + this = "Augustus" or + this = "Theodore" or + this = "Ira" or + this = "Timothy" or + this = "Cyrus" or + this = "Horace" or + this = "Simon" or + this = "Asa" or + this = "Frank" or + this = "Nelson" or + this = "Leonard" or + this = "Harrison" or + this = "Anthony" or + this = "Louis" or + this = "Milton" or + this = "Noah" or + this = "Cornelius" or + this = "Abdul" or + this = "Warren" or + this = "Harvey" or + this = "Dennis" or + this = "Wesley" or + this = "Sylvester" or + this = "Gilbert" or + this = "Sullivan" or + this = "Edmund" or + this = "Wilson" or + this = "Perry" or + this = "Matthew" or + this = "Simba" or + this = "Nala" or + this = "Rafiki" or + this = "Shenzi" or + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Edwin" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" or + this = "Stephen" + } + + /** Gets the hair color of the person. If the person is bald, there is no result. */ + string getHairColor() { + this = "Ronil" and result = "black" + or + this = "Dina" and result = "black" + or + this = "Ravi" and result = "black" + or + this = "Bruce" and result = "brown" + or + this = "Jo" and result = "red" + or + this = "Aida" and result = "blond" + or + this = "Esme" and result = "blond" + or + this = "Fred" and result = "gray" + or + this = "Meera" and result = "brown" + or + this = "Maya" and result = "brown" + or + this = "Chad" and result = "brown" + or + this = "Tiana" and result = "black" + or + this = "Laura" and result = "blond" + or + this = "George" and result = "blond" + or + this = "Will" and result = "blond" + or + this = "Mary" and result = "blond" + or + this = "Almira" and result = "black" + or + this = "Susannah" and result = "blond" + or + this = "Rhoda" and result = "blond" + or + this = "Cynthia" and result = "gray" + or + this = "Eunice" and result = "white" + or + this = "Olive" and result = "brown" + or + this = "Virginia" and result = "brown" + or + this = "Angeline" and result = "red" + or + this = "Helen" and result = "white" + or + this = "Cornelia" and result = "gray" + or + this = "Harriet" and result = "white" + or + this = "Mahala" and result = "black" + or + this = "Abby" and result = "red" + or + this = "Margaret" and result = "brown" + or + this = "Deb" and result = "brown" + or + this = "Minerva" and result = "brown" + or + this = "Severus" and result = "black" + or + this = "Lavina" and result = "brown" + or + this = "Adeline" and result = "brown" + or + this = "Cath" and result = "brown" + or + this = "Elisa" and result = "brown" + or + this = "Lucretia" and result = "gray" + or + this = "Anne" and result = "black" + or + this = "Eleanor" and result = "brown" + or + this = "Joanna" and result = "brown" + or + this = "Adam" and result = "black" + or + this = "Agnes" and result = "black" + or + this = "Rosanna" and result = "gray" + or + this = "Clara" and result = "blond" + or + this = "Melissa" and result = "brown" + or + this = "Amy" and result = "brown" + or + this = "Isabel" and result = "black" + or + this = "Jemima" and result = "red" + or + this = "Cordelia" and result = "red" + or + this = "Melinda" and result = "gray" + or + this = "Delila" and result = "white" + or + this = "Jeremiah" and result = "gray" + or + this = "Hester" and result = "black" + or + this = "Walter" and result = "black" + or + this = "Aaron" and result = "gray" + or + this = "Reuben" and result = "gray" + or + this = "Eli" and result = "gray" + or + this = "Amos" and result = "white" + or + this = "Augustus" and result = "white" + or + this = "Theodore" and result = "white" + or + this = "Timothy" and result = "brown" + or + this = "Cyrus" and result = "brown" + or + this = "Horace" and result = "brown" + or + this = "Simon" and result = "brown" + or + this = "Asa" and result = "brown" + or + this = "Frank" and result = "brown" + or + this = "Nelson" and result = "black" + or + this = "Leonard" and result = "black" + or + this = "Harrison" and result = "black" + or + this = "Anthony" and result = "black" + or + this = "Louis" and result = "black" + or + this = "Milton" and result = "blond" + or + this = "Noah" and result = "blond" + or + this = "Cornelius" and result = "red" + or + this = "Abdul" and result = "brown" + or + this = "Warren" and result = "red" + or + this = "Harvey" and result = "blond" + or + this = "Dennis" and result = "blond" + or + this = "Wesley" and result = "brown" + or + this = "Sylvester" and result = "brown" + or + this = "Gilbert" and result = "brown" + or + this = "Sullivan" and result = "brown" + or + this = "Edmund" and result = "brown" + or + this = "Wilson" and result = "blond" + or + this = "Perry" and result = "black" + or + this = "Simba" and result = "brown" + or + this = "Nala" and result = "brown" + or + this = "Rafiki" and result = "red" + or + this = "Shenzi" and result = "gray" + or + this = "Ernest" and result = "blond" + or + this = "Gertrude" and result = "brown" + or + this = "Oscar" and result = "blond" + or + this = "Lilian" and result = "brown" + or + this = "Raymond" and result = "brown" + or + this = "Elgar" and result = "brown" + or + this = "Elmer" and result = "brown" + or + this = "Herbert" and result = "brown" + or + this = "Maude" and result = "brown" + or + this = "Mae" and result = "brown" + or + this = "Otto" and result = "black" + or + this = "Edwin" and result = "black" + or + this = "Ophelia" and result = "brown" + or + this = "Parsley" and result = "brown" + or + this = "Sage" and result = "brown" + or + this = "Rosemary" and result = "brown" + or + this = "Thyme" and result = "brown" + or + this = "Garfunkel" and result = "brown" + or + this = "King Basil" and result = "brown" + or + this = "Stephen" and result = "black" + or + this = "Stephen" and result = "gray" + } + + /** Gets the age of the person (in years). If the person is deceased, there is no result. */ + int getAge() { + this = "Ronil" and result = 21 + or + this = "Dina" and result = 53 + or + this = "Ravi" and result = 16 + or + this = "Bruce" and result = 35 + or + this = "Jo" and result = 47 + or + this = "Aida" and result = 26 + or + this = "Esme" and result = 25 + or + this = "Charlie" and result = 31 + or + this = "Fred" and result = 68 + or + this = "Meera" and result = 62 + or + this = "Maya" and result = 29 + or + this = "Chad" and result = 49 + or + this = "Tiana" and result = 18 + or + this = "Laura" and result = 2 + or + this = "George" and result = 3 + or + this = "Will" and result = 41 + or + this = "Mary" and result = 51 + or + this = "Almira" and result = 1 + or + this = "Susannah" and result = 97 + or + this = "Rhoda" and result = 39 + or + this = "Cynthia" and result = 89 + or + this = "Eunice" and result = 83 + or + this = "Olive" and result = 25 + or + this = "Virginia" and result = 52 + or + this = "Angeline" and result = 22 + or + this = "Helen" and result = 79 + or + this = "Cornelia" and result = 59 + or + this = "Harriet" and result = 57 + or + this = "Mahala" and result = 61 + or + this = "Abby" and result = 24 + or + this = "Margaret" and result = 59 + or + this = "Deb" and result = 31 + or + this = "Minerva" and result = 72 + or + this = "Severus" and result = 61 + or + this = "Lavina" and result = 33 + or + this = "Adeline" and result = 17 + or + this = "Cath" and result = 22 + or + this = "Elisa" and result = 9 + or + this = "Lucretia" and result = 56 + or + this = "Anne" and result = 11 + or + this = "Eleanor" and result = 80 + or + this = "Joanna" and result = 43 + or + this = "Adam" and result = 37 + or + this = "Agnes" and result = 47 + or + this = "Rosanna" and result = 61 + or + this = "Clara" and result = 31 + or + this = "Melissa" and result = 37 + or + this = "Amy" and result = 12 + or + this = "Isabel" and result = 6 + or + this = "Jemima" and result = 16 + or + this = "Cordelia" and result = 21 + or + this = "Melinda" and result = 55 + or + this = "Delila" and result = 66 + or + this = "Jeremiah" and result = 54 + or + this = "Elijah" and result = 42 + or + this = "Hester" and result = 68 + or + this = "Walter" and result = 66 + or + this = "Oliver" and result = 33 + or + this = "Hugh" and result = 51 + or + this = "Aaron" and result = 49 + or + this = "Reuben" and result = 58 + or + this = "Eli" and result = 70 + or + this = "Amos" and result = 65 + or + this = "Augustus" and result = 56 + or + this = "Theodore" and result = 69 + or + this = "Ira" and result = 1 + or + this = "Timothy" and result = 54 + or + this = "Cyrus" and result = 78 + or + this = "Horace" and result = 34 + or + this = "Simon" and result = 23 + or + this = "Asa" and result = 28 + or + this = "Frank" and result = 59 + or + this = "Nelson" and result = 38 + or + this = "Leonard" and result = 58 + or + this = "Harrison" and result = 7 + or + this = "Anthony" and result = 2 + or + this = "Louis" and result = 34 + or + this = "Milton" and result = 36 + or + this = "Noah" and result = 48 + or + this = "Cornelius" and result = 41 + or + this = "Abdul" and result = 67 + or + this = "Warren" and result = 47 + or + this = "Harvey" and result = 31 + or + this = "Dennis" and result = 39 + or + this = "Wesley" and result = 13 + or + this = "Sylvester" and result = 19 + or + this = "Gilbert" and result = 16 + or + this = "Sullivan" and result = 17 + or + this = "Edmund" and result = 29 + or + this = "Wilson" and result = 27 + or + this = "Perry" and result = 31 + or + this = "Matthew" and result = 55 + or + this = "Simba" and result = 8 + or + this = "Nala" and result = 7 + or + this = "Rafiki" and result = 76 + or + this = "Shenzi" and result = 67 + } + + /** Gets the height of the person (in cm). If the person is deceased, there is no result. */ + float getHeight() { + this = "Ronil" and result = 183.0 + or + this = "Dina" and result = 155.1 + or + this = "Ravi" and result = 175.2 + or + this = "Bruce" and result = 191.3 + or + this = "Jo" and result = 163.4 + or + this = "Aida" and result = 182.6 + or + this = "Esme" and result = 176.9 + or + this = "Charlie" and result = 189.7 + or + this = "Fred" and result = 179.4 + or + this = "Meera" and result = 160.1 + or + this = "Maya" and result = 153.0 + or + this = "Chad" and result = 168.5 + or + this = "Tiana" and result = 149.7 + or + this = "Laura" and result = 87.5 + or + this = "George" and result = 96.4 + or + this = "Will" and result = 167.1 + or + this = "Mary" and result = 159.8 + or + this = "Almira" and result = 62.1 + or + this = "Susannah" and result = 145.8 + or + this = "Rhoda" and result = 180.1 + or + this = "Cynthia" and result = 161.8 + or + this = "Eunice" and result = 153.2 + or + this = "Olive" and result = 179.9 + or + this = "Virginia" and result = 165.1 + or + this = "Angeline" and result = 172.3 + or + this = "Helen" and result = 163.1 + or + this = "Cornelia" and result = 160.8 + or + this = "Harriet" and result = 163.2 + or + this = "Mahala" and result = 157.7 + or + this = "Abby" and result = 174.5 + or + this = "Margaret" and result = 165.6 + or + this = "Deb" and result = 171.6 + or + this = "Minerva" and result = 168.7 + or + this = "Severus" and result = 188.8 + or + this = "Lavina" and result = 155.1 + or + this = "Adeline" and result = 165.5 + or + this = "Cath" and result = 147.8 + or + this = "Elisa" and result = 129.4 + or + this = "Lucretia" and result = 153.6 + or + this = "Anne" and result = 140.4 + or + this = "Eleanor" and result = 151.1 + or + this = "Joanna" and result = 167.2 + or + this = "Adam" and result = 155.5 + or + this = "Agnes" and result = 156.8 + or + this = "Rosanna" and result = 162.4 + or + this = "Clara" and result = 158.6 + or + this = "Melissa" and result = 182.3 + or + this = "Amy" and result = 147.1 + or + this = "Isabel" and result = 121.4 + or + this = "Jemima" and result = 149.8 + or + this = "Cordelia" and result = 151.7 + or + this = "Melinda" and result = 154.4 + or + this = "Delila" and result = 163.4 + or + this = "Jeremiah" and result = 167.5 + or + this = "Elijah" and result = 184.5 + or + this = "Hester" and result = 152.7 + or + this = "Walter" and result = 159.6 + or + this = "Oliver" and result = 192.4 + or + this = "Hugh" and result = 173.1 + or + this = "Aaron" and result = 176.6 + or + this = "Reuben" and result = 169.9 + or + this = "Eli" and result = 180.4 + or + this = "Amos" and result = 167.4 + or + this = "Augustus" and result = 156.5 + or + this = "Theodore" and result = 176.6 + or + this = "Ira" and result = 54.1 + or + this = "Timothy" and result = 172.2 + or + this = "Cyrus" and result = 157.9 + or + this = "Horace" and result = 169.3 + or + this = "Simon" and result = 157.1 + or + this = "Asa" and result = 149.4 + or + this = "Frank" and result = 167.2 + or + this = "Nelson" and result = 173.0 + or + this = "Leonard" and result = 172.0 + or + this = "Harrison" and result = 126.0 + or + this = "Anthony" and result = 98.4 + or + this = "Louis" and result = 186.8 + or + this = "Milton" and result = 157.8 + or + this = "Noah" and result = 190.5 + or + this = "Cornelius" and result = 183.1 + or + this = "Abdul" and result = 182.0 + or + this = "Warren" and result = 175.0 + or + this = "Harvey" and result = 169.3 + or + this = "Dennis" and result = 160.4 + or + this = "Wesley" and result = 139.8 + or + this = "Sylvester" and result = 188.2 + or + this = "Gilbert" and result = 177.6 + or + this = "Sullivan" and result = 168.3 + or + this = "Edmund" and result = 159.2 + or + this = "Wilson" and result = 167.6 + or + this = "Perry" and result = 189.1 + or + this = "Matthew" and result = 167.2 + or + this = "Simba" and result = 140.1 + or + this = "Nala" and result = 138.0 + or + this = "Rafiki" and result = 139.3 + or + this = "Shenzi" and result = 171.1 + } + + /** Gets the location of the person's home ("north", "south", "east", or "west"). If the person is deceased, there is no result. */ + string getLocation() { + this = "Ronil" and result = "north" + or + this = "Dina" and result = "north" + or + this = "Ravi" and result = "north" + or + this = "Bruce" and result = "south" + or + this = "Jo" and result = "west" + or + this = "Aida" and result = "east" + or + this = "Esme" and result = "east" + or + this = "Charlie" and result = "south" + or + this = "Fred" and result = "west" + or + this = "Meera" and result = "south" + or + this = "Maya" and result = "south" + or + this = "Chad" and result = "south" + or + this = "Tiana" and result = "west" + or + this = "Laura" and result = "south" + or + this = "George" and result = "south" + or + this = "Will" and result = "south" + or + this = "Mary" and result = "south" + or + this = "Almira" and result = "south" + or + this = "Susannah" and result = "north" + or + this = "Rhoda" and result = "north" + or + this = "Cynthia" and result = "north" + or + this = "Eunice" and result = "north" + or + this = "Olive" and result = "west" + or + this = "Virginia" and result = "west" + or + this = "Angeline" and result = "west" + or + this = "Helen" and result = "west" + or + this = "Cornelia" and result = "east" + or + this = "Harriet" and result = "east" + or + this = "Mahala" and result = "east" + or + this = "Abby" and result = "east" + or + this = "Margaret" and result = "east" + or + this = "Deb" and result = "east" + or + this = "Minerva" and result = "south" + or + this = "Severus" and result = "north" + or + this = "Lavina" and result = "east" + or + this = "Adeline" and result = "west" + or + this = "Cath" and result = "east" + or + this = "Elisa" and result = "east" + or + this = "Lucretia" and result = "north" + or + this = "Anne" and result = "north" + or + this = "Eleanor" and result = "south" + or + this = "Joanna" and result = "south" + or + this = "Adam" and result = "east" + or + this = "Agnes" and result = "east" + or + this = "Rosanna" and result = "east" + or + this = "Clara" and result = "east" + or + this = "Melissa" and result = "west" + or + this = "Amy" and result = "west" + or + this = "Isabel" and result = "west" + or + this = "Jemima" and result = "west" + or + this = "Cordelia" and result = "west" + or + this = "Melinda" and result = "west" + or + this = "Delila" and result = "south" + or + this = "Jeremiah" and result = "north" + or + this = "Elijah" and result = "north" + or + this = "Hester" and result = "east" + or + this = "Walter" and result = "east" + or + this = "Oliver" and result = "east" + or + this = "Hugh" and result = "south" + or + this = "Aaron" and result = "south" + or + this = "Reuben" and result = "west" + or + this = "Eli" and result = "west" + or + this = "Amos" and result = "east" + or + this = "Augustus" and result = "south" + or + this = "Theodore" and result = "west" + or + this = "Ira" and result = "south" + or + this = "Timothy" and result = "north" + or + this = "Cyrus" and result = "north" + or + this = "Horace" and result = "east" + or + this = "Simon" and result = "east" + or + this = "Asa" and result = "east" + or + this = "Frank" and result = "west" + or + this = "Nelson" and result = "west" + or + this = "Leonard" and result = "west" + or + this = "Harrison" and result = "north" + or + this = "Anthony" and result = "north" + or + this = "Louis" and result = "north" + or + this = "Milton" and result = "south" + or + this = "Noah" and result = "south" + or + this = "Cornelius" and result = "east" + or + this = "Abdul" and result = "east" + or + this = "Warren" and result = "west" + or + this = "Harvey" and result = "west" + or + this = "Dennis" and result = "west" + or + this = "Wesley" and result = "west" + or + this = "Sylvester" and result = "south" + or + this = "Gilbert" and result = "east" + or + this = "Sullivan" and result = "east" + or + this = "Edmund" and result = "north" + or + this = "Wilson" and result = "north" + or + this = "Perry" and result = "west" + or + this = "Matthew" and result = "east" + or + this = "Simba" and result = "south" + or + this = "Nala" and result = "south" + or + this = "Rafiki" and result = "north" + or + this = "Shenzi" and result = "west" + } + + /** Holds if the person is deceased. */ + predicate isDeceased() { + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Edwin" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" + } + + /** Gets a parent of the person (alive or deceased). */ + Person getAParent() { + this = "Stephen" and result = "Edmund" + or + this = "Edmund" and result = "Augustus" + or + this = "Augustus" and result = "Stephen" + or + this = "Abby" and result = "Cornelia" + or + this = "Abby" and result = "Amos" + or + this = "Abdul" and result = "Susannah" + or + this = "Adam" and result = "Amos" + or + this = "Adeline" and result = "Melinda" + or + this = "Adeline" and result = "Frank" + or + this = "Agnes" and result = "Abdul" + or + this = "Aida" and result = "Agnes" + or + this = "Almira" and result = "Sylvester" + or + this = "Amos" and result = "Eunice" + or + this = "Amy" and result = "Noah" + or + this = "Amy" and result = "Chad" + or + this = "Angeline" and result = "Reuben" + or + this = "Angeline" and result = "Lucretia" + or + this = "Anne" and result = "Rhoda" + or + this = "Anne" and result = "Louis" + or + this = "Anthony" and result = "Lavina" + or + this = "Anthony" and result = "Asa" + or + this = "Asa" and result = "Cornelia" + or + this = "Cath" and result = "Harriet" + or + this = "Charlie" and result = "Matthew" + or + this = "Clara" and result = "Ernest" + or + this = "Cornelia" and result = "Cynthia" + or + this = "Cornelius" and result = "Eli" + or + this = "Deb" and result = "Margaret" + or + this = "Dennis" and result = "Fred" + or + this = "Eli" and result = "Susannah" + or + this = "Elijah" and result = "Delila" + or + this = "Elisa" and result = "Deb" + or + this = "Elisa" and result = "Horace" + or + this = "Esme" and result = "Margaret" + or + this = "Frank" and result = "Eleanor" + or + this = "Frank" and result = "Cyrus" + or + this = "George" and result = "Maya" + or + this = "George" and result = "Wilson" + or + this = "Gilbert" and result = "Cornelius" + or + this = "Harriet" and result = "Cynthia" + or + this = "Harrison" and result = "Louis" + or + this = "Harvey" and result = "Fred" + or + this = "Helen" and result = "Susannah" + or + this = "Hester" and result = "Edwin" + or + this = "Hugh" and result = "Cyrus" + or + this = "Hugh" and result = "Helen" + or + this = "Ira" and result = "Maya" + or + this = "Ira" and result = "Wilson" + or + this = "Isabel" and result = "Perry" + or + this = "Isabel" and result = "Harvey" + or + this = "Jemima" and result = "Melinda" + or + this = "Jemima" and result = "Frank" + or + this = "Ernest" and result = "Lilian" + or + this = "Ernest" and result = "Oscar" + or + this = "Gertrude" and result = "Ophelia" + or + this = "Gertrude" and result = "Raymond" + or + this = "Lilian" and result = "Elgar" + or + this = "Lilian" and result = "Mae" + or + this = "Raymond" and result = "Elgar" + or + this = "Raymond" and result = "Mae" + or + this = "Elmer" and result = "Ophelia" + or + this = "Elmer" and result = "Raymond" + or + this = "Herbert" and result = "Ophelia" + or + this = "Herbert" and result = "Raymond" + or + this = "Maude" and result = "Ophelia" + or + this = "Maude" and result = "Raymond" + or + this = "Otto" and result = "Elgar" + or + this = "Otto" and result = "Mae" + or + this = "Edwin" and result = "Otto" + or + this = "Parsley" and result = "Simon" + or + this = "Parsley" and result = "Garfunkel" + or + this = "Sage" and result = "Simon" + or + this = "Sage" and result = "Garfunkel" + or + this = "Rosemary" and result = "Simon" + or + this = "Rosemary" and result = "Garfunkel" + or + this = "Thyme" and result = "Simon" + or + this = "Thyme" and result = "Garfunkel" + or + this = "King Basil" and result = "Ophelia" + or + this = "King Basil" and result = "Raymond" + or + this = "Jo" and result = "Theodore" + or + this = "Joanna" and result = "Shenzi" + or + this = "Laura" and result = "Maya" + or + this = "Laura" and result = "Wilson" + or + this = "Lavina" and result = "Mahala" + or + this = "Lavina" and result = "Walter" + or + this = "Leonard" and result = "Cyrus" + or + this = "Leonard" and result = "Helen" + or + this = "Lucretia" and result = "Eleanor" + or + this = "Lucretia" and result = "Cyrus" + or + this = "Mahala" and result = "Eunice" + or + this = "Margaret" and result = "Cynthia" + or + this = "Matthew" and result = "Cyrus" + or + this = "Matthew" and result = "Helen" + or + this = "Maya" and result = "Meera" + or + this = "Melinda" and result = "Rafiki" + or + this = "Melissa" and result = "Mahala" + or + this = "Melissa" and result = "Walter" + or + this = "Nala" and result = "Bruce" + or + this = "Nelson" and result = "Mahala" + or + this = "Nelson" and result = "Walter" + or + this = "Noah" and result = "Eli" + or + this = "Olive" and result = "Reuben" + or + this = "Olive" and result = "Lucretia" + or + this = "Oliver" and result = "Matthew" + or + this = "Perry" and result = "Leonard" + or + this = "Ravi" and result = "Dina" + or + this = "Simba" and result = "Will" + or + this = "Simon" and result = "Margaret" + or + this = "Sullivan" and result = "Cornelius" + or + this = "Sylvester" and result = "Timothy" + or + this = "Theodore" and result = "Susannah" + or + this = "Tiana" and result = "Jo" + or + this = "Virginia" and result = "Helen" + or + this = "Warren" and result = "Shenzi" + or + this = "Wesley" and result = "Warren" + or + this = "Wesley" and result = "Jo" + or + this = "Will" and result = "Eli" + } + + /** Holds if the person is allowed in the region. Initially, all villagers are allowed in every region. */ + predicate isAllowedIn(string region) { + region = "north" or + region = "south" or + region = "east" or + region = "west" + } +} + +/** Returns a parent of the person. */ +Person parentOf(Person p) { result = p.getAParent() } diff --git a/java/ql/lib/tutorial.qll b/java/ql/lib/tutorial.qll new file mode 100644 index 00000000000..8cb1797a532 --- /dev/null +++ b/java/ql/lib/tutorial.qll @@ -0,0 +1,1207 @@ +/** + * This library is used in the QL detective tutorials. + * + * Note: Data is usually stored in a separate database and the QL libraries only contain predicates, + * but for this tutorial both the data and the predicates are stored in the library. + */ +class Person extends string { + Person() { + this = "Ronil" or + this = "Dina" or + this = "Ravi" or + this = "Bruce" or + this = "Jo" or + this = "Aida" or + this = "Esme" or + this = "Charlie" or + this = "Fred" or + this = "Meera" or + this = "Maya" or + this = "Chad" or + this = "Tiana" or + this = "Laura" or + this = "George" or + this = "Will" or + this = "Mary" or + this = "Almira" or + this = "Susannah" or + this = "Rhoda" or + this = "Cynthia" or + this = "Eunice" or + this = "Olive" or + this = "Virginia" or + this = "Angeline" or + this = "Helen" or + this = "Cornelia" or + this = "Harriet" or + this = "Mahala" or + this = "Abby" or + this = "Margaret" or + this = "Deb" or + this = "Minerva" or + this = "Severus" or + this = "Lavina" or + this = "Adeline" or + this = "Cath" or + this = "Elisa" or + this = "Lucretia" or + this = "Anne" or + this = "Eleanor" or + this = "Joanna" or + this = "Adam" or + this = "Agnes" or + this = "Rosanna" or + this = "Clara" or + this = "Melissa" or + this = "Amy" or + this = "Isabel" or + this = "Jemima" or + this = "Cordelia" or + this = "Melinda" or + this = "Delila" or + this = "Jeremiah" or + this = "Elijah" or + this = "Hester" or + this = "Walter" or + this = "Oliver" or + this = "Hugh" or + this = "Aaron" or + this = "Reuben" or + this = "Eli" or + this = "Amos" or + this = "Augustus" or + this = "Theodore" or + this = "Ira" or + this = "Timothy" or + this = "Cyrus" or + this = "Horace" or + this = "Simon" or + this = "Asa" or + this = "Frank" or + this = "Nelson" or + this = "Leonard" or + this = "Harrison" or + this = "Anthony" or + this = "Louis" or + this = "Milton" or + this = "Noah" or + this = "Cornelius" or + this = "Abdul" or + this = "Warren" or + this = "Harvey" or + this = "Dennis" or + this = "Wesley" or + this = "Sylvester" or + this = "Gilbert" or + this = "Sullivan" or + this = "Edmund" or + this = "Wilson" or + this = "Perry" or + this = "Matthew" or + this = "Simba" or + this = "Nala" or + this = "Rafiki" or + this = "Shenzi" or + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Edwin" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" or + this = "Stephen" + } + + /** Gets the hair color of the person. If the person is bald, there is no result. */ + string getHairColor() { + this = "Ronil" and result = "black" + or + this = "Dina" and result = "black" + or + this = "Ravi" and result = "black" + or + this = "Bruce" and result = "brown" + or + this = "Jo" and result = "red" + or + this = "Aida" and result = "blond" + or + this = "Esme" and result = "blond" + or + this = "Fred" and result = "gray" + or + this = "Meera" and result = "brown" + or + this = "Maya" and result = "brown" + or + this = "Chad" and result = "brown" + or + this = "Tiana" and result = "black" + or + this = "Laura" and result = "blond" + or + this = "George" and result = "blond" + or + this = "Will" and result = "blond" + or + this = "Mary" and result = "blond" + or + this = "Almira" and result = "black" + or + this = "Susannah" and result = "blond" + or + this = "Rhoda" and result = "blond" + or + this = "Cynthia" and result = "gray" + or + this = "Eunice" and result = "white" + or + this = "Olive" and result = "brown" + or + this = "Virginia" and result = "brown" + or + this = "Angeline" and result = "red" + or + this = "Helen" and result = "white" + or + this = "Cornelia" and result = "gray" + or + this = "Harriet" and result = "white" + or + this = "Mahala" and result = "black" + or + this = "Abby" and result = "red" + or + this = "Margaret" and result = "brown" + or + this = "Deb" and result = "brown" + or + this = "Minerva" and result = "brown" + or + this = "Severus" and result = "black" + or + this = "Lavina" and result = "brown" + or + this = "Adeline" and result = "brown" + or + this = "Cath" and result = "brown" + or + this = "Elisa" and result = "brown" + or + this = "Lucretia" and result = "gray" + or + this = "Anne" and result = "black" + or + this = "Eleanor" and result = "brown" + or + this = "Joanna" and result = "brown" + or + this = "Adam" and result = "black" + or + this = "Agnes" and result = "black" + or + this = "Rosanna" and result = "gray" + or + this = "Clara" and result = "blond" + or + this = "Melissa" and result = "brown" + or + this = "Amy" and result = "brown" + or + this = "Isabel" and result = "black" + or + this = "Jemima" and result = "red" + or + this = "Cordelia" and result = "red" + or + this = "Melinda" and result = "gray" + or + this = "Delila" and result = "white" + or + this = "Jeremiah" and result = "gray" + or + this = "Hester" and result = "black" + or + this = "Walter" and result = "black" + or + this = "Aaron" and result = "gray" + or + this = "Reuben" and result = "gray" + or + this = "Eli" and result = "gray" + or + this = "Amos" and result = "white" + or + this = "Augustus" and result = "white" + or + this = "Theodore" and result = "white" + or + this = "Timothy" and result = "brown" + or + this = "Cyrus" and result = "brown" + or + this = "Horace" and result = "brown" + or + this = "Simon" and result = "brown" + or + this = "Asa" and result = "brown" + or + this = "Frank" and result = "brown" + or + this = "Nelson" and result = "black" + or + this = "Leonard" and result = "black" + or + this = "Harrison" and result = "black" + or + this = "Anthony" and result = "black" + or + this = "Louis" and result = "black" + or + this = "Milton" and result = "blond" + or + this = "Noah" and result = "blond" + or + this = "Cornelius" and result = "red" + or + this = "Abdul" and result = "brown" + or + this = "Warren" and result = "red" + or + this = "Harvey" and result = "blond" + or + this = "Dennis" and result = "blond" + or + this = "Wesley" and result = "brown" + or + this = "Sylvester" and result = "brown" + or + this = "Gilbert" and result = "brown" + or + this = "Sullivan" and result = "brown" + or + this = "Edmund" and result = "brown" + or + this = "Wilson" and result = "blond" + or + this = "Perry" and result = "black" + or + this = "Simba" and result = "brown" + or + this = "Nala" and result = "brown" + or + this = "Rafiki" and result = "red" + or + this = "Shenzi" and result = "gray" + or + this = "Ernest" and result = "blond" + or + this = "Gertrude" and result = "brown" + or + this = "Oscar" and result = "blond" + or + this = "Lilian" and result = "brown" + or + this = "Raymond" and result = "brown" + or + this = "Elgar" and result = "brown" + or + this = "Elmer" and result = "brown" + or + this = "Herbert" and result = "brown" + or + this = "Maude" and result = "brown" + or + this = "Mae" and result = "brown" + or + this = "Otto" and result = "black" + or + this = "Edwin" and result = "black" + or + this = "Ophelia" and result = "brown" + or + this = "Parsley" and result = "brown" + or + this = "Sage" and result = "brown" + or + this = "Rosemary" and result = "brown" + or + this = "Thyme" and result = "brown" + or + this = "Garfunkel" and result = "brown" + or + this = "King Basil" and result = "brown" + or + this = "Stephen" and result = "black" + or + this = "Stephen" and result = "gray" + } + + /** Gets the age of the person (in years). If the person is deceased, there is no result. */ + int getAge() { + this = "Ronil" and result = 21 + or + this = "Dina" and result = 53 + or + this = "Ravi" and result = 16 + or + this = "Bruce" and result = 35 + or + this = "Jo" and result = 47 + or + this = "Aida" and result = 26 + or + this = "Esme" and result = 25 + or + this = "Charlie" and result = 31 + or + this = "Fred" and result = 68 + or + this = "Meera" and result = 62 + or + this = "Maya" and result = 29 + or + this = "Chad" and result = 49 + or + this = "Tiana" and result = 18 + or + this = "Laura" and result = 2 + or + this = "George" and result = 3 + or + this = "Will" and result = 41 + or + this = "Mary" and result = 51 + or + this = "Almira" and result = 1 + or + this = "Susannah" and result = 97 + or + this = "Rhoda" and result = 39 + or + this = "Cynthia" and result = 89 + or + this = "Eunice" and result = 83 + or + this = "Olive" and result = 25 + or + this = "Virginia" and result = 52 + or + this = "Angeline" and result = 22 + or + this = "Helen" and result = 79 + or + this = "Cornelia" and result = 59 + or + this = "Harriet" and result = 57 + or + this = "Mahala" and result = 61 + or + this = "Abby" and result = 24 + or + this = "Margaret" and result = 59 + or + this = "Deb" and result = 31 + or + this = "Minerva" and result = 72 + or + this = "Severus" and result = 61 + or + this = "Lavina" and result = 33 + or + this = "Adeline" and result = 17 + or + this = "Cath" and result = 22 + or + this = "Elisa" and result = 9 + or + this = "Lucretia" and result = 56 + or + this = "Anne" and result = 11 + or + this = "Eleanor" and result = 80 + or + this = "Joanna" and result = 43 + or + this = "Adam" and result = 37 + or + this = "Agnes" and result = 47 + or + this = "Rosanna" and result = 61 + or + this = "Clara" and result = 31 + or + this = "Melissa" and result = 37 + or + this = "Amy" and result = 12 + or + this = "Isabel" and result = 6 + or + this = "Jemima" and result = 16 + or + this = "Cordelia" and result = 21 + or + this = "Melinda" and result = 55 + or + this = "Delila" and result = 66 + or + this = "Jeremiah" and result = 54 + or + this = "Elijah" and result = 42 + or + this = "Hester" and result = 68 + or + this = "Walter" and result = 66 + or + this = "Oliver" and result = 33 + or + this = "Hugh" and result = 51 + or + this = "Aaron" and result = 49 + or + this = "Reuben" and result = 58 + or + this = "Eli" and result = 70 + or + this = "Amos" and result = 65 + or + this = "Augustus" and result = 56 + or + this = "Theodore" and result = 69 + or + this = "Ira" and result = 1 + or + this = "Timothy" and result = 54 + or + this = "Cyrus" and result = 78 + or + this = "Horace" and result = 34 + or + this = "Simon" and result = 23 + or + this = "Asa" and result = 28 + or + this = "Frank" and result = 59 + or + this = "Nelson" and result = 38 + or + this = "Leonard" and result = 58 + or + this = "Harrison" and result = 7 + or + this = "Anthony" and result = 2 + or + this = "Louis" and result = 34 + or + this = "Milton" and result = 36 + or + this = "Noah" and result = 48 + or + this = "Cornelius" and result = 41 + or + this = "Abdul" and result = 67 + or + this = "Warren" and result = 47 + or + this = "Harvey" and result = 31 + or + this = "Dennis" and result = 39 + or + this = "Wesley" and result = 13 + or + this = "Sylvester" and result = 19 + or + this = "Gilbert" and result = 16 + or + this = "Sullivan" and result = 17 + or + this = "Edmund" and result = 29 + or + this = "Wilson" and result = 27 + or + this = "Perry" and result = 31 + or + this = "Matthew" and result = 55 + or + this = "Simba" and result = 8 + or + this = "Nala" and result = 7 + or + this = "Rafiki" and result = 76 + or + this = "Shenzi" and result = 67 + } + + /** Gets the height of the person (in cm). If the person is deceased, there is no result. */ + float getHeight() { + this = "Ronil" and result = 183.0 + or + this = "Dina" and result = 155.1 + or + this = "Ravi" and result = 175.2 + or + this = "Bruce" and result = 191.3 + or + this = "Jo" and result = 163.4 + or + this = "Aida" and result = 182.6 + or + this = "Esme" and result = 176.9 + or + this = "Charlie" and result = 189.7 + or + this = "Fred" and result = 179.4 + or + this = "Meera" and result = 160.1 + or + this = "Maya" and result = 153.0 + or + this = "Chad" and result = 168.5 + or + this = "Tiana" and result = 149.7 + or + this = "Laura" and result = 87.5 + or + this = "George" and result = 96.4 + or + this = "Will" and result = 167.1 + or + this = "Mary" and result = 159.8 + or + this = "Almira" and result = 62.1 + or + this = "Susannah" and result = 145.8 + or + this = "Rhoda" and result = 180.1 + or + this = "Cynthia" and result = 161.8 + or + this = "Eunice" and result = 153.2 + or + this = "Olive" and result = 179.9 + or + this = "Virginia" and result = 165.1 + or + this = "Angeline" and result = 172.3 + or + this = "Helen" and result = 163.1 + or + this = "Cornelia" and result = 160.8 + or + this = "Harriet" and result = 163.2 + or + this = "Mahala" and result = 157.7 + or + this = "Abby" and result = 174.5 + or + this = "Margaret" and result = 165.6 + or + this = "Deb" and result = 171.6 + or + this = "Minerva" and result = 168.7 + or + this = "Severus" and result = 188.8 + or + this = "Lavina" and result = 155.1 + or + this = "Adeline" and result = 165.5 + or + this = "Cath" and result = 147.8 + or + this = "Elisa" and result = 129.4 + or + this = "Lucretia" and result = 153.6 + or + this = "Anne" and result = 140.4 + or + this = "Eleanor" and result = 151.1 + or + this = "Joanna" and result = 167.2 + or + this = "Adam" and result = 155.5 + or + this = "Agnes" and result = 156.8 + or + this = "Rosanna" and result = 162.4 + or + this = "Clara" and result = 158.6 + or + this = "Melissa" and result = 182.3 + or + this = "Amy" and result = 147.1 + or + this = "Isabel" and result = 121.4 + or + this = "Jemima" and result = 149.8 + or + this = "Cordelia" and result = 151.7 + or + this = "Melinda" and result = 154.4 + or + this = "Delila" and result = 163.4 + or + this = "Jeremiah" and result = 167.5 + or + this = "Elijah" and result = 184.5 + or + this = "Hester" and result = 152.7 + or + this = "Walter" and result = 159.6 + or + this = "Oliver" and result = 192.4 + or + this = "Hugh" and result = 173.1 + or + this = "Aaron" and result = 176.6 + or + this = "Reuben" and result = 169.9 + or + this = "Eli" and result = 180.4 + or + this = "Amos" and result = 167.4 + or + this = "Augustus" and result = 156.5 + or + this = "Theodore" and result = 176.6 + or + this = "Ira" and result = 54.1 + or + this = "Timothy" and result = 172.2 + or + this = "Cyrus" and result = 157.9 + or + this = "Horace" and result = 169.3 + or + this = "Simon" and result = 157.1 + or + this = "Asa" and result = 149.4 + or + this = "Frank" and result = 167.2 + or + this = "Nelson" and result = 173.0 + or + this = "Leonard" and result = 172.0 + or + this = "Harrison" and result = 126.0 + or + this = "Anthony" and result = 98.4 + or + this = "Louis" and result = 186.8 + or + this = "Milton" and result = 157.8 + or + this = "Noah" and result = 190.5 + or + this = "Cornelius" and result = 183.1 + or + this = "Abdul" and result = 182.0 + or + this = "Warren" and result = 175.0 + or + this = "Harvey" and result = 169.3 + or + this = "Dennis" and result = 160.4 + or + this = "Wesley" and result = 139.8 + or + this = "Sylvester" and result = 188.2 + or + this = "Gilbert" and result = 177.6 + or + this = "Sullivan" and result = 168.3 + or + this = "Edmund" and result = 159.2 + or + this = "Wilson" and result = 167.6 + or + this = "Perry" and result = 189.1 + or + this = "Matthew" and result = 167.2 + or + this = "Simba" and result = 140.1 + or + this = "Nala" and result = 138.0 + or + this = "Rafiki" and result = 139.3 + or + this = "Shenzi" and result = 171.1 + } + + /** Gets the location of the person's home ("north", "south", "east", or "west"). If the person is deceased, there is no result. */ + string getLocation() { + this = "Ronil" and result = "north" + or + this = "Dina" and result = "north" + or + this = "Ravi" and result = "north" + or + this = "Bruce" and result = "south" + or + this = "Jo" and result = "west" + or + this = "Aida" and result = "east" + or + this = "Esme" and result = "east" + or + this = "Charlie" and result = "south" + or + this = "Fred" and result = "west" + or + this = "Meera" and result = "south" + or + this = "Maya" and result = "south" + or + this = "Chad" and result = "south" + or + this = "Tiana" and result = "west" + or + this = "Laura" and result = "south" + or + this = "George" and result = "south" + or + this = "Will" and result = "south" + or + this = "Mary" and result = "south" + or + this = "Almira" and result = "south" + or + this = "Susannah" and result = "north" + or + this = "Rhoda" and result = "north" + or + this = "Cynthia" and result = "north" + or + this = "Eunice" and result = "north" + or + this = "Olive" and result = "west" + or + this = "Virginia" and result = "west" + or + this = "Angeline" and result = "west" + or + this = "Helen" and result = "west" + or + this = "Cornelia" and result = "east" + or + this = "Harriet" and result = "east" + or + this = "Mahala" and result = "east" + or + this = "Abby" and result = "east" + or + this = "Margaret" and result = "east" + or + this = "Deb" and result = "east" + or + this = "Minerva" and result = "south" + or + this = "Severus" and result = "north" + or + this = "Lavina" and result = "east" + or + this = "Adeline" and result = "west" + or + this = "Cath" and result = "east" + or + this = "Elisa" and result = "east" + or + this = "Lucretia" and result = "north" + or + this = "Anne" and result = "north" + or + this = "Eleanor" and result = "south" + or + this = "Joanna" and result = "south" + or + this = "Adam" and result = "east" + or + this = "Agnes" and result = "east" + or + this = "Rosanna" and result = "east" + or + this = "Clara" and result = "east" + or + this = "Melissa" and result = "west" + or + this = "Amy" and result = "west" + or + this = "Isabel" and result = "west" + or + this = "Jemima" and result = "west" + or + this = "Cordelia" and result = "west" + or + this = "Melinda" and result = "west" + or + this = "Delila" and result = "south" + or + this = "Jeremiah" and result = "north" + or + this = "Elijah" and result = "north" + or + this = "Hester" and result = "east" + or + this = "Walter" and result = "east" + or + this = "Oliver" and result = "east" + or + this = "Hugh" and result = "south" + or + this = "Aaron" and result = "south" + or + this = "Reuben" and result = "west" + or + this = "Eli" and result = "west" + or + this = "Amos" and result = "east" + or + this = "Augustus" and result = "south" + or + this = "Theodore" and result = "west" + or + this = "Ira" and result = "south" + or + this = "Timothy" and result = "north" + or + this = "Cyrus" and result = "north" + or + this = "Horace" and result = "east" + or + this = "Simon" and result = "east" + or + this = "Asa" and result = "east" + or + this = "Frank" and result = "west" + or + this = "Nelson" and result = "west" + or + this = "Leonard" and result = "west" + or + this = "Harrison" and result = "north" + or + this = "Anthony" and result = "north" + or + this = "Louis" and result = "north" + or + this = "Milton" and result = "south" + or + this = "Noah" and result = "south" + or + this = "Cornelius" and result = "east" + or + this = "Abdul" and result = "east" + or + this = "Warren" and result = "west" + or + this = "Harvey" and result = "west" + or + this = "Dennis" and result = "west" + or + this = "Wesley" and result = "west" + or + this = "Sylvester" and result = "south" + or + this = "Gilbert" and result = "east" + or + this = "Sullivan" and result = "east" + or + this = "Edmund" and result = "north" + or + this = "Wilson" and result = "north" + or + this = "Perry" and result = "west" + or + this = "Matthew" and result = "east" + or + this = "Simba" and result = "south" + or + this = "Nala" and result = "south" + or + this = "Rafiki" and result = "north" + or + this = "Shenzi" and result = "west" + } + + /** Holds if the person is deceased. */ + predicate isDeceased() { + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Edwin" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" + } + + /** Gets a parent of the person (alive or deceased). */ + Person getAParent() { + this = "Stephen" and result = "Edmund" + or + this = "Edmund" and result = "Augustus" + or + this = "Augustus" and result = "Stephen" + or + this = "Abby" and result = "Cornelia" + or + this = "Abby" and result = "Amos" + or + this = "Abdul" and result = "Susannah" + or + this = "Adam" and result = "Amos" + or + this = "Adeline" and result = "Melinda" + or + this = "Adeline" and result = "Frank" + or + this = "Agnes" and result = "Abdul" + or + this = "Aida" and result = "Agnes" + or + this = "Almira" and result = "Sylvester" + or + this = "Amos" and result = "Eunice" + or + this = "Amy" and result = "Noah" + or + this = "Amy" and result = "Chad" + or + this = "Angeline" and result = "Reuben" + or + this = "Angeline" and result = "Lucretia" + or + this = "Anne" and result = "Rhoda" + or + this = "Anne" and result = "Louis" + or + this = "Anthony" and result = "Lavina" + or + this = "Anthony" and result = "Asa" + or + this = "Asa" and result = "Cornelia" + or + this = "Cath" and result = "Harriet" + or + this = "Charlie" and result = "Matthew" + or + this = "Clara" and result = "Ernest" + or + this = "Cornelia" and result = "Cynthia" + or + this = "Cornelius" and result = "Eli" + or + this = "Deb" and result = "Margaret" + or + this = "Dennis" and result = "Fred" + or + this = "Eli" and result = "Susannah" + or + this = "Elijah" and result = "Delila" + or + this = "Elisa" and result = "Deb" + or + this = "Elisa" and result = "Horace" + or + this = "Esme" and result = "Margaret" + or + this = "Frank" and result = "Eleanor" + or + this = "Frank" and result = "Cyrus" + or + this = "George" and result = "Maya" + or + this = "George" and result = "Wilson" + or + this = "Gilbert" and result = "Cornelius" + or + this = "Harriet" and result = "Cynthia" + or + this = "Harrison" and result = "Louis" + or + this = "Harvey" and result = "Fred" + or + this = "Helen" and result = "Susannah" + or + this = "Hester" and result = "Edwin" + or + this = "Hugh" and result = "Cyrus" + or + this = "Hugh" and result = "Helen" + or + this = "Ira" and result = "Maya" + or + this = "Ira" and result = "Wilson" + or + this = "Isabel" and result = "Perry" + or + this = "Isabel" and result = "Harvey" + or + this = "Jemima" and result = "Melinda" + or + this = "Jemima" and result = "Frank" + or + this = "Ernest" and result = "Lilian" + or + this = "Ernest" and result = "Oscar" + or + this = "Gertrude" and result = "Ophelia" + or + this = "Gertrude" and result = "Raymond" + or + this = "Lilian" and result = "Elgar" + or + this = "Lilian" and result = "Mae" + or + this = "Raymond" and result = "Elgar" + or + this = "Raymond" and result = "Mae" + or + this = "Elmer" and result = "Ophelia" + or + this = "Elmer" and result = "Raymond" + or + this = "Herbert" and result = "Ophelia" + or + this = "Herbert" and result = "Raymond" + or + this = "Maude" and result = "Ophelia" + or + this = "Maude" and result = "Raymond" + or + this = "Otto" and result = "Elgar" + or + this = "Otto" and result = "Mae" + or + this = "Edwin" and result = "Otto" + or + this = "Parsley" and result = "Simon" + or + this = "Parsley" and result = "Garfunkel" + or + this = "Sage" and result = "Simon" + or + this = "Sage" and result = "Garfunkel" + or + this = "Rosemary" and result = "Simon" + or + this = "Rosemary" and result = "Garfunkel" + or + this = "Thyme" and result = "Simon" + or + this = "Thyme" and result = "Garfunkel" + or + this = "King Basil" and result = "Ophelia" + or + this = "King Basil" and result = "Raymond" + or + this = "Jo" and result = "Theodore" + or + this = "Joanna" and result = "Shenzi" + or + this = "Laura" and result = "Maya" + or + this = "Laura" and result = "Wilson" + or + this = "Lavina" and result = "Mahala" + or + this = "Lavina" and result = "Walter" + or + this = "Leonard" and result = "Cyrus" + or + this = "Leonard" and result = "Helen" + or + this = "Lucretia" and result = "Eleanor" + or + this = "Lucretia" and result = "Cyrus" + or + this = "Mahala" and result = "Eunice" + or + this = "Margaret" and result = "Cynthia" + or + this = "Matthew" and result = "Cyrus" + or + this = "Matthew" and result = "Helen" + or + this = "Maya" and result = "Meera" + or + this = "Melinda" and result = "Rafiki" + or + this = "Melissa" and result = "Mahala" + or + this = "Melissa" and result = "Walter" + or + this = "Nala" and result = "Bruce" + or + this = "Nelson" and result = "Mahala" + or + this = "Nelson" and result = "Walter" + or + this = "Noah" and result = "Eli" + or + this = "Olive" and result = "Reuben" + or + this = "Olive" and result = "Lucretia" + or + this = "Oliver" and result = "Matthew" + or + this = "Perry" and result = "Leonard" + or + this = "Ravi" and result = "Dina" + or + this = "Simba" and result = "Will" + or + this = "Simon" and result = "Margaret" + or + this = "Sullivan" and result = "Cornelius" + or + this = "Sylvester" and result = "Timothy" + or + this = "Theodore" and result = "Susannah" + or + this = "Tiana" and result = "Jo" + or + this = "Virginia" and result = "Helen" + or + this = "Warren" and result = "Shenzi" + or + this = "Wesley" and result = "Warren" + or + this = "Wesley" and result = "Jo" + or + this = "Will" and result = "Eli" + } + + /** Holds if the person is allowed in the region. Initially, all villagers are allowed in every region. */ + predicate isAllowedIn(string region) { + region = "north" or + region = "south" or + region = "east" or + region = "west" + } +} + +/** Returns a parent of the person. */ +Person parentOf(Person p) { result = p.getAParent() } diff --git a/javascript/ql/lib/tutorial.qll b/javascript/ql/lib/tutorial.qll new file mode 100644 index 00000000000..8cb1797a532 --- /dev/null +++ b/javascript/ql/lib/tutorial.qll @@ -0,0 +1,1207 @@ +/** + * This library is used in the QL detective tutorials. + * + * Note: Data is usually stored in a separate database and the QL libraries only contain predicates, + * but for this tutorial both the data and the predicates are stored in the library. + */ +class Person extends string { + Person() { + this = "Ronil" or + this = "Dina" or + this = "Ravi" or + this = "Bruce" or + this = "Jo" or + this = "Aida" or + this = "Esme" or + this = "Charlie" or + this = "Fred" or + this = "Meera" or + this = "Maya" or + this = "Chad" or + this = "Tiana" or + this = "Laura" or + this = "George" or + this = "Will" or + this = "Mary" or + this = "Almira" or + this = "Susannah" or + this = "Rhoda" or + this = "Cynthia" or + this = "Eunice" or + this = "Olive" or + this = "Virginia" or + this = "Angeline" or + this = "Helen" or + this = "Cornelia" or + this = "Harriet" or + this = "Mahala" or + this = "Abby" or + this = "Margaret" or + this = "Deb" or + this = "Minerva" or + this = "Severus" or + this = "Lavina" or + this = "Adeline" or + this = "Cath" or + this = "Elisa" or + this = "Lucretia" or + this = "Anne" or + this = "Eleanor" or + this = "Joanna" or + this = "Adam" or + this = "Agnes" or + this = "Rosanna" or + this = "Clara" or + this = "Melissa" or + this = "Amy" or + this = "Isabel" or + this = "Jemima" or + this = "Cordelia" or + this = "Melinda" or + this = "Delila" or + this = "Jeremiah" or + this = "Elijah" or + this = "Hester" or + this = "Walter" or + this = "Oliver" or + this = "Hugh" or + this = "Aaron" or + this = "Reuben" or + this = "Eli" or + this = "Amos" or + this = "Augustus" or + this = "Theodore" or + this = "Ira" or + this = "Timothy" or + this = "Cyrus" or + this = "Horace" or + this = "Simon" or + this = "Asa" or + this = "Frank" or + this = "Nelson" or + this = "Leonard" or + this = "Harrison" or + this = "Anthony" or + this = "Louis" or + this = "Milton" or + this = "Noah" or + this = "Cornelius" or + this = "Abdul" or + this = "Warren" or + this = "Harvey" or + this = "Dennis" or + this = "Wesley" or + this = "Sylvester" or + this = "Gilbert" or + this = "Sullivan" or + this = "Edmund" or + this = "Wilson" or + this = "Perry" or + this = "Matthew" or + this = "Simba" or + this = "Nala" or + this = "Rafiki" or + this = "Shenzi" or + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Edwin" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" or + this = "Stephen" + } + + /** Gets the hair color of the person. If the person is bald, there is no result. */ + string getHairColor() { + this = "Ronil" and result = "black" + or + this = "Dina" and result = "black" + or + this = "Ravi" and result = "black" + or + this = "Bruce" and result = "brown" + or + this = "Jo" and result = "red" + or + this = "Aida" and result = "blond" + or + this = "Esme" and result = "blond" + or + this = "Fred" and result = "gray" + or + this = "Meera" and result = "brown" + or + this = "Maya" and result = "brown" + or + this = "Chad" and result = "brown" + or + this = "Tiana" and result = "black" + or + this = "Laura" and result = "blond" + or + this = "George" and result = "blond" + or + this = "Will" and result = "blond" + or + this = "Mary" and result = "blond" + or + this = "Almira" and result = "black" + or + this = "Susannah" and result = "blond" + or + this = "Rhoda" and result = "blond" + or + this = "Cynthia" and result = "gray" + or + this = "Eunice" and result = "white" + or + this = "Olive" and result = "brown" + or + this = "Virginia" and result = "brown" + or + this = "Angeline" and result = "red" + or + this = "Helen" and result = "white" + or + this = "Cornelia" and result = "gray" + or + this = "Harriet" and result = "white" + or + this = "Mahala" and result = "black" + or + this = "Abby" and result = "red" + or + this = "Margaret" and result = "brown" + or + this = "Deb" and result = "brown" + or + this = "Minerva" and result = "brown" + or + this = "Severus" and result = "black" + or + this = "Lavina" and result = "brown" + or + this = "Adeline" and result = "brown" + or + this = "Cath" and result = "brown" + or + this = "Elisa" and result = "brown" + or + this = "Lucretia" and result = "gray" + or + this = "Anne" and result = "black" + or + this = "Eleanor" and result = "brown" + or + this = "Joanna" and result = "brown" + or + this = "Adam" and result = "black" + or + this = "Agnes" and result = "black" + or + this = "Rosanna" and result = "gray" + or + this = "Clara" and result = "blond" + or + this = "Melissa" and result = "brown" + or + this = "Amy" and result = "brown" + or + this = "Isabel" and result = "black" + or + this = "Jemima" and result = "red" + or + this = "Cordelia" and result = "red" + or + this = "Melinda" and result = "gray" + or + this = "Delila" and result = "white" + or + this = "Jeremiah" and result = "gray" + or + this = "Hester" and result = "black" + or + this = "Walter" and result = "black" + or + this = "Aaron" and result = "gray" + or + this = "Reuben" and result = "gray" + or + this = "Eli" and result = "gray" + or + this = "Amos" and result = "white" + or + this = "Augustus" and result = "white" + or + this = "Theodore" and result = "white" + or + this = "Timothy" and result = "brown" + or + this = "Cyrus" and result = "brown" + or + this = "Horace" and result = "brown" + or + this = "Simon" and result = "brown" + or + this = "Asa" and result = "brown" + or + this = "Frank" and result = "brown" + or + this = "Nelson" and result = "black" + or + this = "Leonard" and result = "black" + or + this = "Harrison" and result = "black" + or + this = "Anthony" and result = "black" + or + this = "Louis" and result = "black" + or + this = "Milton" and result = "blond" + or + this = "Noah" and result = "blond" + or + this = "Cornelius" and result = "red" + or + this = "Abdul" and result = "brown" + or + this = "Warren" and result = "red" + or + this = "Harvey" and result = "blond" + or + this = "Dennis" and result = "blond" + or + this = "Wesley" and result = "brown" + or + this = "Sylvester" and result = "brown" + or + this = "Gilbert" and result = "brown" + or + this = "Sullivan" and result = "brown" + or + this = "Edmund" and result = "brown" + or + this = "Wilson" and result = "blond" + or + this = "Perry" and result = "black" + or + this = "Simba" and result = "brown" + or + this = "Nala" and result = "brown" + or + this = "Rafiki" and result = "red" + or + this = "Shenzi" and result = "gray" + or + this = "Ernest" and result = "blond" + or + this = "Gertrude" and result = "brown" + or + this = "Oscar" and result = "blond" + or + this = "Lilian" and result = "brown" + or + this = "Raymond" and result = "brown" + or + this = "Elgar" and result = "brown" + or + this = "Elmer" and result = "brown" + or + this = "Herbert" and result = "brown" + or + this = "Maude" and result = "brown" + or + this = "Mae" and result = "brown" + or + this = "Otto" and result = "black" + or + this = "Edwin" and result = "black" + or + this = "Ophelia" and result = "brown" + or + this = "Parsley" and result = "brown" + or + this = "Sage" and result = "brown" + or + this = "Rosemary" and result = "brown" + or + this = "Thyme" and result = "brown" + or + this = "Garfunkel" and result = "brown" + or + this = "King Basil" and result = "brown" + or + this = "Stephen" and result = "black" + or + this = "Stephen" and result = "gray" + } + + /** Gets the age of the person (in years). If the person is deceased, there is no result. */ + int getAge() { + this = "Ronil" and result = 21 + or + this = "Dina" and result = 53 + or + this = "Ravi" and result = 16 + or + this = "Bruce" and result = 35 + or + this = "Jo" and result = 47 + or + this = "Aida" and result = 26 + or + this = "Esme" and result = 25 + or + this = "Charlie" and result = 31 + or + this = "Fred" and result = 68 + or + this = "Meera" and result = 62 + or + this = "Maya" and result = 29 + or + this = "Chad" and result = 49 + or + this = "Tiana" and result = 18 + or + this = "Laura" and result = 2 + or + this = "George" and result = 3 + or + this = "Will" and result = 41 + or + this = "Mary" and result = 51 + or + this = "Almira" and result = 1 + or + this = "Susannah" and result = 97 + or + this = "Rhoda" and result = 39 + or + this = "Cynthia" and result = 89 + or + this = "Eunice" and result = 83 + or + this = "Olive" and result = 25 + or + this = "Virginia" and result = 52 + or + this = "Angeline" and result = 22 + or + this = "Helen" and result = 79 + or + this = "Cornelia" and result = 59 + or + this = "Harriet" and result = 57 + or + this = "Mahala" and result = 61 + or + this = "Abby" and result = 24 + or + this = "Margaret" and result = 59 + or + this = "Deb" and result = 31 + or + this = "Minerva" and result = 72 + or + this = "Severus" and result = 61 + or + this = "Lavina" and result = 33 + or + this = "Adeline" and result = 17 + or + this = "Cath" and result = 22 + or + this = "Elisa" and result = 9 + or + this = "Lucretia" and result = 56 + or + this = "Anne" and result = 11 + or + this = "Eleanor" and result = 80 + or + this = "Joanna" and result = 43 + or + this = "Adam" and result = 37 + or + this = "Agnes" and result = 47 + or + this = "Rosanna" and result = 61 + or + this = "Clara" and result = 31 + or + this = "Melissa" and result = 37 + or + this = "Amy" and result = 12 + or + this = "Isabel" and result = 6 + or + this = "Jemima" and result = 16 + or + this = "Cordelia" and result = 21 + or + this = "Melinda" and result = 55 + or + this = "Delila" and result = 66 + or + this = "Jeremiah" and result = 54 + or + this = "Elijah" and result = 42 + or + this = "Hester" and result = 68 + or + this = "Walter" and result = 66 + or + this = "Oliver" and result = 33 + or + this = "Hugh" and result = 51 + or + this = "Aaron" and result = 49 + or + this = "Reuben" and result = 58 + or + this = "Eli" and result = 70 + or + this = "Amos" and result = 65 + or + this = "Augustus" and result = 56 + or + this = "Theodore" and result = 69 + or + this = "Ira" and result = 1 + or + this = "Timothy" and result = 54 + or + this = "Cyrus" and result = 78 + or + this = "Horace" and result = 34 + or + this = "Simon" and result = 23 + or + this = "Asa" and result = 28 + or + this = "Frank" and result = 59 + or + this = "Nelson" and result = 38 + or + this = "Leonard" and result = 58 + or + this = "Harrison" and result = 7 + or + this = "Anthony" and result = 2 + or + this = "Louis" and result = 34 + or + this = "Milton" and result = 36 + or + this = "Noah" and result = 48 + or + this = "Cornelius" and result = 41 + or + this = "Abdul" and result = 67 + or + this = "Warren" and result = 47 + or + this = "Harvey" and result = 31 + or + this = "Dennis" and result = 39 + or + this = "Wesley" and result = 13 + or + this = "Sylvester" and result = 19 + or + this = "Gilbert" and result = 16 + or + this = "Sullivan" and result = 17 + or + this = "Edmund" and result = 29 + or + this = "Wilson" and result = 27 + or + this = "Perry" and result = 31 + or + this = "Matthew" and result = 55 + or + this = "Simba" and result = 8 + or + this = "Nala" and result = 7 + or + this = "Rafiki" and result = 76 + or + this = "Shenzi" and result = 67 + } + + /** Gets the height of the person (in cm). If the person is deceased, there is no result. */ + float getHeight() { + this = "Ronil" and result = 183.0 + or + this = "Dina" and result = 155.1 + or + this = "Ravi" and result = 175.2 + or + this = "Bruce" and result = 191.3 + or + this = "Jo" and result = 163.4 + or + this = "Aida" and result = 182.6 + or + this = "Esme" and result = 176.9 + or + this = "Charlie" and result = 189.7 + or + this = "Fred" and result = 179.4 + or + this = "Meera" and result = 160.1 + or + this = "Maya" and result = 153.0 + or + this = "Chad" and result = 168.5 + or + this = "Tiana" and result = 149.7 + or + this = "Laura" and result = 87.5 + or + this = "George" and result = 96.4 + or + this = "Will" and result = 167.1 + or + this = "Mary" and result = 159.8 + or + this = "Almira" and result = 62.1 + or + this = "Susannah" and result = 145.8 + or + this = "Rhoda" and result = 180.1 + or + this = "Cynthia" and result = 161.8 + or + this = "Eunice" and result = 153.2 + or + this = "Olive" and result = 179.9 + or + this = "Virginia" and result = 165.1 + or + this = "Angeline" and result = 172.3 + or + this = "Helen" and result = 163.1 + or + this = "Cornelia" and result = 160.8 + or + this = "Harriet" and result = 163.2 + or + this = "Mahala" and result = 157.7 + or + this = "Abby" and result = 174.5 + or + this = "Margaret" and result = 165.6 + or + this = "Deb" and result = 171.6 + or + this = "Minerva" and result = 168.7 + or + this = "Severus" and result = 188.8 + or + this = "Lavina" and result = 155.1 + or + this = "Adeline" and result = 165.5 + or + this = "Cath" and result = 147.8 + or + this = "Elisa" and result = 129.4 + or + this = "Lucretia" and result = 153.6 + or + this = "Anne" and result = 140.4 + or + this = "Eleanor" and result = 151.1 + or + this = "Joanna" and result = 167.2 + or + this = "Adam" and result = 155.5 + or + this = "Agnes" and result = 156.8 + or + this = "Rosanna" and result = 162.4 + or + this = "Clara" and result = 158.6 + or + this = "Melissa" and result = 182.3 + or + this = "Amy" and result = 147.1 + or + this = "Isabel" and result = 121.4 + or + this = "Jemima" and result = 149.8 + or + this = "Cordelia" and result = 151.7 + or + this = "Melinda" and result = 154.4 + or + this = "Delila" and result = 163.4 + or + this = "Jeremiah" and result = 167.5 + or + this = "Elijah" and result = 184.5 + or + this = "Hester" and result = 152.7 + or + this = "Walter" and result = 159.6 + or + this = "Oliver" and result = 192.4 + or + this = "Hugh" and result = 173.1 + or + this = "Aaron" and result = 176.6 + or + this = "Reuben" and result = 169.9 + or + this = "Eli" and result = 180.4 + or + this = "Amos" and result = 167.4 + or + this = "Augustus" and result = 156.5 + or + this = "Theodore" and result = 176.6 + or + this = "Ira" and result = 54.1 + or + this = "Timothy" and result = 172.2 + or + this = "Cyrus" and result = 157.9 + or + this = "Horace" and result = 169.3 + or + this = "Simon" and result = 157.1 + or + this = "Asa" and result = 149.4 + or + this = "Frank" and result = 167.2 + or + this = "Nelson" and result = 173.0 + or + this = "Leonard" and result = 172.0 + or + this = "Harrison" and result = 126.0 + or + this = "Anthony" and result = 98.4 + or + this = "Louis" and result = 186.8 + or + this = "Milton" and result = 157.8 + or + this = "Noah" and result = 190.5 + or + this = "Cornelius" and result = 183.1 + or + this = "Abdul" and result = 182.0 + or + this = "Warren" and result = 175.0 + or + this = "Harvey" and result = 169.3 + or + this = "Dennis" and result = 160.4 + or + this = "Wesley" and result = 139.8 + or + this = "Sylvester" and result = 188.2 + or + this = "Gilbert" and result = 177.6 + or + this = "Sullivan" and result = 168.3 + or + this = "Edmund" and result = 159.2 + or + this = "Wilson" and result = 167.6 + or + this = "Perry" and result = 189.1 + or + this = "Matthew" and result = 167.2 + or + this = "Simba" and result = 140.1 + or + this = "Nala" and result = 138.0 + or + this = "Rafiki" and result = 139.3 + or + this = "Shenzi" and result = 171.1 + } + + /** Gets the location of the person's home ("north", "south", "east", or "west"). If the person is deceased, there is no result. */ + string getLocation() { + this = "Ronil" and result = "north" + or + this = "Dina" and result = "north" + or + this = "Ravi" and result = "north" + or + this = "Bruce" and result = "south" + or + this = "Jo" and result = "west" + or + this = "Aida" and result = "east" + or + this = "Esme" and result = "east" + or + this = "Charlie" and result = "south" + or + this = "Fred" and result = "west" + or + this = "Meera" and result = "south" + or + this = "Maya" and result = "south" + or + this = "Chad" and result = "south" + or + this = "Tiana" and result = "west" + or + this = "Laura" and result = "south" + or + this = "George" and result = "south" + or + this = "Will" and result = "south" + or + this = "Mary" and result = "south" + or + this = "Almira" and result = "south" + or + this = "Susannah" and result = "north" + or + this = "Rhoda" and result = "north" + or + this = "Cynthia" and result = "north" + or + this = "Eunice" and result = "north" + or + this = "Olive" and result = "west" + or + this = "Virginia" and result = "west" + or + this = "Angeline" and result = "west" + or + this = "Helen" and result = "west" + or + this = "Cornelia" and result = "east" + or + this = "Harriet" and result = "east" + or + this = "Mahala" and result = "east" + or + this = "Abby" and result = "east" + or + this = "Margaret" and result = "east" + or + this = "Deb" and result = "east" + or + this = "Minerva" and result = "south" + or + this = "Severus" and result = "north" + or + this = "Lavina" and result = "east" + or + this = "Adeline" and result = "west" + or + this = "Cath" and result = "east" + or + this = "Elisa" and result = "east" + or + this = "Lucretia" and result = "north" + or + this = "Anne" and result = "north" + or + this = "Eleanor" and result = "south" + or + this = "Joanna" and result = "south" + or + this = "Adam" and result = "east" + or + this = "Agnes" and result = "east" + or + this = "Rosanna" and result = "east" + or + this = "Clara" and result = "east" + or + this = "Melissa" and result = "west" + or + this = "Amy" and result = "west" + or + this = "Isabel" and result = "west" + or + this = "Jemima" and result = "west" + or + this = "Cordelia" and result = "west" + or + this = "Melinda" and result = "west" + or + this = "Delila" and result = "south" + or + this = "Jeremiah" and result = "north" + or + this = "Elijah" and result = "north" + or + this = "Hester" and result = "east" + or + this = "Walter" and result = "east" + or + this = "Oliver" and result = "east" + or + this = "Hugh" and result = "south" + or + this = "Aaron" and result = "south" + or + this = "Reuben" and result = "west" + or + this = "Eli" and result = "west" + or + this = "Amos" and result = "east" + or + this = "Augustus" and result = "south" + or + this = "Theodore" and result = "west" + or + this = "Ira" and result = "south" + or + this = "Timothy" and result = "north" + or + this = "Cyrus" and result = "north" + or + this = "Horace" and result = "east" + or + this = "Simon" and result = "east" + or + this = "Asa" and result = "east" + or + this = "Frank" and result = "west" + or + this = "Nelson" and result = "west" + or + this = "Leonard" and result = "west" + or + this = "Harrison" and result = "north" + or + this = "Anthony" and result = "north" + or + this = "Louis" and result = "north" + or + this = "Milton" and result = "south" + or + this = "Noah" and result = "south" + or + this = "Cornelius" and result = "east" + or + this = "Abdul" and result = "east" + or + this = "Warren" and result = "west" + or + this = "Harvey" and result = "west" + or + this = "Dennis" and result = "west" + or + this = "Wesley" and result = "west" + or + this = "Sylvester" and result = "south" + or + this = "Gilbert" and result = "east" + or + this = "Sullivan" and result = "east" + or + this = "Edmund" and result = "north" + or + this = "Wilson" and result = "north" + or + this = "Perry" and result = "west" + or + this = "Matthew" and result = "east" + or + this = "Simba" and result = "south" + or + this = "Nala" and result = "south" + or + this = "Rafiki" and result = "north" + or + this = "Shenzi" and result = "west" + } + + /** Holds if the person is deceased. */ + predicate isDeceased() { + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Edwin" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" + } + + /** Gets a parent of the person (alive or deceased). */ + Person getAParent() { + this = "Stephen" and result = "Edmund" + or + this = "Edmund" and result = "Augustus" + or + this = "Augustus" and result = "Stephen" + or + this = "Abby" and result = "Cornelia" + or + this = "Abby" and result = "Amos" + or + this = "Abdul" and result = "Susannah" + or + this = "Adam" and result = "Amos" + or + this = "Adeline" and result = "Melinda" + or + this = "Adeline" and result = "Frank" + or + this = "Agnes" and result = "Abdul" + or + this = "Aida" and result = "Agnes" + or + this = "Almira" and result = "Sylvester" + or + this = "Amos" and result = "Eunice" + or + this = "Amy" and result = "Noah" + or + this = "Amy" and result = "Chad" + or + this = "Angeline" and result = "Reuben" + or + this = "Angeline" and result = "Lucretia" + or + this = "Anne" and result = "Rhoda" + or + this = "Anne" and result = "Louis" + or + this = "Anthony" and result = "Lavina" + or + this = "Anthony" and result = "Asa" + or + this = "Asa" and result = "Cornelia" + or + this = "Cath" and result = "Harriet" + or + this = "Charlie" and result = "Matthew" + or + this = "Clara" and result = "Ernest" + or + this = "Cornelia" and result = "Cynthia" + or + this = "Cornelius" and result = "Eli" + or + this = "Deb" and result = "Margaret" + or + this = "Dennis" and result = "Fred" + or + this = "Eli" and result = "Susannah" + or + this = "Elijah" and result = "Delila" + or + this = "Elisa" and result = "Deb" + or + this = "Elisa" and result = "Horace" + or + this = "Esme" and result = "Margaret" + or + this = "Frank" and result = "Eleanor" + or + this = "Frank" and result = "Cyrus" + or + this = "George" and result = "Maya" + or + this = "George" and result = "Wilson" + or + this = "Gilbert" and result = "Cornelius" + or + this = "Harriet" and result = "Cynthia" + or + this = "Harrison" and result = "Louis" + or + this = "Harvey" and result = "Fred" + or + this = "Helen" and result = "Susannah" + or + this = "Hester" and result = "Edwin" + or + this = "Hugh" and result = "Cyrus" + or + this = "Hugh" and result = "Helen" + or + this = "Ira" and result = "Maya" + or + this = "Ira" and result = "Wilson" + or + this = "Isabel" and result = "Perry" + or + this = "Isabel" and result = "Harvey" + or + this = "Jemima" and result = "Melinda" + or + this = "Jemima" and result = "Frank" + or + this = "Ernest" and result = "Lilian" + or + this = "Ernest" and result = "Oscar" + or + this = "Gertrude" and result = "Ophelia" + or + this = "Gertrude" and result = "Raymond" + or + this = "Lilian" and result = "Elgar" + or + this = "Lilian" and result = "Mae" + or + this = "Raymond" and result = "Elgar" + or + this = "Raymond" and result = "Mae" + or + this = "Elmer" and result = "Ophelia" + or + this = "Elmer" and result = "Raymond" + or + this = "Herbert" and result = "Ophelia" + or + this = "Herbert" and result = "Raymond" + or + this = "Maude" and result = "Ophelia" + or + this = "Maude" and result = "Raymond" + or + this = "Otto" and result = "Elgar" + or + this = "Otto" and result = "Mae" + or + this = "Edwin" and result = "Otto" + or + this = "Parsley" and result = "Simon" + or + this = "Parsley" and result = "Garfunkel" + or + this = "Sage" and result = "Simon" + or + this = "Sage" and result = "Garfunkel" + or + this = "Rosemary" and result = "Simon" + or + this = "Rosemary" and result = "Garfunkel" + or + this = "Thyme" and result = "Simon" + or + this = "Thyme" and result = "Garfunkel" + or + this = "King Basil" and result = "Ophelia" + or + this = "King Basil" and result = "Raymond" + or + this = "Jo" and result = "Theodore" + or + this = "Joanna" and result = "Shenzi" + or + this = "Laura" and result = "Maya" + or + this = "Laura" and result = "Wilson" + or + this = "Lavina" and result = "Mahala" + or + this = "Lavina" and result = "Walter" + or + this = "Leonard" and result = "Cyrus" + or + this = "Leonard" and result = "Helen" + or + this = "Lucretia" and result = "Eleanor" + or + this = "Lucretia" and result = "Cyrus" + or + this = "Mahala" and result = "Eunice" + or + this = "Margaret" and result = "Cynthia" + or + this = "Matthew" and result = "Cyrus" + or + this = "Matthew" and result = "Helen" + or + this = "Maya" and result = "Meera" + or + this = "Melinda" and result = "Rafiki" + or + this = "Melissa" and result = "Mahala" + or + this = "Melissa" and result = "Walter" + or + this = "Nala" and result = "Bruce" + or + this = "Nelson" and result = "Mahala" + or + this = "Nelson" and result = "Walter" + or + this = "Noah" and result = "Eli" + or + this = "Olive" and result = "Reuben" + or + this = "Olive" and result = "Lucretia" + or + this = "Oliver" and result = "Matthew" + or + this = "Perry" and result = "Leonard" + or + this = "Ravi" and result = "Dina" + or + this = "Simba" and result = "Will" + or + this = "Simon" and result = "Margaret" + or + this = "Sullivan" and result = "Cornelius" + or + this = "Sylvester" and result = "Timothy" + or + this = "Theodore" and result = "Susannah" + or + this = "Tiana" and result = "Jo" + or + this = "Virginia" and result = "Helen" + or + this = "Warren" and result = "Shenzi" + or + this = "Wesley" and result = "Warren" + or + this = "Wesley" and result = "Jo" + or + this = "Will" and result = "Eli" + } + + /** Holds if the person is allowed in the region. Initially, all villagers are allowed in every region. */ + predicate isAllowedIn(string region) { + region = "north" or + region = "south" or + region = "east" or + region = "west" + } +} + +/** Returns a parent of the person. */ +Person parentOf(Person p) { result = p.getAParent() } diff --git a/python/ql/lib/tutorial.qll b/python/ql/lib/tutorial.qll new file mode 100644 index 00000000000..8cb1797a532 --- /dev/null +++ b/python/ql/lib/tutorial.qll @@ -0,0 +1,1207 @@ +/** + * This library is used in the QL detective tutorials. + * + * Note: Data is usually stored in a separate database and the QL libraries only contain predicates, + * but for this tutorial both the data and the predicates are stored in the library. + */ +class Person extends string { + Person() { + this = "Ronil" or + this = "Dina" or + this = "Ravi" or + this = "Bruce" or + this = "Jo" or + this = "Aida" or + this = "Esme" or + this = "Charlie" or + this = "Fred" or + this = "Meera" or + this = "Maya" or + this = "Chad" or + this = "Tiana" or + this = "Laura" or + this = "George" or + this = "Will" or + this = "Mary" or + this = "Almira" or + this = "Susannah" or + this = "Rhoda" or + this = "Cynthia" or + this = "Eunice" or + this = "Olive" or + this = "Virginia" or + this = "Angeline" or + this = "Helen" or + this = "Cornelia" or + this = "Harriet" or + this = "Mahala" or + this = "Abby" or + this = "Margaret" or + this = "Deb" or + this = "Minerva" or + this = "Severus" or + this = "Lavina" or + this = "Adeline" or + this = "Cath" or + this = "Elisa" or + this = "Lucretia" or + this = "Anne" or + this = "Eleanor" or + this = "Joanna" or + this = "Adam" or + this = "Agnes" or + this = "Rosanna" or + this = "Clara" or + this = "Melissa" or + this = "Amy" or + this = "Isabel" or + this = "Jemima" or + this = "Cordelia" or + this = "Melinda" or + this = "Delila" or + this = "Jeremiah" or + this = "Elijah" or + this = "Hester" or + this = "Walter" or + this = "Oliver" or + this = "Hugh" or + this = "Aaron" or + this = "Reuben" or + this = "Eli" or + this = "Amos" or + this = "Augustus" or + this = "Theodore" or + this = "Ira" or + this = "Timothy" or + this = "Cyrus" or + this = "Horace" or + this = "Simon" or + this = "Asa" or + this = "Frank" or + this = "Nelson" or + this = "Leonard" or + this = "Harrison" or + this = "Anthony" or + this = "Louis" or + this = "Milton" or + this = "Noah" or + this = "Cornelius" or + this = "Abdul" or + this = "Warren" or + this = "Harvey" or + this = "Dennis" or + this = "Wesley" or + this = "Sylvester" or + this = "Gilbert" or + this = "Sullivan" or + this = "Edmund" or + this = "Wilson" or + this = "Perry" or + this = "Matthew" or + this = "Simba" or + this = "Nala" or + this = "Rafiki" or + this = "Shenzi" or + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Edwin" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" or + this = "Stephen" + } + + /** Gets the hair color of the person. If the person is bald, there is no result. */ + string getHairColor() { + this = "Ronil" and result = "black" + or + this = "Dina" and result = "black" + or + this = "Ravi" and result = "black" + or + this = "Bruce" and result = "brown" + or + this = "Jo" and result = "red" + or + this = "Aida" and result = "blond" + or + this = "Esme" and result = "blond" + or + this = "Fred" and result = "gray" + or + this = "Meera" and result = "brown" + or + this = "Maya" and result = "brown" + or + this = "Chad" and result = "brown" + or + this = "Tiana" and result = "black" + or + this = "Laura" and result = "blond" + or + this = "George" and result = "blond" + or + this = "Will" and result = "blond" + or + this = "Mary" and result = "blond" + or + this = "Almira" and result = "black" + or + this = "Susannah" and result = "blond" + or + this = "Rhoda" and result = "blond" + or + this = "Cynthia" and result = "gray" + or + this = "Eunice" and result = "white" + or + this = "Olive" and result = "brown" + or + this = "Virginia" and result = "brown" + or + this = "Angeline" and result = "red" + or + this = "Helen" and result = "white" + or + this = "Cornelia" and result = "gray" + or + this = "Harriet" and result = "white" + or + this = "Mahala" and result = "black" + or + this = "Abby" and result = "red" + or + this = "Margaret" and result = "brown" + or + this = "Deb" and result = "brown" + or + this = "Minerva" and result = "brown" + or + this = "Severus" and result = "black" + or + this = "Lavina" and result = "brown" + or + this = "Adeline" and result = "brown" + or + this = "Cath" and result = "brown" + or + this = "Elisa" and result = "brown" + or + this = "Lucretia" and result = "gray" + or + this = "Anne" and result = "black" + or + this = "Eleanor" and result = "brown" + or + this = "Joanna" and result = "brown" + or + this = "Adam" and result = "black" + or + this = "Agnes" and result = "black" + or + this = "Rosanna" and result = "gray" + or + this = "Clara" and result = "blond" + or + this = "Melissa" and result = "brown" + or + this = "Amy" and result = "brown" + or + this = "Isabel" and result = "black" + or + this = "Jemima" and result = "red" + or + this = "Cordelia" and result = "red" + or + this = "Melinda" and result = "gray" + or + this = "Delila" and result = "white" + or + this = "Jeremiah" and result = "gray" + or + this = "Hester" and result = "black" + or + this = "Walter" and result = "black" + or + this = "Aaron" and result = "gray" + or + this = "Reuben" and result = "gray" + or + this = "Eli" and result = "gray" + or + this = "Amos" and result = "white" + or + this = "Augustus" and result = "white" + or + this = "Theodore" and result = "white" + or + this = "Timothy" and result = "brown" + or + this = "Cyrus" and result = "brown" + or + this = "Horace" and result = "brown" + or + this = "Simon" and result = "brown" + or + this = "Asa" and result = "brown" + or + this = "Frank" and result = "brown" + or + this = "Nelson" and result = "black" + or + this = "Leonard" and result = "black" + or + this = "Harrison" and result = "black" + or + this = "Anthony" and result = "black" + or + this = "Louis" and result = "black" + or + this = "Milton" and result = "blond" + or + this = "Noah" and result = "blond" + or + this = "Cornelius" and result = "red" + or + this = "Abdul" and result = "brown" + or + this = "Warren" and result = "red" + or + this = "Harvey" and result = "blond" + or + this = "Dennis" and result = "blond" + or + this = "Wesley" and result = "brown" + or + this = "Sylvester" and result = "brown" + or + this = "Gilbert" and result = "brown" + or + this = "Sullivan" and result = "brown" + or + this = "Edmund" and result = "brown" + or + this = "Wilson" and result = "blond" + or + this = "Perry" and result = "black" + or + this = "Simba" and result = "brown" + or + this = "Nala" and result = "brown" + or + this = "Rafiki" and result = "red" + or + this = "Shenzi" and result = "gray" + or + this = "Ernest" and result = "blond" + or + this = "Gertrude" and result = "brown" + or + this = "Oscar" and result = "blond" + or + this = "Lilian" and result = "brown" + or + this = "Raymond" and result = "brown" + or + this = "Elgar" and result = "brown" + or + this = "Elmer" and result = "brown" + or + this = "Herbert" and result = "brown" + or + this = "Maude" and result = "brown" + or + this = "Mae" and result = "brown" + or + this = "Otto" and result = "black" + or + this = "Edwin" and result = "black" + or + this = "Ophelia" and result = "brown" + or + this = "Parsley" and result = "brown" + or + this = "Sage" and result = "brown" + or + this = "Rosemary" and result = "brown" + or + this = "Thyme" and result = "brown" + or + this = "Garfunkel" and result = "brown" + or + this = "King Basil" and result = "brown" + or + this = "Stephen" and result = "black" + or + this = "Stephen" and result = "gray" + } + + /** Gets the age of the person (in years). If the person is deceased, there is no result. */ + int getAge() { + this = "Ronil" and result = 21 + or + this = "Dina" and result = 53 + or + this = "Ravi" and result = 16 + or + this = "Bruce" and result = 35 + or + this = "Jo" and result = 47 + or + this = "Aida" and result = 26 + or + this = "Esme" and result = 25 + or + this = "Charlie" and result = 31 + or + this = "Fred" and result = 68 + or + this = "Meera" and result = 62 + or + this = "Maya" and result = 29 + or + this = "Chad" and result = 49 + or + this = "Tiana" and result = 18 + or + this = "Laura" and result = 2 + or + this = "George" and result = 3 + or + this = "Will" and result = 41 + or + this = "Mary" and result = 51 + or + this = "Almira" and result = 1 + or + this = "Susannah" and result = 97 + or + this = "Rhoda" and result = 39 + or + this = "Cynthia" and result = 89 + or + this = "Eunice" and result = 83 + or + this = "Olive" and result = 25 + or + this = "Virginia" and result = 52 + or + this = "Angeline" and result = 22 + or + this = "Helen" and result = 79 + or + this = "Cornelia" and result = 59 + or + this = "Harriet" and result = 57 + or + this = "Mahala" and result = 61 + or + this = "Abby" and result = 24 + or + this = "Margaret" and result = 59 + or + this = "Deb" and result = 31 + or + this = "Minerva" and result = 72 + or + this = "Severus" and result = 61 + or + this = "Lavina" and result = 33 + or + this = "Adeline" and result = 17 + or + this = "Cath" and result = 22 + or + this = "Elisa" and result = 9 + or + this = "Lucretia" and result = 56 + or + this = "Anne" and result = 11 + or + this = "Eleanor" and result = 80 + or + this = "Joanna" and result = 43 + or + this = "Adam" and result = 37 + or + this = "Agnes" and result = 47 + or + this = "Rosanna" and result = 61 + or + this = "Clara" and result = 31 + or + this = "Melissa" and result = 37 + or + this = "Amy" and result = 12 + or + this = "Isabel" and result = 6 + or + this = "Jemima" and result = 16 + or + this = "Cordelia" and result = 21 + or + this = "Melinda" and result = 55 + or + this = "Delila" and result = 66 + or + this = "Jeremiah" and result = 54 + or + this = "Elijah" and result = 42 + or + this = "Hester" and result = 68 + or + this = "Walter" and result = 66 + or + this = "Oliver" and result = 33 + or + this = "Hugh" and result = 51 + or + this = "Aaron" and result = 49 + or + this = "Reuben" and result = 58 + or + this = "Eli" and result = 70 + or + this = "Amos" and result = 65 + or + this = "Augustus" and result = 56 + or + this = "Theodore" and result = 69 + or + this = "Ira" and result = 1 + or + this = "Timothy" and result = 54 + or + this = "Cyrus" and result = 78 + or + this = "Horace" and result = 34 + or + this = "Simon" and result = 23 + or + this = "Asa" and result = 28 + or + this = "Frank" and result = 59 + or + this = "Nelson" and result = 38 + or + this = "Leonard" and result = 58 + or + this = "Harrison" and result = 7 + or + this = "Anthony" and result = 2 + or + this = "Louis" and result = 34 + or + this = "Milton" and result = 36 + or + this = "Noah" and result = 48 + or + this = "Cornelius" and result = 41 + or + this = "Abdul" and result = 67 + or + this = "Warren" and result = 47 + or + this = "Harvey" and result = 31 + or + this = "Dennis" and result = 39 + or + this = "Wesley" and result = 13 + or + this = "Sylvester" and result = 19 + or + this = "Gilbert" and result = 16 + or + this = "Sullivan" and result = 17 + or + this = "Edmund" and result = 29 + or + this = "Wilson" and result = 27 + or + this = "Perry" and result = 31 + or + this = "Matthew" and result = 55 + or + this = "Simba" and result = 8 + or + this = "Nala" and result = 7 + or + this = "Rafiki" and result = 76 + or + this = "Shenzi" and result = 67 + } + + /** Gets the height of the person (in cm). If the person is deceased, there is no result. */ + float getHeight() { + this = "Ronil" and result = 183.0 + or + this = "Dina" and result = 155.1 + or + this = "Ravi" and result = 175.2 + or + this = "Bruce" and result = 191.3 + or + this = "Jo" and result = 163.4 + or + this = "Aida" and result = 182.6 + or + this = "Esme" and result = 176.9 + or + this = "Charlie" and result = 189.7 + or + this = "Fred" and result = 179.4 + or + this = "Meera" and result = 160.1 + or + this = "Maya" and result = 153.0 + or + this = "Chad" and result = 168.5 + or + this = "Tiana" and result = 149.7 + or + this = "Laura" and result = 87.5 + or + this = "George" and result = 96.4 + or + this = "Will" and result = 167.1 + or + this = "Mary" and result = 159.8 + or + this = "Almira" and result = 62.1 + or + this = "Susannah" and result = 145.8 + or + this = "Rhoda" and result = 180.1 + or + this = "Cynthia" and result = 161.8 + or + this = "Eunice" and result = 153.2 + or + this = "Olive" and result = 179.9 + or + this = "Virginia" and result = 165.1 + or + this = "Angeline" and result = 172.3 + or + this = "Helen" and result = 163.1 + or + this = "Cornelia" and result = 160.8 + or + this = "Harriet" and result = 163.2 + or + this = "Mahala" and result = 157.7 + or + this = "Abby" and result = 174.5 + or + this = "Margaret" and result = 165.6 + or + this = "Deb" and result = 171.6 + or + this = "Minerva" and result = 168.7 + or + this = "Severus" and result = 188.8 + or + this = "Lavina" and result = 155.1 + or + this = "Adeline" and result = 165.5 + or + this = "Cath" and result = 147.8 + or + this = "Elisa" and result = 129.4 + or + this = "Lucretia" and result = 153.6 + or + this = "Anne" and result = 140.4 + or + this = "Eleanor" and result = 151.1 + or + this = "Joanna" and result = 167.2 + or + this = "Adam" and result = 155.5 + or + this = "Agnes" and result = 156.8 + or + this = "Rosanna" and result = 162.4 + or + this = "Clara" and result = 158.6 + or + this = "Melissa" and result = 182.3 + or + this = "Amy" and result = 147.1 + or + this = "Isabel" and result = 121.4 + or + this = "Jemima" and result = 149.8 + or + this = "Cordelia" and result = 151.7 + or + this = "Melinda" and result = 154.4 + or + this = "Delila" and result = 163.4 + or + this = "Jeremiah" and result = 167.5 + or + this = "Elijah" and result = 184.5 + or + this = "Hester" and result = 152.7 + or + this = "Walter" and result = 159.6 + or + this = "Oliver" and result = 192.4 + or + this = "Hugh" and result = 173.1 + or + this = "Aaron" and result = 176.6 + or + this = "Reuben" and result = 169.9 + or + this = "Eli" and result = 180.4 + or + this = "Amos" and result = 167.4 + or + this = "Augustus" and result = 156.5 + or + this = "Theodore" and result = 176.6 + or + this = "Ira" and result = 54.1 + or + this = "Timothy" and result = 172.2 + or + this = "Cyrus" and result = 157.9 + or + this = "Horace" and result = 169.3 + or + this = "Simon" and result = 157.1 + or + this = "Asa" and result = 149.4 + or + this = "Frank" and result = 167.2 + or + this = "Nelson" and result = 173.0 + or + this = "Leonard" and result = 172.0 + or + this = "Harrison" and result = 126.0 + or + this = "Anthony" and result = 98.4 + or + this = "Louis" and result = 186.8 + or + this = "Milton" and result = 157.8 + or + this = "Noah" and result = 190.5 + or + this = "Cornelius" and result = 183.1 + or + this = "Abdul" and result = 182.0 + or + this = "Warren" and result = 175.0 + or + this = "Harvey" and result = 169.3 + or + this = "Dennis" and result = 160.4 + or + this = "Wesley" and result = 139.8 + or + this = "Sylvester" and result = 188.2 + or + this = "Gilbert" and result = 177.6 + or + this = "Sullivan" and result = 168.3 + or + this = "Edmund" and result = 159.2 + or + this = "Wilson" and result = 167.6 + or + this = "Perry" and result = 189.1 + or + this = "Matthew" and result = 167.2 + or + this = "Simba" and result = 140.1 + or + this = "Nala" and result = 138.0 + or + this = "Rafiki" and result = 139.3 + or + this = "Shenzi" and result = 171.1 + } + + /** Gets the location of the person's home ("north", "south", "east", or "west"). If the person is deceased, there is no result. */ + string getLocation() { + this = "Ronil" and result = "north" + or + this = "Dina" and result = "north" + or + this = "Ravi" and result = "north" + or + this = "Bruce" and result = "south" + or + this = "Jo" and result = "west" + or + this = "Aida" and result = "east" + or + this = "Esme" and result = "east" + or + this = "Charlie" and result = "south" + or + this = "Fred" and result = "west" + or + this = "Meera" and result = "south" + or + this = "Maya" and result = "south" + or + this = "Chad" and result = "south" + or + this = "Tiana" and result = "west" + or + this = "Laura" and result = "south" + or + this = "George" and result = "south" + or + this = "Will" and result = "south" + or + this = "Mary" and result = "south" + or + this = "Almira" and result = "south" + or + this = "Susannah" and result = "north" + or + this = "Rhoda" and result = "north" + or + this = "Cynthia" and result = "north" + or + this = "Eunice" and result = "north" + or + this = "Olive" and result = "west" + or + this = "Virginia" and result = "west" + or + this = "Angeline" and result = "west" + or + this = "Helen" and result = "west" + or + this = "Cornelia" and result = "east" + or + this = "Harriet" and result = "east" + or + this = "Mahala" and result = "east" + or + this = "Abby" and result = "east" + or + this = "Margaret" and result = "east" + or + this = "Deb" and result = "east" + or + this = "Minerva" and result = "south" + or + this = "Severus" and result = "north" + or + this = "Lavina" and result = "east" + or + this = "Adeline" and result = "west" + or + this = "Cath" and result = "east" + or + this = "Elisa" and result = "east" + or + this = "Lucretia" and result = "north" + or + this = "Anne" and result = "north" + or + this = "Eleanor" and result = "south" + or + this = "Joanna" and result = "south" + or + this = "Adam" and result = "east" + or + this = "Agnes" and result = "east" + or + this = "Rosanna" and result = "east" + or + this = "Clara" and result = "east" + or + this = "Melissa" and result = "west" + or + this = "Amy" and result = "west" + or + this = "Isabel" and result = "west" + or + this = "Jemima" and result = "west" + or + this = "Cordelia" and result = "west" + or + this = "Melinda" and result = "west" + or + this = "Delila" and result = "south" + or + this = "Jeremiah" and result = "north" + or + this = "Elijah" and result = "north" + or + this = "Hester" and result = "east" + or + this = "Walter" and result = "east" + or + this = "Oliver" and result = "east" + or + this = "Hugh" and result = "south" + or + this = "Aaron" and result = "south" + or + this = "Reuben" and result = "west" + or + this = "Eli" and result = "west" + or + this = "Amos" and result = "east" + or + this = "Augustus" and result = "south" + or + this = "Theodore" and result = "west" + or + this = "Ira" and result = "south" + or + this = "Timothy" and result = "north" + or + this = "Cyrus" and result = "north" + or + this = "Horace" and result = "east" + or + this = "Simon" and result = "east" + or + this = "Asa" and result = "east" + or + this = "Frank" and result = "west" + or + this = "Nelson" and result = "west" + or + this = "Leonard" and result = "west" + or + this = "Harrison" and result = "north" + or + this = "Anthony" and result = "north" + or + this = "Louis" and result = "north" + or + this = "Milton" and result = "south" + or + this = "Noah" and result = "south" + or + this = "Cornelius" and result = "east" + or + this = "Abdul" and result = "east" + or + this = "Warren" and result = "west" + or + this = "Harvey" and result = "west" + or + this = "Dennis" and result = "west" + or + this = "Wesley" and result = "west" + or + this = "Sylvester" and result = "south" + or + this = "Gilbert" and result = "east" + or + this = "Sullivan" and result = "east" + or + this = "Edmund" and result = "north" + or + this = "Wilson" and result = "north" + or + this = "Perry" and result = "west" + or + this = "Matthew" and result = "east" + or + this = "Simba" and result = "south" + or + this = "Nala" and result = "south" + or + this = "Rafiki" and result = "north" + or + this = "Shenzi" and result = "west" + } + + /** Holds if the person is deceased. */ + predicate isDeceased() { + this = "Ernest" or + this = "Gertrude" or + this = "Oscar" or + this = "Lilian" or + this = "Edwin" or + this = "Raymond" or + this = "Elgar" or + this = "Elmer" or + this = "Herbert" or + this = "Maude" or + this = "Mae" or + this = "Otto" or + this = "Ophelia" or + this = "Parsley" or + this = "Sage" or + this = "Rosemary" or + this = "Thyme" or + this = "Garfunkel" or + this = "King Basil" + } + + /** Gets a parent of the person (alive or deceased). */ + Person getAParent() { + this = "Stephen" and result = "Edmund" + or + this = "Edmund" and result = "Augustus" + or + this = "Augustus" and result = "Stephen" + or + this = "Abby" and result = "Cornelia" + or + this = "Abby" and result = "Amos" + or + this = "Abdul" and result = "Susannah" + or + this = "Adam" and result = "Amos" + or + this = "Adeline" and result = "Melinda" + or + this = "Adeline" and result = "Frank" + or + this = "Agnes" and result = "Abdul" + or + this = "Aida" and result = "Agnes" + or + this = "Almira" and result = "Sylvester" + or + this = "Amos" and result = "Eunice" + or + this = "Amy" and result = "Noah" + or + this = "Amy" and result = "Chad" + or + this = "Angeline" and result = "Reuben" + or + this = "Angeline" and result = "Lucretia" + or + this = "Anne" and result = "Rhoda" + or + this = "Anne" and result = "Louis" + or + this = "Anthony" and result = "Lavina" + or + this = "Anthony" and result = "Asa" + or + this = "Asa" and result = "Cornelia" + or + this = "Cath" and result = "Harriet" + or + this = "Charlie" and result = "Matthew" + or + this = "Clara" and result = "Ernest" + or + this = "Cornelia" and result = "Cynthia" + or + this = "Cornelius" and result = "Eli" + or + this = "Deb" and result = "Margaret" + or + this = "Dennis" and result = "Fred" + or + this = "Eli" and result = "Susannah" + or + this = "Elijah" and result = "Delila" + or + this = "Elisa" and result = "Deb" + or + this = "Elisa" and result = "Horace" + or + this = "Esme" and result = "Margaret" + or + this = "Frank" and result = "Eleanor" + or + this = "Frank" and result = "Cyrus" + or + this = "George" and result = "Maya" + or + this = "George" and result = "Wilson" + or + this = "Gilbert" and result = "Cornelius" + or + this = "Harriet" and result = "Cynthia" + or + this = "Harrison" and result = "Louis" + or + this = "Harvey" and result = "Fred" + or + this = "Helen" and result = "Susannah" + or + this = "Hester" and result = "Edwin" + or + this = "Hugh" and result = "Cyrus" + or + this = "Hugh" and result = "Helen" + or + this = "Ira" and result = "Maya" + or + this = "Ira" and result = "Wilson" + or + this = "Isabel" and result = "Perry" + or + this = "Isabel" and result = "Harvey" + or + this = "Jemima" and result = "Melinda" + or + this = "Jemima" and result = "Frank" + or + this = "Ernest" and result = "Lilian" + or + this = "Ernest" and result = "Oscar" + or + this = "Gertrude" and result = "Ophelia" + or + this = "Gertrude" and result = "Raymond" + or + this = "Lilian" and result = "Elgar" + or + this = "Lilian" and result = "Mae" + or + this = "Raymond" and result = "Elgar" + or + this = "Raymond" and result = "Mae" + or + this = "Elmer" and result = "Ophelia" + or + this = "Elmer" and result = "Raymond" + or + this = "Herbert" and result = "Ophelia" + or + this = "Herbert" and result = "Raymond" + or + this = "Maude" and result = "Ophelia" + or + this = "Maude" and result = "Raymond" + or + this = "Otto" and result = "Elgar" + or + this = "Otto" and result = "Mae" + or + this = "Edwin" and result = "Otto" + or + this = "Parsley" and result = "Simon" + or + this = "Parsley" and result = "Garfunkel" + or + this = "Sage" and result = "Simon" + or + this = "Sage" and result = "Garfunkel" + or + this = "Rosemary" and result = "Simon" + or + this = "Rosemary" and result = "Garfunkel" + or + this = "Thyme" and result = "Simon" + or + this = "Thyme" and result = "Garfunkel" + or + this = "King Basil" and result = "Ophelia" + or + this = "King Basil" and result = "Raymond" + or + this = "Jo" and result = "Theodore" + or + this = "Joanna" and result = "Shenzi" + or + this = "Laura" and result = "Maya" + or + this = "Laura" and result = "Wilson" + or + this = "Lavina" and result = "Mahala" + or + this = "Lavina" and result = "Walter" + or + this = "Leonard" and result = "Cyrus" + or + this = "Leonard" and result = "Helen" + or + this = "Lucretia" and result = "Eleanor" + or + this = "Lucretia" and result = "Cyrus" + or + this = "Mahala" and result = "Eunice" + or + this = "Margaret" and result = "Cynthia" + or + this = "Matthew" and result = "Cyrus" + or + this = "Matthew" and result = "Helen" + or + this = "Maya" and result = "Meera" + or + this = "Melinda" and result = "Rafiki" + or + this = "Melissa" and result = "Mahala" + or + this = "Melissa" and result = "Walter" + or + this = "Nala" and result = "Bruce" + or + this = "Nelson" and result = "Mahala" + or + this = "Nelson" and result = "Walter" + or + this = "Noah" and result = "Eli" + or + this = "Olive" and result = "Reuben" + or + this = "Olive" and result = "Lucretia" + or + this = "Oliver" and result = "Matthew" + or + this = "Perry" and result = "Leonard" + or + this = "Ravi" and result = "Dina" + or + this = "Simba" and result = "Will" + or + this = "Simon" and result = "Margaret" + or + this = "Sullivan" and result = "Cornelius" + or + this = "Sylvester" and result = "Timothy" + or + this = "Theodore" and result = "Susannah" + or + this = "Tiana" and result = "Jo" + or + this = "Virginia" and result = "Helen" + or + this = "Warren" and result = "Shenzi" + or + this = "Wesley" and result = "Warren" + or + this = "Wesley" and result = "Jo" + or + this = "Will" and result = "Eli" + } + + /** Holds if the person is allowed in the region. Initially, all villagers are allowed in every region. */ + predicate isAllowedIn(string region) { + region = "north" or + region = "south" or + region = "east" or + region = "west" + } +} + +/** Returns a parent of the person. */ +Person parentOf(Person p) { result = p.getAParent() } From ee44e742f6fa67619453ac571f88c51647d032d9 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 13 Oct 2021 20:07:10 +0200 Subject: [PATCH 272/361] Data flow: Avoid bad join-order in `pathIntoCallable0` --- .../code/csharp/dataflow/internal/DataFlowImpl.qll | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) 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 4ca06c93362..c5ea5f4fc77 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -3561,13 +3561,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa) and + callable = resolveCall(call, outercc) } /** @@ -3579,8 +3576,9 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa) and + parameterCand(callable, i, apa, mid.getConfiguration()) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) From 5be7a97a16f7f41d7d50092fcb8f22f94328afc0 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 13 Oct 2021 20:07:18 +0200 Subject: [PATCH 273/361] Data flow: Avoid unnecessary non-linear recursion via `getConfiguration()` --- .../csharp/dataflow/internal/DataFlowImpl.qll | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) 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 c5ea5f4fc77..0db4f7fc53e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,9 +3563,9 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + AccessPath ap, AccessPathApprox apa, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa) and + pathIntoArg(mid, i, outercc, call, ap, apa, config) and callable = resolveCall(call, outercc) } @@ -3572,13 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa) and - parameterCand(callable, i, apa, mid.getConfiguration()) and + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3615,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3629,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3645,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** From c14dcfbfe4d4397ac7c9237fe185e95b51e5ed25 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 13 Oct 2021 20:13:28 +0200 Subject: [PATCH 274/361] Data flow: Sync --- .../cpp/dataflow/internal/DataFlowImpl.qll | 46 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl2.qll | 46 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl3.qll | 46 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl4.qll | 46 ++++++++++--------- .../dataflow/internal/DataFlowImplLocal.qll | 46 ++++++++++--------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 46 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl2.qll | 46 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl3.qll | 46 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl4.qll | 46 ++++++++++--------- .../dataflow/internal/DataFlowImpl2.qll | 46 ++++++++++--------- .../dataflow/internal/DataFlowImpl3.qll | 46 ++++++++++--------- .../dataflow/internal/DataFlowImpl4.qll | 46 ++++++++++--------- .../dataflow/internal/DataFlowImpl5.qll | 46 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl.qll | 46 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl2.qll | 46 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl3.qll | 46 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl4.qll | 46 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl5.qll | 46 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl6.qll | 46 ++++++++++--------- .../DataFlowImplForSerializability.qll | 46 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl.qll | 46 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl2.qll | 46 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl3.qll | 46 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl4.qll | 46 ++++++++++--------- 24 files changed, 576 insertions(+), 528 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 4ca06c93362..0db4f7fc53e 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** 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 4ca06c93362..0db4f7fc53e 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 @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** 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 4ca06c93362..0db4f7fc53e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** 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 4ca06c93362..0db4f7fc53e 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 4ca06c93362..0db4f7fc53e 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -3460,7 +3460,7 @@ private predicate pathStep( exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone or @@ -3537,14 +3537,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) */ pragma[noinline] private predicate pathIntoArg( - PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa + PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa, + Configuration config ) { exists(ArgNode arg | arg = mid.getNodeEx().asNode() and cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = ap.getApprox() + apa = ap.getApprox() and + config = mid.getConfiguration() ) } @@ -3561,13 +3563,10 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap + AccessPath ap, AccessPathApprox apa, Configuration config ) { - exists(AccessPathApprox apa | - pathIntoArg(mid, i, outercc, call, ap, apa) and - callable = resolveCall(call, outercc) and - parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) - ) + pathIntoArg(mid, i, outercc, call, ap, apa, config) and + callable = resolveCall(call, outercc) } /** @@ -3575,12 +3574,14 @@ private predicate pathIntoCallable0( * before and after entering the callable are `outercc` and `innercc`, * respectively. */ +pragma[nomagic] private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, - DataFlowCall call + DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, i, outercc, call, ap) and + exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | + pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and + parameterCand(callable, i, apa, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) @@ -3617,11 +3618,11 @@ private predicate paramFlowsThrough( pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, - AccessPathApprox apa + AccessPathApprox apa, Configuration config ) { exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) + pathIntoCallable(mid, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, innercc, sc, ap, apa, config) ) } @@ -3631,9 +3632,9 @@ private predicate pathThroughCallable0( */ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, cc, ap, apa) and - out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) ) } @@ -3647,10 +3648,11 @@ private module Subpaths { PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, AccessPath apout ) { - pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, innercc, sc, _) and - paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, - unbindConf(arg.getConfiguration())) + exists(Configuration config | + pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, innercc, sc, _, config) and + paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config)) + ) } /** From 4991301f365063f16222a5ee45521b5a3eec1dc1 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 13 Oct 2021 19:45:02 +0100 Subject: [PATCH 275/361] JS: Fix incorrect fix. --- .../ql/lib/semmle/javascript/security/UselessUseOfCat.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll index eda163f053f..b2b65038508 100644 --- a/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll +++ b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll @@ -307,7 +307,7 @@ module PrettyPrintCatCall { then result = str.suffix(5) else // prettify `${newpath}` to just newpath - if str.matches("`${%") and str.matches("}`%") and not str.suffix(3).matches("%{%") + if str.matches("`${%") and str.matches("%}`") and not str.suffix(3).matches("%{%") then result = str.prefix(str.length() - 2).suffix(3) else result = str } From a358a192c404c00fcb9d29b8d98c62ad3b7c0f69 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 14 Oct 2021 10:11:55 +0200 Subject: [PATCH 276/361] add explicit this to all calls to class predicates --- csharp/ql/lib/semmle/code/asp/WebConfig.qll | 22 +- csharp/ql/lib/semmle/code/cil/Access.qll | 10 +- csharp/ql/lib/semmle/code/cil/BasicBlock.qll | 38 +- .../lib/semmle/code/cil/ConsistencyChecks.qll | 67 +-- csharp/ql/lib/semmle/code/cil/ControlFlow.qll | 16 +- csharp/ql/lib/semmle/code/cil/Declaration.qll | 17 +- csharp/ql/lib/semmle/code/cil/Generics.qll | 2 +- csharp/ql/lib/semmle/code/cil/Instruction.qll | 16 +- .../lib/semmle/code/cil/InstructionGroups.qll | 54 +-- .../ql/lib/semmle/code/cil/Instructions.qll | 103 ++-- csharp/ql/lib/semmle/code/cil/Method.qll | 72 +-- csharp/ql/lib/semmle/code/cil/Type.qll | 8 +- csharp/ql/lib/semmle/code/cil/Types.qll | 18 +- csharp/ql/lib/semmle/code/cil/Variable.qll | 39 +- .../lib/semmle/code/csharp/AnnotatedType.qll | 14 +- .../ql/lib/semmle/code/csharp/Attribute.qll | 2 +- csharp/ql/lib/semmle/code/csharp/Callable.qll | 28 +- csharp/ql/lib/semmle/code/csharp/Element.qll | 2 +- csharp/ql/lib/semmle/code/csharp/Event.qll | 12 +- csharp/ql/lib/semmle/code/csharp/File.qll | 30 +- csharp/ql/lib/semmle/code/csharp/Generics.qll | 36 +- csharp/ql/lib/semmle/code/csharp/Member.qll | 45 +- csharp/ql/lib/semmle/code/csharp/Modifier.qll | 8 +- .../lib/semmle/code/csharp/Preprocessor.qll | 2 +- csharp/ql/lib/semmle/code/csharp/PrintAst.qll | 6 +- csharp/ql/lib/semmle/code/csharp/Property.qll | 46 +- csharp/ql/lib/semmle/code/csharp/Stmt.qll | 70 +-- csharp/ql/lib/semmle/code/csharp/Type.qll | 98 ++-- .../ql/lib/semmle/code/csharp/Unification.qll | 2 +- csharp/ql/lib/semmle/code/csharp/Variable.qll | 10 +- csharp/ql/lib/semmle/code/csharp/XML.qll | 12 +- .../semmle/code/csharp/commons/Assertions.qll | 4 +- .../code/csharp/commons/GeneratedCode.qll | 4 +- .../code/csharp/controlflow/BasicBlocks.qll | 32 +- .../csharp/controlflow/ControlFlowElement.qll | 5 +- .../csharp/controlflow/ControlFlowGraph.qll | 24 +- .../semmle/code/csharp/controlflow/Guards.qll | 6 +- .../internal/ControlFlowGraphImpl.qll | 8 +- .../controlflow/internal/PreBasicBlocks.qll | 6 +- .../csharp/controlflow/internal/Splitting.qll | 10 +- .../controlflow/internal/SuccessorType.qll | 4 +- .../csharp/dataflow/LibraryTypeDataFlow.qll | 150 +++--- .../lib/semmle/code/csharp/dataflow/SSA.qll | 26 +- .../csharp/dataflow/internal/DataFlowImpl.qll | 16 +- .../dataflow/internal/DataFlowImpl2.qll | 16 +- .../dataflow/internal/DataFlowImpl3.qll | 16 +- .../dataflow/internal/DataFlowImpl4.qll | 16 +- .../dataflow/internal/DataFlowImpl5.qll | 16 +- .../dataflow/internal/DataFlowImplCommon.qll | 4 +- .../internal/rangeanalysis/RangeUtils.qll | 4 +- .../rangeanalysis/SsaReadPositionCommon.qll | 6 +- .../tainttracking1/TaintTrackingImpl.qll | 12 +- .../tainttracking2/TaintTrackingImpl.qll | 12 +- .../tainttracking3/TaintTrackingImpl.qll | 12 +- .../tainttracking4/TaintTrackingImpl.qll | 12 +- .../tainttracking5/TaintTrackingImpl.qll | 12 +- .../semmle/code/csharp/dispatch/Dispatch.qll | 75 +-- .../csharp/dispatch/OverridableCallable.qll | 24 +- .../lib/semmle/code/csharp/exprs/Access.qll | 18 +- .../code/csharp/exprs/ArithmeticOperation.qll | 4 +- .../semmle/code/csharp/exprs/Assignment.qll | 6 +- .../ql/lib/semmle/code/csharp/exprs/Call.qll | 52 +- .../lib/semmle/code/csharp/exprs/Creation.qll | 12 +- .../lib/semmle/code/csharp/exprs/Dynamic.qll | 12 +- .../ql/lib/semmle/code/csharp/exprs/Expr.qll | 38 +- .../lib/semmle/code/csharp/exprs/Literal.qll | 6 +- .../csharp/frameworks/EntityFramework.qll | 14 +- .../semmle/code/csharp/frameworks/Format.qll | 4 +- .../semmle/code/csharp/frameworks/JsonNET.qll | 8 +- .../lib/semmle/code/csharp/frameworks/Moq.qll | 2 +- .../semmle/code/csharp/frameworks/System.qll | 14 +- .../lib/semmle/code/csharp/frameworks/WCF.qll | 2 +- .../frameworks/microsoft/AspNetCore.qll | 100 ++-- .../frameworks/system/collections/Generic.qll | 8 +- .../frameworks/system/data/SqlClient.qll | 2 +- .../system/text/RegularExpressions.qll | 2 +- .../code/csharp/frameworks/system/web/Mvc.qll | 6 +- .../csharp/frameworks/system/web/WebPages.qll | 12 +- .../code/csharp/security/SensitiveActions.qll | 2 +- .../HardcodedSymmetricEncryptionKey.qll | 6 +- .../security/dataflow/ExternalAPIsQuery.qll | 4 +- .../csharp/security/dataflow/XSSSinks.qll | 2 +- .../security/dataflow/flowsources/Remote.qll | 4 +- .../csharp/security/xml/InsecureXMLQuery.qll | 4 +- csharp/ql/lib/semmle/code/dotnet/Callable.qll | 2 +- .../ql/lib/semmle/code/dotnet/Declaration.qll | 2 +- csharp/ql/lib/semmle/code/dotnet/Element.qll | 6 +- csharp/ql/lib/semmle/code/dotnet/Expr.qll | 2 +- csharp/ql/lib/semmle/code/dotnet/Generics.qll | 4 +- .../ql/lib/semmle/code/dotnet/Namespace.qll | 2 +- csharp/ql/lib/semmle/code/dotnet/Type.qll | 18 +- csharp/ql/lib/semmle/code/dotnet/Variable.qll | 4 +- .../Diagnostics/DiagnosticExtractionErrors.ql | 4 +- csharp/ql/src/Stubs/Stubs.qll | 17 +- .../ir/implementation/raw/IRBlock.qll | 30 +- .../ir/implementation/raw/Instruction.qll | 451 +++++++++--------- .../ir/implementation/raw/Operand.qll | 56 ++- .../raw/internal/TranslatedCondition.qll | 4 +- .../raw/internal/TranslatedDeclaration.qll | 4 +- .../raw/internal/TranslatedElement.qll | 4 +- .../raw/internal/TranslatedExpr.qll | 56 ++- .../raw/internal/TranslatedFunction.qll | 20 +- .../raw/internal/TranslatedInitialization.qll | 50 +- .../raw/internal/TranslatedStmt.qll | 92 ++-- .../implementation/unaliased_ssa/IRBlock.qll | 30 +- .../unaliased_ssa/Instruction.qll | 451 +++++++++--------- .../implementation/unaliased_ssa/Operand.qll | 56 ++- .../internal/AliasAnalysisImports.qll | 14 +- .../src/experimental/ir/internal/IRGuards.qll | 8 +- .../assignables/AssignableDefinition.ql | 16 +- .../library-tests/cil/consistency/Handles.ql | 2 +- 111 files changed, 1667 insertions(+), 1519 deletions(-) diff --git a/csharp/ql/lib/semmle/code/asp/WebConfig.qll b/csharp/ql/lib/semmle/code/asp/WebConfig.qll index ed0f9aef451..16d5393afc2 100644 --- a/csharp/ql/lib/semmle/code/asp/WebConfig.qll +++ b/csharp/ql/lib/semmle/code/asp/WebConfig.qll @@ -8,7 +8,7 @@ import csharp * A `Web.config` file. */ class WebConfigXML extends XMLFile { - WebConfigXML() { getName().matches("%Web.config") } + WebConfigXML() { this.getName().matches("%Web.config") } } /** A `<configuration>` tag in an ASP.NET configuration file. */ @@ -73,12 +73,14 @@ class FormsElement extends XMLElement { /** * Gets attribute's `requireSSL` value. */ - string getRequireSSL() { result = getAttribute("requireSSL").getValue().trim().toLowerCase() } + string getRequireSSL() { + result = this.getAttribute("requireSSL").getValue().trim().toLowerCase() + } /** * Holds if `requireSSL` value is true. */ - predicate isRequireSSL() { getRequireSSL() = "true" } + predicate isRequireSSL() { this.getRequireSSL() = "true" } } /** A `<httpCookies>` tag in an ASP.NET configuration file. */ @@ -89,26 +91,28 @@ class HttpCookiesElement extends XMLElement { * Gets attribute's `httpOnlyCookies` value. */ string getHttpOnlyCookies() { - result = getAttribute("httpOnlyCookies").getValue().trim().toLowerCase() + result = this.getAttribute("httpOnlyCookies").getValue().trim().toLowerCase() } /** * Holds if there is any chance that `httpOnlyCookies` is set to `true`. */ - predicate isHttpOnlyCookies() { getHttpOnlyCookies() = "true" } + predicate isHttpOnlyCookies() { this.getHttpOnlyCookies() = "true" } /** * Gets attribute's `requireSSL` value. */ - string getRequireSSL() { result = getAttribute("requireSSL").getValue().trim().toLowerCase() } + string getRequireSSL() { + result = this.getAttribute("requireSSL").getValue().trim().toLowerCase() + } /** * Holds if there is any chance that `requireSSL` is set to `true` either globally or for Forms. */ predicate isRequireSSL() { - getRequireSSL() = "true" + this.getRequireSSL() = "true" or - not getRequireSSL() = "false" and // not set all, i.e. default - exists(FormsElement forms | forms.getFile() = getFile() | forms.isRequireSSL()) + not this.getRequireSSL() = "false" and // not set all, i.e. default + exists(FormsElement forms | forms.getFile() = this.getFile() | forms.isRequireSSL()) } } diff --git a/csharp/ql/lib/semmle/code/cil/Access.qll b/csharp/ql/lib/semmle/code/cil/Access.qll index 6d72a48ff1b..5fecd8acb10 100644 --- a/csharp/ql/lib/semmle/code/cil/Access.qll +++ b/csharp/ql/lib/semmle/code/cil/Access.qll @@ -20,7 +20,7 @@ class VariableAccess extends Access, @cil_access { } /** An instruction that reads a variable. */ class ReadAccess extends VariableAccess, Expr, @cil_read_access { - override Type getType() { result = getTarget().getType() } + override Type getType() { result = this.getTarget().getType() } } /** An instruction yielding an address. */ @@ -49,7 +49,7 @@ class ParameterReadAccess extends ParameterAccess, ReadAccess { class ParameterWriteAccess extends ParameterAccess, WriteAccess { override int getPopCount() { result = 1 } - override Expr getExpr() { result = getOperand(0) } + override Expr getExpr() { result = this.getOperand(0) } } /** An access to the `this` parameter. */ @@ -71,9 +71,9 @@ class LocalVariableAccess extends StackVariableAccess, @cil_local_access { class LocalVariableWriteAccess extends LocalVariableAccess, WriteAccess { override int getPopCount() { result = 1 } - override Expr getExpr() { result = getOperand(0) } + override Expr getExpr() { result = this.getOperand(0) } - override string getExtra() { result = "L" + getTarget().getIndex() } + override string getExtra() { result = "L" + this.getTarget().getIndex() } } /** An instruction that reads a local variable. */ @@ -85,7 +85,7 @@ class LocalVariableReadAccess extends LocalVariableAccess, ReadAccess { class FieldAccess extends VariableAccess, @cil_field_access { override Field getTarget() { result = VariableAccess.super.getTarget() } - override string getExtra() { result = getTarget().getName() } + override string getExtra() { result = this.getTarget().getName() } /** Gets the qualifier of the access, if any. */ abstract Expr getQualifier(); diff --git a/csharp/ql/lib/semmle/code/cil/BasicBlock.qll b/csharp/ql/lib/semmle/code/cil/BasicBlock.qll index 0c9c0b8ad07..2680cb0a769 100644 --- a/csharp/ql/lib/semmle/code/cil/BasicBlock.qll +++ b/csharp/ql/lib/semmle/code/cil/BasicBlock.qll @@ -10,7 +10,7 @@ private import CIL */ class BasicBlock extends Cached::TBasicBlockStart { /** Gets an immediate successor of this basic block, if any. */ - BasicBlock getASuccessor() { result.getFirstNode() = getLastNode().getASuccessor() } + BasicBlock getASuccessor() { result.getFirstNode() = this.getLastNode().getASuccessor() } /** Gets an immediate predecessor of this basic block, if any. */ BasicBlock getAPredecessor() { result.getASuccessor() = this } @@ -31,7 +31,7 @@ class BasicBlock extends Cached::TBasicBlockStart { * The basic block on line 2 is an immediate `true` successor of the * basic block on line 1. */ - BasicBlock getATrueSuccessor() { result.getFirstNode() = getLastNode().getTrueSuccessor() } + BasicBlock getATrueSuccessor() { result.getFirstNode() = this.getLastNode().getTrueSuccessor() } /** * Gets an immediate `false` successor, if any. @@ -49,22 +49,22 @@ class BasicBlock extends Cached::TBasicBlockStart { * The basic block on line 2 is an immediate `false` successor of the * basic block on line 1. */ - BasicBlock getAFalseSuccessor() { result.getFirstNode() = getLastNode().getFalseSuccessor() } + BasicBlock getAFalseSuccessor() { result.getFirstNode() = this.getLastNode().getFalseSuccessor() } /** Gets the control flow node at a specific (zero-indexed) position in this basic block. */ - ControlFlowNode getNode(int pos) { Cached::bbIndex(getFirstNode(), result, pos) } + ControlFlowNode getNode(int pos) { Cached::bbIndex(this.getFirstNode(), result, pos) } /** Gets a control flow node in this basic block. */ - ControlFlowNode getANode() { result = getNode(_) } + ControlFlowNode getANode() { result = this.getNode(_) } /** Gets the first control flow node in this basic block. */ ControlFlowNode getFirstNode() { this = Cached::TBasicBlockStart(result) } /** Gets the last control flow node in this basic block. */ - ControlFlowNode getLastNode() { result = getNode(length() - 1) } + ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) } /** Gets the length of this basic block. */ - int length() { result = strictcount(getANode()) } + int length() { result = strictcount(this.getANode()) } /** * Holds if this basic block strictly dominates basic block `bb`. @@ -114,7 +114,7 @@ class BasicBlock extends Cached::TBasicBlockStart { */ predicate dominates(BasicBlock bb) { bb = this or - strictlyDominates(bb) + this.strictlyDominates(bb) } /** @@ -140,14 +140,14 @@ class BasicBlock extends Cached::TBasicBlockStart { * does not dominate the basic block on line 6. */ predicate inDominanceFrontier(BasicBlock df) { - dominatesPredecessor(df) and - not strictlyDominates(df) + this.dominatesPredecessor(df) and + not this.strictlyDominates(df) } /** * Holds if this basic block dominates a predecessor of `df`. */ - private predicate dominatesPredecessor(BasicBlock df) { dominates(df.getAPredecessor()) } + private predicate dominatesPredecessor(BasicBlock df) { this.dominates(df.getAPredecessor()) } /** * Gets the basic block that immediately dominates this basic block, if any. @@ -226,7 +226,7 @@ class BasicBlock extends Cached::TBasicBlockStart { * post-dominates itself. */ predicate postDominates(BasicBlock bb) { - strictlyPostDominates(bb) or + this.strictlyPostDominates(bb) or this = bb } @@ -239,7 +239,7 @@ class BasicBlock extends Cached::TBasicBlockStart { predicate inLoop() { this.getASuccessor+() = this } /** Gets a textual representation of this basic block. */ - string toString() { result = getFirstNode().toString() } + string toString() { result = this.getFirstNode().toString() } /** Gets the location of this basic block. */ Location getLocation() { result = this.getFirstNode().getLocation() } @@ -325,16 +325,16 @@ private predicate exitBB(BasicBlock bb) { not exists(bb.getLastNode().getASucces * A basic block with more than one predecessor. */ class JoinBlock extends BasicBlock { - JoinBlock() { getFirstNode().isJoin() } + JoinBlock() { this.getFirstNode().isJoin() } } /** A basic block that terminates in a condition, splitting the subsequent control flow. */ class ConditionBlock extends BasicBlock { ConditionBlock() { exists(BasicBlock succ | - succ = getATrueSuccessor() + succ = this.getATrueSuccessor() or - succ = getAFalseSuccessor() + succ = this.getAFalseSuccessor() ) } @@ -380,16 +380,16 @@ class ConditionBlock extends BasicBlock { */ exists(BasicBlock succ | - isCandidateSuccessor(succ, testIsTrue) and + this.isCandidateSuccessor(succ, testIsTrue) and succ.dominates(controlled) ) } private predicate isCandidateSuccessor(BasicBlock succ, boolean testIsTrue) { ( - testIsTrue = true and succ = getATrueSuccessor() + testIsTrue = true and succ = this.getATrueSuccessor() or - testIsTrue = false and succ = getAFalseSuccessor() + testIsTrue = false and succ = this.getAFalseSuccessor() ) and forall(BasicBlock pred | pred = succ.getAPredecessor() and pred != this | succ.dominates(pred)) } diff --git a/csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll b/csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll index 02cfd149886..262bb58ab9c 100644 --- a/csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll +++ b/csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll @@ -62,7 +62,7 @@ abstract class InstructionViolation extends CfgViolation, CfgCheck { override string toString() { result = instruction.getImplementation().getMethod().toStringWithTypes() + ": " + - instruction.toString() + ", " + getInstructionsUpTo() + instruction.toString() + ", " + this.getInstructionsUpTo() } } @@ -126,7 +126,7 @@ class MissingOperand extends InstructionViolation { } override string getMessage() { - result = "This instruction is missing operand " + getMissingOperand() + result = "This instruction is missing operand " + this.getMissingOperand() } } @@ -364,7 +364,7 @@ class TypeViolation extends ConsistencyViolation, TypeCheck { /** Gets the type containing the violation. */ Type getType() { this = TypeCheck(result) } - override string toString() { result = getType().toString() } + override string toString() { result = this.getType().toString() } abstract override string getMessage(); } @@ -374,7 +374,7 @@ class TypeViolation extends ConsistencyViolation, TypeCheck { */ class TypeIsBothConstructedAndUnbound extends TypeViolation { TypeIsBothConstructedAndUnbound() { - getType() instanceof ConstructedGeneric and getType() instanceof UnboundGeneric + this.getType() instanceof ConstructedGeneric and this.getType() instanceof UnboundGeneric } override string getMessage() { result = "Type is both constructed and unbound" } @@ -397,16 +397,16 @@ class InconsistentTypeLocation extends TypeViolation { */ class TypeParameterMismatch extends TypeViolation { TypeParameterMismatch() { - getType().(ConstructedGeneric).getNumberOfTypeArguments() != - getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() + this.getType().(ConstructedGeneric).getNumberOfTypeArguments() != + this.getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() } override string getMessage() { result = - "Constructed type (" + getType().toStringWithTypes() + ") has " + - getType().(ConstructedGeneric).getNumberOfTypeArguments() + - " type arguments and unbound type (" + getType().getUnboundType().toStringWithTypes() + - ") has " + getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() + + "Constructed type (" + this.getType().toStringWithTypes() + ") has " + + this.getType().(ConstructedGeneric).getNumberOfTypeArguments() + + " type arguments and unbound type (" + this.getType().getUnboundType().toStringWithTypes() + + ") has " + this.getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() + " type parameters" } } @@ -418,7 +418,7 @@ class MethodViolation extends ConsistencyViolation, DeclarationCheck { /** Gets the method containing the violation. */ Method getMethod() { this = DeclarationCheck(result) } - override string toString() { result = getMethod().toString() } + override string toString() { result = this.getMethod().toString() } override string getMessage() { none() } } @@ -440,14 +440,15 @@ class InconsistentMethodLocation extends MethodViolation { */ class ConstructedMethodTypeParams extends MethodViolation { ConstructedMethodTypeParams() { - getMethod().(ConstructedGeneric).getNumberOfTypeArguments() != - getMethod().getUnboundDeclaration().(UnboundGeneric).getNumberOfTypeParameters() + this.getMethod().(ConstructedGeneric).getNumberOfTypeArguments() != + this.getMethod().getUnboundDeclaration().(UnboundGeneric).getNumberOfTypeParameters() } override string getMessage() { result = - "The constructed method " + getMethod().toStringWithTypes() + - " does not match unbound method " + getMethod().getUnboundDeclaration().toStringWithTypes() + "The constructed method " + this.getMethod().toStringWithTypes() + + " does not match unbound method " + + this.getMethod().getUnboundDeclaration().toStringWithTypes() } } @@ -477,8 +478,8 @@ class InvalidOverride extends MethodViolation { private Method base; InvalidOverride() { - base = getMethod().getOverriddenMethod() and - not getMethod().getDeclaringType().getABaseType+() = base.getDeclaringType() and + base = this.getMethod().getOverriddenMethod() and + not this.getMethod().getDeclaringType().getABaseType+() = base.getDeclaringType() and base.getDeclaringType().isUnboundDeclaration() // Bases classes of constructed types aren't extracted properly. } @@ -493,7 +494,9 @@ class InvalidOverride extends MethodViolation { * A pointer type that does not have a pointee type. */ class InvalidPointerType extends TypeViolation { - InvalidPointerType() { exists(PointerType p | p = getType() | count(p.getReferentType()) != 1) } + InvalidPointerType() { + exists(PointerType p | p = this.getType() | count(p.getReferentType()) != 1) + } override string getMessage() { result = "Invalid Pointertype.getPointeeType()" } } @@ -502,7 +505,9 @@ class InvalidPointerType extends TypeViolation { * An array with an invalid `getElementType`. */ class ArrayTypeMissingElement extends TypeViolation { - ArrayTypeMissingElement() { exists(ArrayType t | t = getType() | count(t.getElementType()) != 1) } + ArrayTypeMissingElement() { + exists(ArrayType t | t = this.getType() | count(t.getElementType()) != 1) + } override string getMessage() { result = "Invalid ArrayType.getElementType()" } } @@ -511,7 +516,7 @@ class ArrayTypeMissingElement extends TypeViolation { * An array with an invalid `getRank`. */ class ArrayTypeInvalidRank extends TypeViolation { - ArrayTypeInvalidRank() { exists(ArrayType t | t = getType() | not t.getRank() > 0) } + ArrayTypeInvalidRank() { exists(ArrayType t | t = this.getType() | not t.getRank() > 0) } override string getMessage() { result = "Invalid ArrayType.getRank()" } } @@ -564,7 +569,7 @@ abstract class DeclarationViolation extends ConsistencyViolation, DeclarationChe /** Gets the member containing the potential violation. */ Declaration getDeclaration() { this = DeclarationCheck(result) } - override string toString() { result = getDeclaration().toString() } + override string toString() { result = this.getDeclaration().toString() } } /** @@ -572,7 +577,7 @@ abstract class DeclarationViolation extends ConsistencyViolation, DeclarationChe */ class PropertyWithNoAccessors extends DeclarationViolation { PropertyWithNoAccessors() { - exists(Property p | p = getDeclaration() | not exists(p.getAnAccessor())) + exists(Property p | p = this.getDeclaration() | not exists(p.getAnAccessor())) } override string getMessage() { result = "Property has no accessors" } @@ -646,7 +651,7 @@ class TypeMultiplyDefined extends TypeViolation, DisabledCheck { override string getMessage() { result = - "This type (" + getType().toStringWithTypes() + ") has " + + "This type (" + this.getType().toStringWithTypes() + ") has " + count(Type t | not t instanceof ConstructedGeneric and t.toStringWithTypes() = this.getType().toStringWithTypes() @@ -669,11 +674,11 @@ class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck { override string getMessage() { result = - "Cannot locate CIL for " + getDeclaration().toStringWithTypes() + " of class " + - getDeclaration().getPrimaryQlClasses() + "Cannot locate CIL for " + this.getDeclaration().toStringWithTypes() + " of class " + + this.getDeclaration().getPrimaryQlClasses() } - override string toString() { result = getDeclaration().toStringWithTypes() } + override string toString() { result = this.getDeclaration().toStringWithTypes() } } /** @@ -717,21 +722,23 @@ private predicate expectedCilDeclaration(CS::Declaration decl) { /** A member with an invalid name. */ class MemberWithInvalidName extends DeclarationViolation { MemberWithInvalidName() { - exists(string name | name = getDeclaration().(Member).getName() | + exists(string name | name = this.getDeclaration().(Member).getName() | exists(name.indexOf(".")) and not name = ".ctor" and not name = ".cctor" ) } - override string getMessage() { result = "Invalid name " + getDeclaration().(Member).getName() } + override string getMessage() { + result = "Invalid name " + this.getDeclaration().(Member).getName() + } } class ConstructedSourceDeclarationMethod extends MethodViolation { Method method; ConstructedSourceDeclarationMethod() { - method = getMethod() and + method = this.getMethod() and method = method.getUnboundDeclaration() and ( method instanceof ConstructedGeneric or @@ -751,7 +758,7 @@ class DeclarationWithMultipleLabels extends DeclarationViolation { } override string getMessage() { - result = "Multiple labels " + concat(getDeclaration().getLabel(), ", ") + result = "Multiple labels " + concat(this.getDeclaration().getLabel(), ", ") } } diff --git a/csharp/ql/lib/semmle/code/cil/ControlFlow.qll b/csharp/ql/lib/semmle/code/cil/ControlFlow.qll index 52a2ddc3376..8b6d6c70a05 100644 --- a/csharp/ql/lib/semmle/code/cil/ControlFlow.qll +++ b/csharp/ql/lib/semmle/code/cil/ControlFlow.qll @@ -23,13 +23,13 @@ class ControlFlowNode extends @cil_controlflow_node { int getPopCount() { result = 0 } /** Gets a successor of this node, if any. */ - final Instruction getASuccessor() { result = getASuccessorType(_) } + final Instruction getASuccessor() { result = this.getASuccessorType(_) } /** Gets a true successor of this node, if any. */ - final Instruction getTrueSuccessor() { result = getASuccessorType(any(TrueFlow f)) } + final Instruction getTrueSuccessor() { result = this.getASuccessorType(any(TrueFlow f)) } /** Gets a false successor of this node, if any. */ - final Instruction getFalseSuccessor() { result = getASuccessorType(any(FalseFlow f)) } + final Instruction getFalseSuccessor() { result = this.getASuccessorType(any(FalseFlow f)) } /** Gets a successor to this node, of type `type`, if any. */ cached @@ -57,7 +57,7 @@ class ControlFlowNode extends @cil_controlflow_node { } /** Gets an operand of this instruction, if any. */ - ControlFlowNode getAnOperand() { result = getOperand(_) } + ControlFlowNode getAnOperand() { result = this.getOperand(_) } /** Gets an expression that consumes the output of this instruction on the stack. */ Instruction getParentExpr() { this = result.getAnOperand() } @@ -86,17 +86,17 @@ class ControlFlowNode extends @cil_controlflow_node { ) } - private int getStackDelta() { result = getPushCount() - getPopCount() } + private int getStackDelta() { result = this.getPushCount() - this.getPopCount() } /** Gets the stack size before this instruction. */ - int getStackSizeBefore() { result = getAPredecessor().getStackSizeAfter() } + int getStackSizeBefore() { result = this.getAPredecessor().getStackSizeAfter() } /** Gets the stack size after this instruction. */ final int getStackSizeAfter() { // This is a guard to prevent ill formed programs // and other logic errors going into an infinite loop. - result in [0 .. getImplementation().getStackSize()] and - result = getStackSizeBefore() + getStackDelta() + result in [0 .. this.getImplementation().getStackSize()] and + result = this.getStackSizeBefore() + this.getStackDelta() } /** Gets the method containing this control flow node. */ diff --git a/csharp/ql/lib/semmle/code/cil/Declaration.qll b/csharp/ql/lib/semmle/code/cil/Declaration.qll index a747d4a6d80..178b5c9966e 100644 --- a/csharp/ql/lib/semmle/code/cil/Declaration.qll +++ b/csharp/ql/lib/semmle/code/cil/Declaration.qll @@ -68,7 +68,7 @@ class Member extends DotNet::Member, Declaration, @cil_member { /** Holds if this member has a security attribute. */ predicate hasSecurity() { cil_security(this) } - override Location getLocation() { result = getDeclaringType().getLocation() } + override Location getLocation() { result = this.getDeclaringType().getLocation() } } /** A property. */ @@ -87,24 +87,25 @@ class Property extends DotNet::Property, Member, CustomModifierReceiver, @cil_pr override Setter getSetter() { this = result.getProperty() } /** Gets an accessor of this property. */ - Accessor getAnAccessor() { result = getGetter() or result = getSetter() } + Accessor getAnAccessor() { result = this.getGetter() or result = this.getSetter() } - override string toString() { result = "property " + getName() } + override string toString() { result = "property " + this.getName() } override string toStringWithTypes() { result = - getType().toStringWithTypes() + " " + getDeclaringType().toStringWithTypes() + "." + getName() + this.getType().toStringWithTypes() + " " + this.getDeclaringType().toStringWithTypes() + "." + + this.getName() } } /** A property that is trivial (wraps a field). */ class TrivialProperty extends Property { TrivialProperty() { - getGetter().(TrivialGetter).getField() = getSetter().(TrivialSetter).getField() + this.getGetter().(TrivialGetter).getField() = this.getSetter().(TrivialSetter).getField() } /** Gets the underlying field of this property. */ - Field getField() { result = getGetter().(TrivialGetter).getField() } + Field getField() { result = this.getGetter().(TrivialGetter).getField() } } /** An event. */ @@ -125,9 +126,9 @@ class Event extends DotNet::Event, Member, @cil_event { /** Gets the raiser. */ Method getRaiser() { cil_raiser(this, result) } - override string toString() { result = "event " + getName() } + override string toString() { result = "event " + this.getName() } override string toStringWithTypes() { - result = getDeclaringType().toStringWithTypes() + "." + getName() + result = this.getDeclaringType().toStringWithTypes() + "." + this.getName() } } diff --git a/csharp/ql/lib/semmle/code/cil/Generics.qll b/csharp/ql/lib/semmle/code/cil/Generics.qll index a742a142cc4..2e702e68ffe 100644 --- a/csharp/ql/lib/semmle/code/cil/Generics.qll +++ b/csharp/ql/lib/semmle/code/cil/Generics.qll @@ -45,5 +45,5 @@ class ConstructedType extends ConstructedGeneric, Type { /** A constructed generic method. */ class ConstructedMethod extends ConstructedGeneric, Method { - final override UnboundGenericMethod getUnboundGeneric() { result = getUnboundMethod() } + final override UnboundGenericMethod getUnboundGeneric() { result = this.getUnboundMethod() } } diff --git a/csharp/ql/lib/semmle/code/cil/Instruction.qll b/csharp/ql/lib/semmle/code/cil/Instruction.qll index 3e620031264..fa9753e1f0c 100644 --- a/csharp/ql/lib/semmle/code/cil/Instruction.qll +++ b/csharp/ql/lib/semmle/code/cil/Instruction.qll @@ -4,15 +4,17 @@ private import CIL /** An instruction. */ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instruction { - override string toString() { result = getOpcodeName() } + override string toString() { result = this.getOpcodeName() } /** Gets a more verbose textual representation of this instruction. */ - string toStringExtra() { result = getIndex() + ": " + getOpcodeName() + getExtraStr() } + string toStringExtra() { + result = this.getIndex() + ": " + this.getOpcodeName() + this.getExtraStr() + } /** Gets the method containing this instruction. */ override MethodImplementation getImplementation() { cil_instruction(this, _, _, result) } - override Method getMethod() { result = getImplementation().getMethod() } + override Method getMethod() { result = this.getImplementation().getMethod() } /** * Gets the index of this instruction. @@ -30,7 +32,7 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi string getExtra() { none() } private string getExtraStr() { - if exists(getExtra()) then result = " " + getExtra() else result = "" + if exists(this.getExtra()) then result = " " + this.getExtra() else result = "" } /** Gets the declaration accessed by this instruction, if any. */ @@ -39,8 +41,8 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi /** Gets a successor instruction to this instruction. */ override Instruction getASuccessorType(FlowType t) { t instanceof NormalFlow and - canFlowNext() and - result = this.getImplementation().getInstruction(getIndex() + 1) + this.canFlowNext() and + result = this.getImplementation().getInstruction(this.getIndex() + 1) } /** Holds if this instruction passes control flow into the next instruction. */ @@ -61,7 +63,7 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi override Location getALocation() { cil_instruction_location(this, result) // The source code, if available or - result = getImplementation().getLocation() // The containing assembly + result = this.getImplementation().getLocation() // The containing assembly } override Location getLocation() { result = Element.super.getLocation() } diff --git a/csharp/ql/lib/semmle/code/cil/InstructionGroups.qll b/csharp/ql/lib/semmle/code/cil/InstructionGroups.qll index e4aeb05a839..5dac4bf7291 100644 --- a/csharp/ql/lib/semmle/code/cil/InstructionGroups.qll +++ b/csharp/ql/lib/semmle/code/cil/InstructionGroups.qll @@ -14,7 +14,7 @@ class Expr extends DotNet::Expr, Instruction, @cil_expr { override Type getType() { result = Instruction.super.getType() } - override Method getEnclosingCallable() { result = getImplementation().getMethod() } + override Method getEnclosingCallable() { result = this.getImplementation().getMethod() } /** * The "parent" of a CIL expression is taken to be the instruction @@ -28,13 +28,13 @@ class Branch extends Instruction, @cil_jump { /** Gets the instruction that is jumped to. */ Instruction getTarget() { cil_jump(this, result) } - override string getExtra() { result = getTarget().getIndex() + ":" } + override string getExtra() { result = this.getTarget().getIndex() + ":" } } /** An instruction that unconditionally jumps to another instruction. */ class UnconditionalBranch extends Branch, @cil_unconditional_jump { override Instruction getASuccessorType(FlowType t) { - t instanceof NormalFlow and result = getTarget() + t instanceof NormalFlow and result = this.getTarget() } override predicate canFlowNext() { none() } @@ -43,9 +43,9 @@ class UnconditionalBranch extends Branch, @cil_unconditional_jump { /** An instruction that jumps to a target based on a condition. */ class ConditionalBranch extends Branch, @cil_conditional_jump { override Instruction getASuccessorType(FlowType t) { - t instanceof TrueFlow and result = getTarget() + t instanceof TrueFlow and result = this.getTarget() or - t instanceof FalseFlow and result = getImplementation().getInstruction(getIndex() + 1) + t instanceof FalseFlow and result = this.getImplementation().getInstruction(this.getIndex() + 1) } override int getPushCount() { result = 0 } @@ -61,7 +61,7 @@ class UnaryExpr extends Expr, @cil_unary_expr { override int getPopCount() { result = 1 } /** Gets the operand of this unary expression. */ - Expr getOperand() { result = getOperand(0) } + Expr getOperand() { result = this.getOperand(0) } } /** A binary expression that compares two values. */ @@ -73,8 +73,8 @@ class ComparisonOperation extends BinaryExpr, @cil_comparison_operation { class BinaryArithmeticExpr extends BinaryExpr, @cil_binary_arithmetic_operation { override Type getType() { exists(Type t0, Type t1 | - t0 = getOperand(0).getType().getUnderlyingType() and - t1 = getOperand(1).getType().getUnderlyingType() + t0 = this.getOperand(0).getType().getUnderlyingType() and + t1 = this.getOperand(1).getType().getUnderlyingType() | t0 = t1 and result = t0 or @@ -100,7 +100,7 @@ class UnaryBitwiseOperation extends UnaryExpr, @cil_unary_bitwise_operation { /** A unary expression that converts a value from one primitive type to another. */ class Conversion extends UnaryExpr, @cil_conversion_operation { /** Gets the expression being converted. */ - Expr getExpr() { result = getOperand(0) } + Expr getExpr() { result = this.getOperand(0) } } /** A branch that leaves the scope of a `Handler`. */ @@ -111,7 +111,7 @@ class Literal extends DotNet::Literal, Expr, @cil_literal { /** Gets the pushed value. */ override string getValue() { cil_value(this, result) } - override string getExtra() { result = getValue() } + override string getExtra() { result = this.getValue() } } /** An integer literal. */ @@ -149,44 +149,44 @@ class Call extends Expr, DotNet::Call, @cil_call_any { /** Gets the method that is called. */ override Method getTarget() { cil_access(this, result) } - override Method getARuntimeTarget() { result = getTarget().getAnOverrider*() } + override Method getARuntimeTarget() { result = this.getTarget().getAnOverrider*() } - override string getExtra() { result = getTarget().getQualifiedName() } + override string getExtra() { result = this.getTarget().getQualifiedName() } /** * Gets the return type of the call. Methods that do not return a value * return the `void` type, `System.Void`, although the value of `getPushCount` is * 0 in this case. */ - override Type getType() { result = getTarget().getReturnType() } + override Type getType() { result = this.getTarget().getReturnType() } // The number of items popped/pushed from the stack // depends on the target of the call. - override int getPopCount() { result = getTarget().getCallPopCount() } + override int getPopCount() { result = this.getTarget().getCallPopCount() } - override int getPushCount() { result = getTarget().getCallPushCount() } + override int getPushCount() { result = this.getTarget().getCallPushCount() } /** * Holds if this is a "tail call", meaning that control does not return to the * calling method. */ predicate isTailCall() { - getImplementation().getInstruction(getIndex() - 1) instanceof Opcodes::Tail + this.getImplementation().getInstruction(this.getIndex() - 1) instanceof Opcodes::Tail } /** Holds if this call is virtual and could go to an overriding method. */ predicate isVirtual() { none() } - override Expr getRawArgument(int i) { result = getOperand(getPopCount() - i - 1) } + override Expr getRawArgument(int i) { result = this.getOperand(this.getPopCount() - i - 1) } /** Gets the qualifier of this call, if any. */ - Expr getQualifier() { result = getRawArgument(0) and not getTarget().isStatic() } + Expr getQualifier() { result = this.getRawArgument(0) and not this.getTarget().isStatic() } override Expr getArgument(int i) { - if getTarget().isStatic() - then result = getRawArgument(i) + if this.getTarget().isStatic() + then result = this.getRawArgument(i) else ( - result = getRawArgument(i + 1) and i >= 0 + result = this.getRawArgument(i + 1) and i >= 0 ) } @@ -217,10 +217,10 @@ class VirtualCall extends Call { /** A read of an array element. */ class ReadArrayElement extends BinaryExpr, @cil_read_array { /** Gets the array being read. */ - Expr getArray() { result = getOperand(1) } + Expr getArray() { result = this.getOperand(1) } /** Gets the index into the array. */ - Expr getArrayIndex() { result = getOperand(0) } + Expr getArrayIndex() { result = this.getOperand(0) } } /** A write of an array element. */ @@ -233,14 +233,14 @@ class WriteArrayElement extends Instruction, @cil_write_array { /** A `return` statement. */ class Return extends Instruction, @cil_ret { /** Gets the expression being returned, if any. */ - Expr getExpr() { result = getOperand(0) } + Expr getExpr() { result = this.getOperand(0) } override predicate canFlowNext() { none() } } /** A `throw` statement. */ class Throw extends Instruction, DotNet::Throw, @cil_throw_any { - override Expr getExpr() { result = getOperand(0) } + override Expr getExpr() { result = this.getOperand(0) } override predicate canFlowNext() { none() } } @@ -250,10 +250,10 @@ class StoreIndirect extends Instruction, @cil_stind { override int getPopCount() { result = 2 } /** Gets the location to store the value at. */ - Expr getAddress() { result = getOperand(1) } + Expr getAddress() { result = this.getOperand(1) } /** Gets the value to store. */ - Expr getExpr() { result = getOperand(0) } + Expr getExpr() { result = this.getOperand(0) } } /** Loads a value from an address/location. */ diff --git a/csharp/ql/lib/semmle/code/cil/Instructions.qll b/csharp/ql/lib/semmle/code/cil/Instructions.qll index e385ceced31..5752ae45b20 100644 --- a/csharp/ql/lib/semmle/code/cil/Instructions.qll +++ b/csharp/ql/lib/semmle/code/cil/Instructions.qll @@ -83,21 +83,21 @@ module Opcodes { class Ldc_i4 extends IntLiteral, @cil_ldc_i4 { override string getOpcodeName() { result = "ldc.i4" } - override string getExtra() { result = getValue() } + override string getExtra() { result = this.getValue() } } /** An `ldc.i8` instruction. */ class Ldc_i8 extends IntLiteral, @cil_ldc_i8 { override string getOpcodeName() { result = "ldc.i8" } - override string getExtra() { result = getValue() } + override string getExtra() { result = this.getValue() } } /** An `ldc.i4.s` instruction. */ class Ldc_i4_s extends IntLiteral, @cil_ldc_i4_s { override string getOpcodeName() { result = "ldc.i4.s" } - override string getExtra() { result = getValue() } + override string getExtra() { result = this.getValue() } } /** An `ldnull` instruction. */ @@ -115,7 +115,7 @@ module Opcodes { class Ldc_r4 extends FloatLiteral, @cil_ldc_r4 { override string getOpcodeName() { result = "ldc.r4" } - override string getExtra() { result = getValue() } + override string getExtra() { result = this.getValue() } override Type getType() { result instanceof FloatType } } @@ -124,7 +124,7 @@ module Opcodes { class Ldc_r8 extends FloatLiteral, @cil_ldc_r8 { override string getOpcodeName() { result = "ldc.r8" } - override string getExtra() { result = getValue() } + override string getExtra() { result = this.getValue() } override Type getType() { result instanceof DoubleType } } @@ -199,9 +199,9 @@ module Opcodes { override string getOpcodeName() { result = "neg" } override NumericType getType() { - result = getOperand().getType() + result = this.getOperand().getType() or - getOperand().getType() instanceof Enum and result instanceof IntType + this.getOperand().getType() instanceof Enum and result instanceof IntType } } @@ -260,7 +260,7 @@ module Opcodes { override int getPushCount() { result = 2 } // This is the only instruction that pushes 2 items - override Type getType() { result = getOperand(0).getType() } + override Type getType() { result = this.getOperand(0).getType() } } /** A `ret` instruction. */ @@ -270,7 +270,7 @@ module Opcodes { override predicate canFlowNext() { none() } override int getPopCount() { - if getImplementation().getMethod().returnsVoid() then result = 0 else result = 1 + if this.getImplementation().getMethod().returnsVoid() then result = 0 else result = 1 } } @@ -283,7 +283,7 @@ module Opcodes { class Ldstr extends StringLiteral, @cil_ldstr { override string getOpcodeName() { result = "ldstr" } - override string getExtra() { result = "\"" + getValue() + "\"" } + override string getExtra() { result = "\"" + this.getValue() + "\"" } override Type getType() { result instanceof StringType } } @@ -427,11 +427,14 @@ module Opcodes { override Instruction getASuccessorType(FlowType t) { t instanceof NormalFlow and - (result = getTarget(_) or result = getImplementation().getInstruction(getIndex() + 1)) + ( + result = this.getTarget(_) or + result = this.getImplementation().getInstruction(this.getIndex() + 1) + ) } override string getExtra() { - result = concat(int n | exists(getTarget(n)) | getTarget(n).getIndex() + ":", " ") + result = concat(int n | exists(this.getTarget(n)) | this.getTarget(n).getIndex() + ":", " ") } } @@ -493,9 +496,9 @@ module Opcodes { // The number of items popped/pushed from the stack depends on the target of // the call. Also, we need to pop the function pointer itself too. - override int getPopCount() { result = getTargetType().getCallPopCount() + 1 } + override int getPopCount() { result = this.getTargetType().getCallPopCount() + 1 } - override int getPushCount() { result = getTargetType().getCallPushCount() } + override int getPushCount() { result = this.getTargetType().getCallPushCount() } } /** A `callvirt` instruction. */ @@ -524,49 +527,49 @@ module Opcodes { override BoolType getType() { exists(result) } /** Gets the type that is being tested against. */ - Type getTestedType() { result = getAccess() } + Type getTestedType() { result = this.getAccess() } - override string getExtra() { result = getTestedType().getQualifiedName() } + override string getExtra() { result = this.getTestedType().getQualifiedName() } } /** A `castclass` instruction. */ class Castclass extends UnaryExpr, @cil_castclass { override string getOpcodeName() { result = "castclass" } - override Type getType() { result = getAccess() } + override Type getType() { result = this.getAccess() } /** Gets the type that is being cast to. */ - Type getTestedType() { result = getAccess() } + Type getTestedType() { result = this.getAccess() } - override string getExtra() { result = getTestedType().getQualifiedName() } + override string getExtra() { result = this.getTestedType().getQualifiedName() } } /** An `stloc.0` instruction. */ class Stloc_0 extends LocalVariableWriteAccess, @cil_stloc_0 { override string getOpcodeName() { result = "stloc.0" } - override LocalVariable getTarget() { result = getImplementation().getLocalVariable(0) } + override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(0) } } /** An `stloc.1` instruction. */ class Stloc_1 extends LocalVariableWriteAccess, @cil_stloc_1 { override string getOpcodeName() { result = "stloc.1" } - override LocalVariable getTarget() { result = getImplementation().getLocalVariable(1) } + override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(1) } } /** An `stloc.2` instruction. */ class Stloc_2 extends LocalVariableWriteAccess, @cil_stloc_2 { override string getOpcodeName() { result = "stloc.2" } - override LocalVariable getTarget() { result = getImplementation().getLocalVariable(2) } + override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(2) } } /** An `stloc.3` instruction. */ class Stloc_3 extends LocalVariableWriteAccess, @cil_stloc_3 { override string getOpcodeName() { result = "stloc.3" } - override LocalVariable getTarget() { result = getImplementation().getLocalVariable(3) } + override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(3) } } /** An `stloc.s` instruction. */ @@ -587,28 +590,28 @@ module Opcodes { class Ldloc_0 extends LocalVariableReadAccess, @cil_ldloc_0 { override string getOpcodeName() { result = "ldloc.0" } - override LocalVariable getTarget() { result = getImplementation().getLocalVariable(0) } + override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(0) } } /** An `ldloc.1` instruction. */ class Ldloc_1 extends LocalVariableReadAccess, @cil_ldloc_1 { override string getOpcodeName() { result = "ldloc.1" } - override LocalVariable getTarget() { result = getImplementation().getLocalVariable(1) } + override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(1) } } /** An `ldloc.2` instruction. */ class Ldloc_2 extends LocalVariableReadAccess, @cil_ldloc_2 { override string getOpcodeName() { result = "ldloc.2" } - override LocalVariable getTarget() { result = getImplementation().getLocalVariable(2) } + override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(2) } } /** An `ldloc.3` instruction. */ class Ldloc_3 extends LocalVariableReadAccess, @cil_ldloc_3 { override string getOpcodeName() { result = "ldloc.3" } - override LocalVariable getTarget() { result = getImplementation().getLocalVariable(3) } + override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(3) } } /** An `ldloc.s` instruction. */ @@ -617,7 +620,7 @@ module Opcodes { override LocalVariable getTarget() { cil_access(this, result) } - override string getExtra() { result = "L" + getTarget().getIndex() } + override string getExtra() { result = "L" + this.getTarget().getIndex() } } /** An `ldloca.s` instruction. */ @@ -626,7 +629,7 @@ module Opcodes { override LocalVariable getTarget() { cil_access(this, result) } - override string getExtra() { result = "L" + getTarget().getIndex() } + override string getExtra() { result = "L" + this.getTarget().getIndex() } } /** An `ldloc` instruction. */ @@ -635,7 +638,7 @@ module Opcodes { override LocalVariable getTarget() { cil_access(this, result) } - override string getExtra() { result = "L" + getTarget().getIndex() } + override string getExtra() { result = "L" + this.getTarget().getIndex() } } /** An `ldarg.0` instruction. */ @@ -643,7 +646,7 @@ module Opcodes { override string getOpcodeName() { result = "ldarg.0" } override MethodParameter getTarget() { - result = getImplementation().getMethod().getRawParameter(0) + result = this.getImplementation().getMethod().getRawParameter(0) } } @@ -652,7 +655,7 @@ module Opcodes { override string getOpcodeName() { result = "ldarg.1" } override MethodParameter getTarget() { - result = getImplementation().getMethod().getRawParameter(1) + result = this.getImplementation().getMethod().getRawParameter(1) } } @@ -661,7 +664,7 @@ module Opcodes { override string getOpcodeName() { result = "ldarg.2" } override MethodParameter getTarget() { - result = getImplementation().getMethod().getRawParameter(2) + result = this.getImplementation().getMethod().getRawParameter(2) } } @@ -670,7 +673,7 @@ module Opcodes { override string getOpcodeName() { result = "ldarg.3" } override MethodParameter getTarget() { - result = getImplementation().getMethod().getRawParameter(3) + result = this.getImplementation().getMethod().getRawParameter(3) } } @@ -710,7 +713,7 @@ module Opcodes { override int getPopCount() { result = 1 } - override Expr getQualifier() { result = getOperand(0) } + override Expr getQualifier() { result = this.getOperand(0) } } /** An `ldflda` instruction. */ @@ -719,7 +722,7 @@ module Opcodes { override int getPopCount() { result = 1 } - override Expr getQualifier() { result = getOperand(0) } + override Expr getQualifier() { result = this.getOperand(0) } } /** An `ldsfld` instruction. */ @@ -746,9 +749,9 @@ module Opcodes { override int getPopCount() { result = 2 } - override Expr getQualifier() { result = getOperand(1) } + override Expr getQualifier() { result = this.getOperand(1) } - override Expr getExpr() { result = getOperand(0) } + override Expr getExpr() { result = this.getOperand(0) } } /** An `stsfld` instruction. */ @@ -759,7 +762,7 @@ module Opcodes { override Expr getQualifier() { none() } - override Expr getExpr() { result = getOperand(0) } + override Expr getExpr() { result = this.getOperand(0) } } /** A `newobj` instruction. */ @@ -772,7 +775,7 @@ module Opcodes { override Type getType() { result = this.getTarget().getDeclaringType() } - override Expr getArgument(int i) { result = getRawArgument(i) } + override Expr getArgument(int i) { result = this.getRawArgument(i) } pragma[noinline] private Parameter getARawTargetParameter() { result = this.getTarget().getARawParameter() } @@ -796,21 +799,21 @@ module Opcodes { class Box extends UnaryExpr, @cil_box { override string getOpcodeName() { result = "box" } - override Type getType() { result = getAccess() } + override Type getType() { result = this.getAccess() } } /** An `unbox.any` instruction. */ class Unbox_any extends UnaryExpr, @cil_unbox_any { override string getOpcodeName() { result = "unbox.any" } - override Type getType() { result = getAccess() } + override Type getType() { result = this.getAccess() } } /** An `unbox` instruction. */ class Unbox extends UnaryExpr, @cil_unbox { override string getOpcodeName() { result = "unbox" } - override Type getType() { result = getAccess() } + override Type getType() { result = this.getAccess() } } /** An `ldobj` instruction. */ @@ -820,7 +823,7 @@ module Opcodes { /** Gets the type of the object. */ Type getTarget() { cil_access(this, result) } - override Type getType() { result = getAccess() } + override Type getType() { result = this.getAccess() } } /** An `ldtoken` instruction. */ @@ -867,31 +870,31 @@ module Opcodes { // Note that this is technically wrong - it should be // result.(ArrayType).getElementType() = getAccess() // However the (ArrayType) may not be in the database. - result = getAccess() + result = this.getAccess() } - override string getExtra() { result = getType().getQualifiedName() } + override string getExtra() { result = this.getType().getQualifiedName() } } /** An `ldelem` instruction. */ class Ldelem extends ReadArrayElement, @cil_ldelem { override string getOpcodeName() { result = "ldelem" } - override Type getType() { result = getAccess() } + override Type getType() { result = this.getAccess() } } /** An `ldelem.ref` instruction. */ class Ldelem_ref extends ReadArrayElement, @cil_ldelem_ref { override string getOpcodeName() { result = "ldelem.ref" } - override Type getType() { result = getArray().getType() } + override Type getType() { result = this.getArray().getType() } } /** An `ldelema` instruction. */ class Ldelema extends ReadArrayElement, ReadRef, @cil_ldelema { override string getOpcodeName() { result = "ldelema" } - override Type getType() { result = getAccess() } + override Type getType() { result = this.getAccess() } } /** An `stelem.ref` instruction. */ @@ -1410,7 +1413,7 @@ module Opcodes { override int getPopCount() { result = 1 } - override Type getType() { result = getAccess() } + override Type getType() { result = this.getAccess() } } /** A `refanytype` instruction. */ diff --git a/csharp/ql/lib/semmle/code/cil/Method.qll b/csharp/ql/lib/semmle/code/cil/Method.qll index 82bde17a477..461a020972b 100644 --- a/csharp/ql/lib/semmle/code/cil/Method.qll +++ b/csharp/ql/lib/semmle/code/cil/Method.qll @@ -28,13 +28,13 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation { LocalVariable getLocalVariable(int n) { cil_local_variable(result, this, n, _) } /** Gets a local variable of this implementation, if any. */ - LocalVariable getALocalVariable() { result = getLocalVariable(_) } + LocalVariable getALocalVariable() { result = this.getLocalVariable(_) } /** Gets an instruction in this implementation, if any. */ - Instruction getAnInstruction() { result = getInstruction(_) } + Instruction getAnInstruction() { result = this.getInstruction(_) } /** Gets the total number of instructions in this implementation. */ - int getNumberOfInstructions() { result = count(getAnInstruction()) } + int getNumberOfInstructions() { result = count(this.getAnInstruction()) } /** Gets the `i`th handler in this implementation. */ Handler getHandler(int i) { result.getImplementation() = this and result.getIndex() = i } @@ -49,7 +49,7 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation { /** Gets the maximum stack size of this implementation. */ int getStackSize() { cil_method_stack_size(this, result) } - override string toString() { result = getMethod().toString() } + override string toString() { result = this.getMethod().toString() } /** Gets a string representing the disassembly of this implementation. */ string getDisassembly() { @@ -75,13 +75,13 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN MethodImplementation getAnImplementation() { result.getMethod() = this } /** Gets the "best" implementation of this method, if any. */ - BestImplementation getImplementation() { result = getAnImplementation() } + BestImplementation getImplementation() { result = this.getAnImplementation() } override Method getMethod() { result = this } override string getName() { cil_method(this, result, _, _) } - override string getUndecoratedName() { result = getName() } + override string getUndecoratedName() { result = this.getName() } override string toString() { result = this.getName() } @@ -92,25 +92,29 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN override Location getALocation() { cil_method_location(this.getUnboundDeclaration(), result) } override MethodParameter getParameter(int n) { - if isStatic() then result = getRawParameter(n) else (result = getRawParameter(n + 1) and n >= 0) + if this.isStatic() + then result = this.getRawParameter(n) + else ( + result = this.getRawParameter(n + 1) and n >= 0 + ) } - override Type getType() { result = getReturnType() } + override Type getType() { result = this.getReturnType() } /** Gets the return type of this method. */ override Type getReturnType() { cil_method(this, _, _, result) } /** Holds if the return type is `void`. */ - predicate returnsVoid() { getReturnType() instanceof VoidType } + predicate returnsVoid() { this.getReturnType() instanceof VoidType } /** Gets the number of stack items pushed in a call to this method. */ - int getCallPushCount() { if returnsVoid() then result = 0 else result = 1 } + int getCallPushCount() { if this.returnsVoid() then result = 0 else result = 1 } /** Gets the number of stack items popped in a call to this method. */ - int getCallPopCount() { result = count(getRawParameter(_)) } + int getCallPopCount() { result = count(this.getRawParameter(_)) } /** Gets a method called by this method. */ - Method getACallee() { result = getImplementation().getAnInstruction().(Call).getTarget() } + Method getACallee() { result = this.getImplementation().getAnInstruction().(Call).getTarget() } /** Holds if this method is `virtual`. */ predicate isVirtual() { cil_virtual(this) } @@ -129,43 +133,45 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN /** Gets the unbound declaration of this method, or the method itself. */ Method getUnboundMethod() { cil_method_source_declaration(this, result) } - override Method getUnboundDeclaration() { result = getUnboundMethod() } + override Method getUnboundDeclaration() { result = this.getUnboundMethod() } /** Holds if this method is an instance constructor. */ - predicate isInstanceConstructor() { isSpecial() and getName() = ".ctor" } + predicate isInstanceConstructor() { this.isSpecial() and this.getName() = ".ctor" } /** Holds if this method is a static class constructor. */ - predicate isStaticConstructor() { isSpecial() and getName() = ".cctor" } + predicate isStaticConstructor() { this.isSpecial() and this.getName() = ".cctor" } /** Holds if this method is a constructor (static or instance). */ - predicate isConstructor() { isStaticConstructor() or isInstanceConstructor() } + predicate isConstructor() { this.isStaticConstructor() or this.isInstanceConstructor() } /** Holds if this method is a destructor/finalizer. */ - predicate isFinalizer() { getOverriddenMethod*().getQualifiedName() = "System.Object.Finalize" } + predicate isFinalizer() { + this.getOverriddenMethod*().getQualifiedName() = "System.Object.Finalize" + } /** Holds if this method is an operator. */ - predicate isOperator() { isSpecial() and getName().matches("op\\_%") } + predicate isOperator() { this.isSpecial() and this.getName().matches("op\\_%") } /** Holds if this method is a getter. */ - predicate isGetter() { isSpecial() and getName().matches("get\\_%") } + predicate isGetter() { this.isSpecial() and this.getName().matches("get\\_%") } /** Holds if this method is a setter. */ - predicate isSetter() { isSpecial() and getName().matches("set\\_%") } + predicate isSetter() { this.isSpecial() and this.getName().matches("set\\_%") } /** Holds if this method is an adder/add event accessor. */ - predicate isAdder() { isSpecial() and getName().matches("add\\_%") } + predicate isAdder() { this.isSpecial() and this.getName().matches("add\\_%") } /** Holds if this method is a remover/remove event accessor. */ - predicate isRemove() { isSpecial() and getName().matches("remove\\_%") } + predicate isRemove() { this.isSpecial() and this.getName().matches("remove\\_%") } /** Holds if this method is an implicit conversion operator. */ - predicate isImplicitConversion() { isSpecial() and getName() = "op_Implicit" } + predicate isImplicitConversion() { this.isSpecial() and this.getName() = "op_Implicit" } /** Holds if this method is an explicit conversion operator. */ - predicate isExplicitConversion() { isSpecial() and getName() = "op_Explicit" } + predicate isExplicitConversion() { this.isSpecial() and this.getName() = "op_Explicit" } /** Holds if this method is a conversion operator. */ - predicate isConversion() { isImplicitConversion() or isExplicitConversion() } + predicate isConversion() { this.isImplicitConversion() or this.isExplicitConversion() } /** * Gets a method that is overridden, either in a base class @@ -176,7 +182,7 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN /** Gets a method that overrides this method, if any. */ final Method getAnOverrider() { result.getOverriddenMethod() = this } - override predicate hasBody() { exists(getImplementation()) } + override predicate hasBody() { exists(this.getImplementation()) } override predicate canReturn(DotNet::Expr expr) { exists(Return ret | ret.getImplementation() = this.getImplementation() and expr = ret.getExpr()) @@ -206,7 +212,7 @@ class InstanceConstructor extends Constructor { /** A method that always returns the `this` parameter. */ class ChainingMethod extends Method { ChainingMethod() { - forex(Return ret | ret = getImplementation().getAnInstruction() | + forex(Return ret | ret = this.getImplementation().getAnInstruction() | ret.getExpr() instanceof ThisAccess ) } @@ -231,7 +237,7 @@ class Getter extends Accessor { */ class TrivialGetter extends Method { TrivialGetter() { - exists(MethodImplementation impl | impl = getAnImplementation() | + exists(MethodImplementation impl | impl = this.getAnImplementation() | impl.getInstruction(0) instanceof ThisAccess and impl.getInstruction(1) instanceof FieldReadAccess and impl.getInstruction(2) instanceof Return @@ -239,7 +245,9 @@ class TrivialGetter extends Method { } /** Gets the underlying field of this getter. */ - Field getField() { getImplementation().getAnInstruction().(FieldReadAccess).getTarget() = result } + Field getField() { + this.getImplementation().getAnInstruction().(FieldReadAccess).getTarget() = result + } } /** A setter. */ @@ -262,7 +270,7 @@ class Setter extends Accessor { */ class TrivialSetter extends Method { TrivialSetter() { - exists(MethodImplementation impl | impl = getImplementation() | + exists(MethodImplementation impl | impl = this.getImplementation() | impl.getInstruction(0) instanceof ThisAccess and impl.getInstruction(1).(ParameterReadAccess).getTarget().getIndex() = 1 and impl.getInstruction(2) instanceof FieldWriteAccess @@ -271,7 +279,7 @@ class TrivialSetter extends Method { /** Gets the underlying field of this setter. */ Field getField() { - result = getImplementation().getAnInstruction().(FieldWriteAccess).getTarget() + result = this.getImplementation().getAnInstruction().(FieldWriteAccess).getTarget() } } @@ -283,5 +291,5 @@ class Operator extends Method { Operator() { this.isOperator() } /** Gets the name of the implementing method (for compatibility with C# data model). */ - string getFunctionName() { result = getName() } + string getFunctionName() { result = this.getName() } } diff --git a/csharp/ql/lib/semmle/code/cil/Type.qll b/csharp/ql/lib/semmle/code/cil/Type.qll index a081d62b7ee..7aeaf9a6495 100644 --- a/csharp/ql/lib/semmle/code/cil/Type.qll +++ b/csharp/ql/lib/semmle/code/cil/Type.qll @@ -19,7 +19,7 @@ class TypeContainer extends DotNet::NamedElement, @cil_type_container { /** A namespace. */ class Namespace extends DotNet::Namespace, TypeContainer, @namespace { - override string toString() { result = getQualifiedName() } + override string toString() { result = this.getQualifiedName() } override Namespace getParent() { result = this.getParentNamespace() } @@ -39,7 +39,7 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { override string toString() { result = this.getName() } /** Gets the containing type of this type, if any. */ - override Type getDeclaringType() { result = getParent() } + override Type getDeclaringType() { result = this.getParent() } /** Gets a member of this type, if any. */ Member getAMember() { result.getDeclaringType() = this } @@ -96,13 +96,13 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { Type getABaseInterface() { cil_base_interface(this, result) } /** Gets an immediate base type of this type, if any. */ - Type getABaseType() { result = getBaseClass() or result = getABaseInterface() } + Type getABaseType() { result = this.getBaseClass() or result = this.getABaseInterface() } /** Gets an immediate subtype of this type, if any. */ Type getASubtype() { result.getABaseType() = this } /** Gets the namespace directly containing this type, if any. */ - Namespace getNamespace() { result = getParent() } + Namespace getNamespace() { result = this.getParent() } /** * Gets an index for implicit conversions. A type can be converted to another numeric type diff --git a/csharp/ql/lib/semmle/code/cil/Types.qll b/csharp/ql/lib/semmle/code/cil/Types.qll index d4d9342b73d..1dfaa0191a1 100644 --- a/csharp/ql/lib/semmle/code/cil/Types.qll +++ b/csharp/ql/lib/semmle/code/cil/Types.qll @@ -12,7 +12,7 @@ class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter { /** Gets the generic type/method declaring this type parameter. */ TypeContainer getGeneric() { cil_type_parameter(result, _, this) } - override Location getLocation() { result = getParent().getLocation() } + override Location getLocation() { result = this.getParent().getLocation() } /** Holds if this type parameter has the `new` constraint. */ predicate isDefaultConstructible() { cil_typeparam_new(this) } @@ -34,11 +34,11 @@ class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter { /** A value or reference type. */ class ValueOrRefType extends DotNet::ValueOrRefType, Type, @cil_valueorreftype { - override ValueOrRefType getDeclaringType() { result = getParent() } + override ValueOrRefType getDeclaringType() { result = this.getParent() } override string getUndecoratedName() { cil_type(this, result, _, _, _) } - override Namespace getDeclaringNamespace() { result = getNamespace() } + override Namespace getDeclaringNamespace() { result = this.getNamespace() } override ValueOrRefType getABaseType() { result = Type.super.getABaseType() } } @@ -79,7 +79,7 @@ class ArrayType extends DotNet::ArrayType, Type, @cil_array_type { override string toStringWithTypes() { result = DotNet::ArrayType.super.toStringWithTypes() } - override Location getLocation() { result = getElementType().getLocation() } + override Location getLocation() { result = this.getElementType().getLocation() } override ValueOrRefType getABaseType() { result = Type.super.getABaseType() } } @@ -92,7 +92,7 @@ class PointerType extends DotNet::PointerType, PrimitiveType, @cil_pointer_type override string getName() { result = DotNet::PointerType.super.getName() } - override Location getLocation() { result = getReferentType().getLocation() } + override Location getLocation() { result = this.getReferentType().getLocation() } override string toString() { result = DotNet::PointerType.super.toString() } @@ -312,13 +312,13 @@ class FunctionPointerType extends Type, CustomModifierReceiver, Parameterizable, override string toString() { result = Type.super.toString() } /** Holds if the return type is `void`. */ - predicate returnsVoid() { getReturnType() instanceof VoidType } + predicate returnsVoid() { this.getReturnType() instanceof VoidType } /** Gets the number of stack items pushed in a call to this method. */ - int getCallPushCount() { if returnsVoid() then result = 0 else result = 1 } + int getCallPushCount() { if this.returnsVoid() then result = 0 else result = 1 } /** Gets the number of stack items popped in a call to this method. */ - int getCallPopCount() { result = count(getRawParameter(_)) } + int getCallPopCount() { result = count(this.getRawParameter(_)) } - override string getLabel() { result = getName() } + override string getLabel() { result = this.getName() } } diff --git a/csharp/ql/lib/semmle/code/cil/Variable.qll b/csharp/ql/lib/semmle/code/cil/Variable.qll index 3a247e1f0d1..604f2c2b646 100644 --- a/csharp/ql/lib/semmle/code/cil/Variable.qll +++ b/csharp/ql/lib/semmle/code/cil/Variable.qll @@ -17,10 +17,10 @@ class Variable extends DotNet::Variable, Declaration, DataFlowNode, @cil_variabl VariableAccess getAnAccess() { result.getTarget() = this } /** Gets a read access to this variable, if any. */ - ReadAccess getARead() { result = getAnAccess() } + ReadAccess getARead() { result = this.getAnAccess() } /** Gets a write access to this variable, if any. */ - WriteAccess getAWrite() { result = getAnAccess() } + WriteAccess getAWrite() { result = this.getAnAccess() } override string toString() { result = Declaration.super.toString() } @@ -40,20 +40,21 @@ class StackVariable extends Variable, @cil_stack_variable { class LocalVariable extends StackVariable, @cil_local_variable { override string toString() { result = - "Local variable " + getIndex() + " of method " + getImplementation().getMethod().getName() + "Local variable " + this.getIndex() + " of method " + + this.getImplementation().getMethod().getName() } /** Gets the method implementation defining this local variable. */ MethodImplementation getImplementation() { this = result.getALocalVariable() } /** Gets the index number of this local variable. This is not usually significant. */ - int getIndex() { this = getImplementation().getLocalVariable(result) } + int getIndex() { this = this.getImplementation().getLocalVariable(result) } override Type getType() { cil_local_variable(this, _, _, result) } - override Location getLocation() { result = getImplementation().getLocation() } + override Location getLocation() { result = this.getImplementation().getLocation() } - override Method getMethod() { result = getImplementation().getMethod() } + override Method getMethod() { result = this.getImplementation().getMethod() } } /** A parameter of a `Method` or `FunctionPointerType`. */ @@ -64,7 +65,7 @@ class Parameter extends DotNet::Parameter, CustomModifierReceiver, @cil_paramete int getIndex() { cil_parameter(this, _, result, _) } override string toString() { - result = "Parameter " + getIndex() + " of " + getDeclaringElement().getName() + result = "Parameter " + this.getIndex() + " of " + this.getDeclaringElement().getName() } override Type getType() { cil_parameter(this, _, _, result) } @@ -82,23 +83,25 @@ class Parameter extends DotNet::Parameter, CustomModifierReceiver, @cil_paramete predicate hasInFlag() { cil_parameter_in(this) } /** Holds if this parameter has C# `out` semantics. */ - override predicate isOut() { hasOutFlag() and not hasInFlag() } + override predicate isOut() { this.hasOutFlag() and not this.hasInFlag() } /** Holds if this parameter has C# `ref` semantics. */ - override predicate isRef() { hasOutFlag() and hasInFlag() } + override predicate isRef() { this.hasOutFlag() and this.hasInFlag() } - override string toStringWithTypes() { result = getPrefix() + getType().toStringWithTypes() } + override string toStringWithTypes() { + result = this.getPrefix() + this.getType().toStringWithTypes() + } private string getPrefix() { - if isOut() + if this.isOut() then result = "out " else - if isRef() + if this.isRef() then result = "ref " else result = "" } - override Location getLocation() { result = getDeclaringElement().getLocation() } + override Location getLocation() { result = this.getDeclaringElement().getLocation() } } /** A method parameter. */ @@ -110,11 +113,11 @@ class MethodParameter extends Parameter, StackVariable { /** Gets a parameter in an overridden method. */ MethodParameter getOverriddenParameter() { - result = getMethod().getOverriddenMethod().getRawParameter(getRawPosition()) + result = this.getMethod().getOverriddenMethod().getRawParameter(this.getRawPosition()) } override MethodParameter getUnboundDeclaration() { - result = getMethod().getUnboundDeclaration().getRawParameter(getRawPosition()) + result = this.getMethod().getUnboundDeclaration().getRawParameter(this.getRawPosition()) } override string toString() { result = Parameter.super.toString() } @@ -136,10 +139,10 @@ class ThisParameter extends MethodParameter { /** A field. */ class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @cil_field { - override string toString() { result = getName() } + override string toString() { result = this.getName() } override string toStringWithTypes() { - result = getDeclaringType().toStringWithTypes() + "." + getName() + result = this.getDeclaringType().toStringWithTypes() + "." + this.getName() } override string getName() { cil_field(this, _, result, _) } @@ -148,5 +151,5 @@ class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @ci override ValueOrRefType getDeclaringType() { cil_field(this, result, _, _) } - override Location getLocation() { result = getDeclaringType().getLocation() } + override Location getLocation() { result = this.getDeclaringType().getLocation() } } diff --git a/csharp/ql/lib/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/lib/semmle/code/csharp/AnnotatedType.qll index 37aa2b23410..8afdbd0d4a3 100644 --- a/csharp/ql/lib/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/lib/semmle/code/csharp/AnnotatedType.qll @@ -67,7 +67,7 @@ private module Annotations { Nullability() { this = TNullability(nullability) } - override string toString() { result = getMemberString() + getSelfNullability() } + override string toString() { result = this.getMemberString() + this.getSelfNullability() } language[monotonicAggregates] private string getMemberString() { @@ -125,7 +125,9 @@ private module Annotations { } /** Gets a textual representation of this type annotation. */ - string toString() { result = getTypePrefix() + getNullability() + getTypeSuffix() } + string toString() { + result = this.getTypePrefix() + this.getNullability() + this.getTypeSuffix() + } private int getFlags() { this = TAnnotationFlags(result, _) } @@ -136,7 +138,7 @@ private module Annotations { /** Gets an annotation in this set of annotations. */ TypeAnnotation getAnAnnotation() { - isSet(result.getBit()) + this.isSet(result.getBit()) or result = this.getNullability() } @@ -298,7 +300,7 @@ class AnnotatedType extends TAnnotatedType { /** Gets a textual representation of this annotated type. */ string toString() { result = - annotations.getTypePrefix() + getUnderlyingType().toStringWithTypes() + + annotations.getTypePrefix() + this.getUnderlyingType().toStringWithTypes() + annotations.getTypeSuffix() } @@ -327,7 +329,7 @@ class AnnotatedType extends TAnnotatedType { /** Gets a type annotation of this annotated type. */ private Annotations::TypeAnnotation getAnAnnotation() { - result = getAnnotations().getAnAnnotation() + result = this.getAnnotations().getAnAnnotation() } /** Holds if the type is a non-nullable reference, for example, `string` in a nullable-enabled context. */ @@ -376,7 +378,7 @@ class AnnotatedArrayType extends AnnotatedType { private string getDimensionString(AnnotatedType elementType) { exists(AnnotatedType et, string res | - et = getElementType() and + et = this.getElementType() and res = type.getArraySuffix() and if et.getUnderlyingType() instanceof ArrayType and not et.isNullableRefType() then result = res + et.(AnnotatedArrayType).getDimensionString(elementType) diff --git a/csharp/ql/lib/semmle/code/csharp/Attribute.qll b/csharp/ql/lib/semmle/code/csharp/Attribute.qll index 06fbda2a150..dae9f8a9fad 100644 --- a/csharp/ql/lib/semmle/code/csharp/Attribute.qll +++ b/csharp/ql/lib/semmle/code/csharp/Attribute.qll @@ -89,7 +89,7 @@ class Attribute extends TopLevelExprParent, @attribute { override Location getALocation() { attribute_location(this, result) } override string toString() { - exists(string type, string name | type = getType().getName() | + exists(string type, string name | type = this.getType().getName() | (if type.matches("%Attribute") then name = type.prefix(type.length() - 9) else name = type) and result = "[" + name + "(...)]" ) diff --git a/csharp/ql/lib/semmle/code/csharp/Callable.qll b/csharp/ql/lib/semmle/code/csharp/Callable.qll index 133ae86d551..41641a9d032 100644 --- a/csharp/ql/lib/semmle/code/csharp/Callable.qll +++ b/csharp/ql/lib/semmle/code/csharp/Callable.qll @@ -117,7 +117,7 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal final BlockStmt getAStatementBody() { result = this.getStatementBody() } /** Holds if this callable has a statement body. */ - final predicate hasStatementBody() { exists(getStatementBody()) } + final predicate hasStatementBody() { exists(this.getStatementBody()) } /** * Gets the expression body of this callable (if any), specified by `=>`. @@ -157,7 +157,7 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal deprecated final Expr getAnExpressionBody() { result = this.getExpressionBody() } /** Holds if this callable has an expression body. */ - final predicate hasExpressionBody() { exists(getExpressionBody()) } + final predicate hasExpressionBody() { exists(this.getExpressionBody()) } /** Gets the entry point in the control graph for this callable. */ ControlFlow::Nodes::EntryNode getEntryPoint() { result.getCallable() = this } @@ -218,7 +218,9 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal exists(YieldReturnStmt yield | yield.getEnclosingCallable() = this | e = yield.getExpr()) } - override string toStringWithTypes() { result = getName() + "(" + parameterTypesToString() + ")" } + override string toStringWithTypes() { + result = this.getName() + "(" + this.parameterTypesToString() + ")" + } /** Gets a `Call` that has this callable as a target. */ Call getACall() { this = result.getTarget() } @@ -270,18 +272,18 @@ class Method extends Callable, Virtualizable, Attributable, @method { override Location getALocation() { method_location(this, result) } /** Holds if this method is an extension method. */ - predicate isExtensionMethod() { getParameter(0).hasExtensionMethodModifier() } + predicate isExtensionMethod() { this.getParameter(0).hasExtensionMethodModifier() } /** Gets the type of the `params` parameter of this method, if any. */ Type getParamsType() { - exists(Parameter last | last = getParameter(getNumberOfParameters() - 1) | + exists(Parameter last | last = this.getParameter(this.getNumberOfParameters() - 1) | last.isParams() and result = last.getType().(ArrayType).getElementType() ) } /** Holds if this method has a `params` parameter. */ - predicate hasParams() { exists(getParamsType()) } + predicate hasParams() { exists(this.getParamsType()) } // Remove when `Callable.isOverridden()` is removed override predicate isOverridden() { Virtualizable.super.isOverridden() } @@ -316,7 +318,7 @@ class ExtensionMethod extends Method { /** Gets the type being extended by this method. */ pragma[noinline] - Type getExtendedType() { result = getParameter(0).getType() } + Type getExtendedType() { result = this.getParameter(0).getType() } override string getAPrimaryQlClass() { result = "ExtensionMethod" } } @@ -355,7 +357,7 @@ class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @ ConstructorInitializer getInitializer() { result = this.getChildExpr(-1) } /** Holds if this constructor has an initializer. */ - predicate hasInitializer() { exists(getInitializer()) } + predicate hasInitializer() { exists(this.getInitializer()) } override ValueOrRefType getDeclaringType() { constructors(this, _, result, _) } @@ -467,7 +469,7 @@ class Operator extends Callable, Member, Attributable, @operator { override string toString() { result = Callable.super.toString() } - override Parameter getRawParameter(int i) { result = getParameter(i) } + override Parameter getRawParameter(int i) { result = this.getParameter(i) } } /** A clone method on a record. */ @@ -999,10 +1001,10 @@ class LocalFunction extends Callable, Modifiable, Attributable, @local_function override Type getReturnType() { local_functions(this, _, result, _) } - override Element getParent() { result = getStatement().getParent() } + override Element getParent() { result = this.getStatement().getParent() } /** Gets the local function statement defining this function. */ - LocalFunctionStmt getStatement() { result.getLocalFunction() = getUnboundDeclaration() } + LocalFunctionStmt getStatement() { result.getLocalFunction() = this.getUnboundDeclaration() } override Callable getEnclosingCallable() { result = this.getStatement().getEnclosingCallable() } @@ -1011,9 +1013,9 @@ class LocalFunction extends Callable, Modifiable, Attributable, @local_function name = this.getName() } - override Location getALocation() { result = getStatement().getALocation() } + override Location getALocation() { result = this.getStatement().getALocation() } - override Parameter getRawParameter(int i) { result = getParameter(i) } + override Parameter getRawParameter(int i) { result = this.getParameter(i) } override string getAPrimaryQlClass() { result = "LocalFunction" } diff --git a/csharp/ql/lib/semmle/code/csharp/Element.qll b/csharp/ql/lib/semmle/code/csharp/Element.qll index fbd96f6086d..390a7b16632 100644 --- a/csharp/ql/lib/semmle/code/csharp/Element.qll +++ b/csharp/ql/lib/semmle/code/csharp/Element.qll @@ -31,7 +31,7 @@ class Element extends DotNet::Element, @element { Element getParent() { result.getAChild() = this } /** Gets a child of this element, if any. */ - Element getAChild() { result = getChild(_) } + Element getAChild() { result = this.getChild(_) } /** Gets the `i`th child of this element (zero-based). */ Element getChild(int i) { none() } diff --git a/csharp/ql/lib/semmle/code/csharp/Event.qll b/csharp/ql/lib/semmle/code/csharp/Event.qll index 7cbfda76877..810cffa927a 100644 --- a/csharp/ql/lib/semmle/code/csharp/Event.qll +++ b/csharp/ql/lib/semmle/code/csharp/Event.qll @@ -29,10 +29,10 @@ class Event extends DeclarationWithAccessors, @event { EventAccessor getAnEventAccessor() { result.getDeclaration() = this } /** Gets the `add` accessor of this event, if any. */ - AddEventAccessor getAddEventAccessor() { result = getAnEventAccessor() } + AddEventAccessor getAddEventAccessor() { result = this.getAnEventAccessor() } /** Gets the `remove` accessor of this event, if any. */ - RemoveEventAccessor getRemoveEventAccessor() { result = getAnEventAccessor() } + RemoveEventAccessor getRemoveEventAccessor() { result = this.getAnEventAccessor() } /** * Holds if this event can be used like a field within its declaring type @@ -111,9 +111,9 @@ class EventAccessor extends Accessor, @event_accessor { * ``` */ class AddEventAccessor extends EventAccessor, @add_event_accessor { - override string getName() { result = "add" + "_" + getDeclaration().getName() } + override string getName() { result = "add" + "_" + this.getDeclaration().getName() } - override string getUndecoratedName() { result = "add" + "_" + getDeclaration().getName() } + override string getUndecoratedName() { result = "add" + "_" + this.getDeclaration().getName() } override string getAPrimaryQlClass() { result = "AddEventAccessor" } } @@ -132,9 +132,9 @@ class AddEventAccessor extends EventAccessor, @add_event_accessor { * ``` */ class RemoveEventAccessor extends EventAccessor, @remove_event_accessor { - override string getName() { result = "remove" + "_" + getDeclaration().getName() } + override string getName() { result = "remove" + "_" + this.getDeclaration().getName() } - override string getUndecoratedName() { result = "remove" + "_" + getDeclaration().getName() } + override string getUndecoratedName() { result = "remove" + "_" + this.getDeclaration().getName() } override string getAPrimaryQlClass() { result = "RemoveEventAccessor" } } diff --git a/csharp/ql/lib/semmle/code/csharp/File.qll b/csharp/ql/lib/semmle/code/csharp/File.qll index df9ce6f3cf6..55fd2ccdc81 100644 --- a/csharp/ql/lib/semmle/code/csharp/File.qll +++ b/csharp/ql/lib/semmle/code/csharp/File.qll @@ -47,7 +47,7 @@ class Container extends @container { */ string getRelativePath() { exists(string absPath, string pref | - absPath = getAbsolutePath() and sourceLocationPrefix(pref) + absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) | absPath = pref and result = "" or @@ -74,7 +74,7 @@ class Container extends @container { * </table> */ string getBaseName() { - result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) + result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) } /** @@ -100,7 +100,9 @@ class Container extends @container { * <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr> * </table> */ - string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } + string getExtension() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) + } /** * Gets the stem of this container, that is, the prefix of its base name up to @@ -119,7 +121,9 @@ class Container extends @container { * <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr> * </table> */ - string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } + string getStem() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) + } /** Gets the parent container of this file or folder, if any. */ Container getParentContainer() { containerparent(result, this) } @@ -128,52 +132,52 @@ class Container extends @container { Container getAChildContainer() { this = result.getParentContainer() } /** Gets a file in this container. */ - File getAFile() { result = getAChildContainer() } + File getAFile() { result = this.getAChildContainer() } /** Gets the file in this container that has the given `baseName`, if any. */ File getFile(string baseName) { - result = getAFile() and + result = this.getAFile() and result.getBaseName() = baseName } /** Gets a sub-folder in this container. */ - Folder getAFolder() { result = getAChildContainer() } + Folder getAFolder() { result = this.getAChildContainer() } /** Gets the sub-folder in this container that has the given `baseName`, if any. */ Folder getFolder(string baseName) { - result = getAFolder() and + result = this.getAFolder() and result.getBaseName() = baseName } /** Gets the file or sub-folder in this container that has the given `name`, if any. */ Container getChildContainer(string name) { - result = getAChildContainer() and + result = this.getAChildContainer() and result.getBaseName() = name } /** Gets the file in this container that has the given `stem` and `extension`, if any. */ File getFile(string stem, string extension) { - result = getAChildContainer() and + result = this.getAChildContainer() and result.getStem() = stem and result.getExtension() = extension } /** Gets a sub-folder contained in this container. */ - Folder getASubFolder() { result = getAChildContainer() } + Folder getASubFolder() { result = this.getAChildContainer() } /** * Gets a textual representation of the path of this container. * * This is the absolute path of the container. */ - string toString() { result = getAbsolutePath() } + string toString() { result = this.getAbsolutePath() } } /** A folder. */ class Folder extends Container, @folder { override string getAbsolutePath() { folders(this, result) } - override string getURL() { result = "folder://" + getAbsolutePath() } + override string getURL() { result = "folder://" + this.getAbsolutePath() } } /** A file. */ diff --git a/csharp/ql/lib/semmle/code/csharp/Generics.qll b/csharp/ql/lib/semmle/code/csharp/Generics.qll index 25a3679715b..9190523e3c0 100644 --- a/csharp/ql/lib/semmle/code/csharp/Generics.qll +++ b/csharp/ql/lib/semmle/code/csharp/Generics.qll @@ -71,14 +71,14 @@ class ConstructedGeneric extends DotNet::ConstructedGeneric, Generic { override UnboundGeneric getUnboundGeneric() { constructed_generic(this, result) } override UnboundGeneric getUnboundDeclaration() { - result = getUnboundGeneric().getUnboundDeclaration() + result = this.getUnboundGeneric().getUnboundDeclaration() } override int getNumberOfTypeArguments() { result = count(int i | type_arguments(_, i, this)) } override Type getTypeArgument(int i) { none() } - override Type getATypeArgument() { result = getTypeArgument(_) } + override Type getATypeArgument() { result = this.getTypeArgument(_) } /** Gets the annotated type of type argument `i`. */ final AnnotatedType getAnnotatedTypeArgument(int i) { result.appliesToTypeArgument(this, i) } @@ -141,7 +141,7 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric { result = ValueOrRefType.super.getUnboundDeclaration() } - final override Type getChild(int n) { result = getTypeParameter(n) } + final override Type getChild(int n) { result = this.getTypeParameter(n) } override string toStringWithTypes() { result = this.getUndecoratedName() + "<" + getTypeParametersToString(this) + ">" @@ -173,7 +173,7 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter { TypeParameterConstraints getConstraints() { result.getTypeParameter() = this } override predicate isRefType() { - exists(TypeParameterConstraints tpc | tpc = getConstraints() | + exists(TypeParameterConstraints tpc | tpc = this.getConstraints() | tpc.hasRefTypeConstraint() or tpc.getATypeConstraint() instanceof Class or tpc.getATypeConstraint().(TypeParameter).isRefType() @@ -182,7 +182,7 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter { } override predicate isValueType() { - exists(TypeParameterConstraints tpc | tpc = getConstraints() | + exists(TypeParameterConstraints tpc | tpc = this.getConstraints() | tpc.hasValueTypeConstraint() or tpc.getATypeConstraint().(TypeParameter).isValueType() ) @@ -219,9 +219,9 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter { /** Gets a non-type-parameter type that was transitively supplied for this parameter. */ Type getAnUltimatelySuppliedType() { - result = getASuppliedType() and not result instanceof TypeParameter + result = this.getASuppliedType() and not result instanceof TypeParameter or - result = getASuppliedType().(TypeParameter).getAnUltimatelySuppliedType() + result = this.getASuppliedType().(TypeParameter).getAnUltimatelySuppliedType() } override int getIndex() { type_parameters(this, result, _, _) } @@ -376,8 +376,8 @@ class UnboundGenericDelegateType extends DelegateType, UnboundGenericType { override string toStringWithTypes() { result = - getUndecoratedName() + "<" + getTypeParametersToString(this) + ">(" + parameterTypesToString() - + ")" + this.getUndecoratedName() + "<" + getTypeParametersToString(this) + ">(" + + this.parameterTypesToString() + ")" } } @@ -404,7 +404,7 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric { override UnboundGenericType getUnboundGeneric() { constructed_generic(this, getTypeRef(result)) } - final override Type getChild(int n) { result = getTypeArgument(n) } + final override Type getChild(int n) { result = this.getTypeArgument(n) } final override string toStringWithTypes() { result = this.getUndecoratedName() + "<" + getTypeArgumentsToString(this) + ">" @@ -542,12 +542,12 @@ class UnboundGenericMethod extends Method, UnboundGeneric { override string toStringWithTypes() { result = - getUndecoratedName() + "<" + getTypeParametersToString(this) + ">" + "(" + - parameterTypesToString() + ")" + this.getUndecoratedName() + "<" + getTypeParametersToString(this) + ">" + "(" + + this.parameterTypesToString() + ")" } final override string getName() { - result = getUndecoratedName() + "<" + getTypeParameterCommas(this) + ">" + result = this.getUndecoratedName() + "<" + getTypeParameterCommas(this) + ">" } final override string getUndecoratedName() { methods(this, result, _, _, _) } @@ -580,8 +580,8 @@ class ConstructedMethod extends Method, ConstructedGeneric { override string toStringWithTypes() { result = - getUndecoratedName() + "<" + getTypeArgumentsToString(this) + ">" + "(" + - parameterTypesToString() + ")" + this.getUndecoratedName() + "<" + getTypeArgumentsToString(this) + ">" + "(" + + this.parameterTypesToString() + ")" } override UnboundGenericMethod getUnboundDeclaration() { @@ -589,12 +589,12 @@ class ConstructedMethod extends Method, ConstructedGeneric { } final override string getName() { - result = getUndecoratedName() + "<" + getTypeArgumentsNames(this) + ">" + result = this.getUndecoratedName() + "<" + getTypeArgumentsNames(this) + ">" } override predicate hasQualifiedName(string qualifier, string name) { - qualifier = getDeclaringType().getQualifiedName() and - name = getUndecoratedName() + "<" + getTypeArgumentsQualifiedNames(this) + ">" + qualifier = this.getDeclaringType().getQualifiedName() and + name = this.getUndecoratedName() + "<" + getTypeArgumentsQualifiedNames(this) + ">" } final override string getUndecoratedName() { methods(this, result, _, _, _) } diff --git a/csharp/ql/lib/semmle/code/csharp/Member.qll b/csharp/ql/lib/semmle/code/csharp/Member.qll index 9f8408621fc..40b887f052a 100644 --- a/csharp/ql/lib/semmle/code/csharp/Member.qll +++ b/csharp/ql/lib/semmle/code/csharp/Member.qll @@ -155,7 +155,9 @@ class Modifiable extends Declaration, @modifiable { * Holds if this declaration is effectively `public`, meaning that it can be * referenced outside the declaring assembly. */ - predicate isEffectivelyPublic() { not isEffectivelyPrivate() and not isEffectivelyInternal() } + predicate isEffectivelyPublic() { + not this.isEffectivelyPrivate() and not this.isEffectivelyInternal() + } } /** A declaration that is a member of a type. */ @@ -193,12 +195,12 @@ class Virtualizable extends Member, @virtualizable { override predicate isPublic() { Member.super.isPublic() or - implementsExplicitInterface() + this.implementsExplicitInterface() } override predicate isPrivate() { super.isPrivate() and - not implementsExplicitInterface() + not this.implementsExplicitInterface() } /** @@ -211,17 +213,17 @@ class Virtualizable extends Member, @virtualizable { /** * Holds if this member implements an interface member explicitly. */ - predicate implementsExplicitInterface() { exists(getExplicitlyImplementedInterface()) } + predicate implementsExplicitInterface() { exists(this.getExplicitlyImplementedInterface()) } /** Holds if this member can be overridden or implemented. */ predicate isOverridableOrImplementable() { - not isSealed() and - not getDeclaringType().isSealed() and + not this.isSealed() and + not this.getDeclaringType().isSealed() and ( - isVirtual() or - isOverride() or - isAbstract() or - getDeclaringType() instanceof Interface + this.isVirtual() or + this.isOverride() or + this.isAbstract() or + this.getDeclaringType() instanceof Interface ) } @@ -243,10 +245,10 @@ class Virtualizable extends Member, @virtualizable { Virtualizable getAnOverrider() { this = result.getOverridee() } /** Holds if this member is overridden by some other member. */ - predicate isOverridden() { exists(getAnOverrider()) } + predicate isOverridden() { exists(this.getAnOverrider()) } /** Holds if this member overrides another member. */ - predicate overrides() { exists(getOverridee()) } + predicate overrides() { exists(this.getOverridee()) } /** * Gets the interface member that is immediately implemented by this member, if any. @@ -274,7 +276,7 @@ class Virtualizable extends Member, @virtualizable { Virtualizable getImplementee(ValueOrRefType t) { implements(this, result, t) } /** Gets the interface member that is immediately implemented by this member, if any. */ - Virtualizable getImplementee() { result = getImplementee(_) } + Virtualizable getImplementee() { result = this.getImplementee(_) } /** * Gets a member that immediately implements this interface member, if any. @@ -338,8 +340,8 @@ class Virtualizable extends Member, @virtualizable { | this = implementation or - getOverridee+() = implementation and - getDeclaringType().getABaseType+() = implementationType + this.getOverridee+() = implementation and + this.getDeclaringType().getABaseType+() = implementationType ) } @@ -355,10 +357,10 @@ class Virtualizable extends Member, @virtualizable { Virtualizable getAnUltimateImplementor() { this = result.getAnUltimateImplementee() } /** Holds if this interface member is implemented by some other member. */ - predicate isImplemented() { exists(getAnImplementor()) } + predicate isImplemented() { exists(this.getAnImplementor()) } /** Holds if this member implements (transitively) an interface member. */ - predicate implements() { exists(getAnUltimateImplementee()) } + predicate implements() { exists(this.getAnUltimateImplementee()) } /** * Holds if this member overrides or implements (reflexively, transitively) @@ -366,8 +368,8 @@ class Virtualizable extends Member, @virtualizable { */ predicate overridesOrImplementsOrEquals(Virtualizable that) { this = that or - getOverridee+() = that or - getAnUltimateImplementee() = that + this.getOverridee+() = that or + this.getAnUltimateImplementee() = that } } @@ -386,7 +388,7 @@ class Parameterizable extends DotNet::Parameterizable, Declaration, @parameteriz */ private string parameterTypeToString(int i) { exists(Parameter p, string prefix | - p = getParameter(i) and + p = this.getParameter(i) and result = prefix + p.getType().toStringWithTypes() | if p.isOut() @@ -407,6 +409,7 @@ class Parameterizable extends DotNet::Parameterizable, Declaration, @parameteriz */ language[monotonicAggregates] string parameterTypesToString() { - result = concat(int i | exists(getParameter(i)) | parameterTypeToString(i), ", " order by i) + result = + concat(int i | exists(this.getParameter(i)) | this.parameterTypeToString(i), ", " order by i) } } diff --git a/csharp/ql/lib/semmle/code/csharp/Modifier.qll b/csharp/ql/lib/semmle/code/csharp/Modifier.qll index 542598d204e..a3018640ee7 100644 --- a/csharp/ql/lib/semmle/code/csharp/Modifier.qll +++ b/csharp/ql/lib/semmle/code/csharp/Modifier.qll @@ -20,9 +20,9 @@ class Modifier extends Element, @modifier { */ class AccessModifier extends Modifier { AccessModifier() { - hasName("public") or - hasName("private") or - hasName("internal") or - hasName("protected") + this.hasName("public") or + this.hasName("private") or + this.hasName("internal") or + this.hasName("protected") } } diff --git a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll index daf4978da53..3342dd5c59c 100644 --- a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll +++ b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll @@ -289,7 +289,7 @@ class IfDirective extends ConditionalDirective, @directive_if { } /** Gets a sibling `#elif` or `#else` preprocessor directive. */ - BranchDirective getASiblingDirective() { result = getSiblingDirective(_) } + BranchDirective getASiblingDirective() { result = this.getSiblingDirective(_) } override string toString() { result = "#if ..." } diff --git a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll index a701c7bfbf3..a3d36fba69d 100644 --- a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll +++ b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll @@ -171,7 +171,7 @@ class PrintAstNode extends TPrintAstNode { /** * Gets a child of this node. */ - final PrintAstNode getAChild() { result = getChild(_) } + final PrintAstNode getAChild() { result = this.getChild(_) } /** * Gets the parent of this node, if any. @@ -189,7 +189,7 @@ class PrintAstNode extends TPrintAstNode { */ string getProperty(string key) { key = "semmle.label" and - result = toString() + result = this.toString() } /** @@ -198,7 +198,7 @@ class PrintAstNode extends TPrintAstNode { * this. */ string getChildEdgeLabel(int childIndex) { - exists(getChild(childIndex)) and + exists(this.getChild(childIndex)) and result = childIndex.toString() } } diff --git a/csharp/ql/lib/semmle/code/csharp/Property.qll b/csharp/ql/lib/semmle/code/csharp/Property.qll index 5464142a085..a91ac6f13a4 100644 --- a/csharp/ql/lib/semmle/code/csharp/Property.qll +++ b/csharp/ql/lib/semmle/code/csharp/Property.qll @@ -53,10 +53,10 @@ class DeclarationWithAccessors extends AssignableMember, Virtualizable, Attribut class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelExprParent, @assignable_with_accessors { /** Gets the `get` accessor of this declaration, if any. */ - Getter getGetter() { result = getAnAccessor() } + Getter getGetter() { result = this.getAnAccessor() } /** Gets the `set` accessor of this declaration, if any. */ - Setter getSetter() { result = getAnAccessor() } + Setter getSetter() { result = this.getAnAccessor() } override DeclarationWithGetSetAccessors getOverridee() { result = DeclarationWithAccessors.super.getOverridee() @@ -182,10 +182,10 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper or // For library types, we don't know about assignments in constructors. We instead assume that // arguments passed to parameters of constructors with suitable names. - getDeclaringType().fromLibrary() and + this.getDeclaringType().fromLibrary() and exists(Parameter param, Constructor c, string propertyName | - propertyName = getName() and - c = getDeclaringType().getAConstructor() and + propertyName = this.getName() and + c = this.getDeclaringType().getAConstructor() and param = c.getAParameter() and // Find a constructor parameter with the same name, but with a lower case initial letter. param.hasName(propertyName.charAt(0).toLowerCase() + propertyName.suffix(1)) @@ -256,7 +256,7 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer override string getUndecoratedName() { indexers(this, result, _, _, _) } /** Gets the dimension of this indexer, that is, its number of parameters. */ - int getDimension() { result = getNumberOfParameters() } + int getDimension() { result = this.getNumberOfParameters() } override ValueOrRefType getDeclaringType() { indexers(this, _, result, _, _) } @@ -304,7 +304,9 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer override Location getALocation() { indexer_location(this, result) } - override string toStringWithTypes() { result = getName() + "[" + parameterTypesToString() + "]" } + override string toStringWithTypes() { + result = this.getName() + "[" + this.parameterTypesToString() + "]" + } override string getAPrimaryQlClass() { result = "Indexer" } } @@ -368,17 +370,17 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor { * ``` */ override Modifier getAModifier() { - result = getAnAccessModifier() + result = this.getAnAccessModifier() or - result = getDeclaration().getAModifier() and - not (result instanceof AccessModifier and exists(getAnAccessModifier())) + result = this.getDeclaration().getAModifier() and + not (result instanceof AccessModifier and exists(this.getAnAccessModifier())) } override Accessor getUnboundDeclaration() { accessors(this, _, _, _, result) } override Location getALocation() { accessor_location(this, result) } - override string toString() { result = getName() } + override string toString() { result = this.getName() } } /** @@ -395,11 +397,11 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor { * ``` */ class Getter extends Accessor, @getter { - override string getName() { result = "get" + "_" + getDeclaration().getName() } + override string getName() { result = "get" + "_" + this.getDeclaration().getName() } - override string getUndecoratedName() { result = "get" + "_" + getDeclaration().getName() } + override string getUndecoratedName() { result = "get" + "_" + this.getDeclaration().getName() } - override Type getReturnType() { result = getDeclaration().getType() } + override Type getReturnType() { result = this.getDeclaration().getType() } /** * Gets the field used in the trival implementation of this getter, if any. @@ -417,8 +419,8 @@ class Getter extends Accessor, @getter { */ Field trivialGetterField() { exists(ReturnStmt ret | - getStatementBody().getNumberOfStmts() = 1 and - getStatementBody().getAChild() = ret and + this.getStatementBody().getNumberOfStmts() = 1 and + this.getStatementBody().getAChild() = ret and ret.getExpr() = result.getAnAccess() ) } @@ -444,9 +446,9 @@ class Getter extends Accessor, @getter { * ``` */ class Setter extends Accessor, @setter { - override string getName() { result = "set" + "_" + getDeclaration().getName() } + override string getName() { result = "set" + "_" + this.getDeclaration().getName() } - override string getUndecoratedName() { result = "set" + "_" + getDeclaration().getName() } + override string getUndecoratedName() { result = "set" + "_" + this.getDeclaration().getName() } override Type getReturnType() { exists(this) and // needed to avoid compiler warning @@ -469,8 +471,8 @@ class Setter extends Accessor, @setter { */ Field trivialSetterField() { exists(AssignExpr assign | - getStatementBody().getNumberOfStmts() = 1 and - assign.getParent() = getStatementBody().getAChild() and + this.getStatementBody().getNumberOfStmts() = 1 and + assign.getParent() = this.getStatementBody().getAChild() and assign.getLValue() = result.getAnAccess() and assign.getRValue() = accessToValue() ) @@ -521,9 +523,9 @@ private ParameterAccess accessToValue() { */ class TrivialProperty extends Property { TrivialProperty() { - isAutoImplemented() + this.isAutoImplemented() or - getGetter().trivialGetterField() = getSetter().trivialSetterField() + this.getGetter().trivialGetterField() = this.getSetter().trivialSetterField() or exists(CIL::TrivialProperty prop | this.matchesHandle(prop)) } diff --git a/csharp/ql/lib/semmle/code/csharp/Stmt.qll b/csharp/ql/lib/semmle/code/csharp/Stmt.qll index 2ccd57078db..be074c176ba 100644 --- a/csharp/ql/lib/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/lib/semmle/code/csharp/Stmt.qll @@ -65,10 +65,10 @@ class BlockStmt extends Stmt, @block_stmt { int getNumberOfStmts() { result = count(this.getAStmt()) } /** Gets the first statement in this block, if any. */ - Stmt getFirstStmt() { result = getStmt(0) } + Stmt getFirstStmt() { result = this.getStmt(0) } /** Gets the last statement in this block, if any. */ - Stmt getLastStmt() { result = getStmt(getNumberOfStmts() - 1) } + Stmt getLastStmt() { result = this.getStmt(this.getNumberOfStmts() - 1) } /** Holds if this block is an empty block with no statements. */ predicate isEmpty() { not exists(this.getAStmt()) } @@ -79,8 +79,8 @@ class BlockStmt extends Stmt, @block_stmt { } override Stmt stripSingletonBlocks() { - if getNumberOfStmts() = 1 - then result = getAChildStmt().stripSingletonBlocks() + if this.getNumberOfStmts() = 1 + then result = this.getAChildStmt().stripSingletonBlocks() else result = this } @@ -420,7 +420,7 @@ class ForStmt extends LoopStmt, @for_stmt { * } * ``` */ - Expr getAnInitializer() { result = getInitializer(_) } + Expr getAnInitializer() { result = this.getInitializer(_) } /** * Gets the `n`th initializer expression of this `for` loop @@ -451,7 +451,7 @@ class ForStmt extends LoopStmt, @for_stmt { * } * ``` */ - Expr getAnUpdate() { result = getUpdate(_) } + Expr getAnUpdate() { result = this.getUpdate(_) } /** * Gets the `n`th update expression of this `for` loop (starting at index 0). @@ -519,7 +519,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt { * ``` */ LocalVariableDeclExpr getVariableDeclExpr(int i) { - result = getVariableDeclTuple().getArgument(i) + result = this.getVariableDeclTuple().getArgument(i) or i = 0 and result = this.getChild(0) } @@ -547,7 +547,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt { * } * ``` */ - LocalVariable getVariable(int i) { result = getVariableDeclExpr(i).getVariable() } + LocalVariable getVariable(int i) { result = this.getVariableDeclExpr(i).getVariable() } /** * Gets a local variable of this `foreach` loop. @@ -560,7 +560,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt { * } * ``` */ - LocalVariable getAVariable() { result = getVariable(_) } + LocalVariable getAVariable() { result = this.getVariable(_) } /** * Gets a local variable declaration of this `foreach` loop. @@ -573,7 +573,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt { * } * ``` */ - LocalVariableDeclExpr getAVariableDeclExpr() { result = getVariableDeclExpr(_) } + LocalVariableDeclExpr getAVariableDeclExpr() { result = this.getVariableDeclExpr(_) } override Expr getCondition() { none() } @@ -690,8 +690,8 @@ class GotoLabelStmt extends GotoStmt, @goto_stmt { /** Gets the target statement that this `goto` statement jumps to. */ LabeledStmt getTarget() { - result.getEnclosingCallable() = getEnclosingCallable() and - result.getLabel() = getLabel() + result.getEnclosingCallable() = this.getEnclosingCallable() and + result.getLabel() = this.getLabel() } override string getAPrimaryQlClass() { result = "GotoLabelStmt" } @@ -717,7 +717,7 @@ class GotoCaseStmt extends GotoStmt, @goto_case_stmt { /** Gets the constant expression that this `goto case` statement jumps to. */ Expr getExpr() { result = this.getChild(0) } - override string getLabel() { result = getExpr().getValue() } + override string getLabel() { result = this.getExpr().getValue() } override string toString() { result = "goto case ...;" } @@ -764,14 +764,14 @@ class ThrowStmt extends JumpStmt, ThrowElement, @throw_stmt { override ExceptionClass getThrownExceptionType() { result = ThrowElement.super.getThrownExceptionType() or - result = getRethrowParent().(CatchClause).getCaughtExceptionType() + result = this.getRethrowParent().(CatchClause).getCaughtExceptionType() } private ControlFlowElement getRethrowParent() { - result = this and not exists(getExpr()) + result = this and not exists(this.getExpr()) or exists(ControlFlowElement mid | - mid = getRethrowParent() and + mid = this.getRethrowParent() and not mid instanceof CatchClause and result = mid.getParent() ) @@ -785,7 +785,7 @@ class ThrowStmt extends JumpStmt, ThrowElement, @throw_stmt { * and may be thrown as an exception. */ class ExceptionClass extends Class { - ExceptionClass() { getBaseClass*() instanceof SystemExceptionClass } + ExceptionClass() { this.getBaseClass*() instanceof SystemExceptionClass } } /** @@ -897,13 +897,15 @@ class TryStmt extends Stmt, @try_stmt { override string getAPrimaryQlClass() { result = "TryStmt" } /** Gets the `catch` clause that handles an exception of type `ex`, if any. */ - CatchClause getAnExceptionHandler(ExceptionClass ex) { result = clauseHandlesException(ex, 0) } + CatchClause getAnExceptionHandler(ExceptionClass ex) { + result = this.clauseHandlesException(ex, 0) + } /** * Holds if catch clause `cc` definitely handles exceptions of type `ex`. */ predicate definitelyHandles(ExceptionClass ex, CatchClause cc) { - cc = getACatchClause() and + cc = this.getACatchClause() and not exists(cc.getFilterClause()) and ( cc.getCaughtExceptionType() = ex.getBaseClass*() @@ -913,22 +915,22 @@ class TryStmt extends Stmt, @try_stmt { } private predicate maybeHandles(ExceptionClass ex, CatchClause cc) { - cc = getACatchClause() and + cc = this.getACatchClause() and cc.getCaughtExceptionType().getBaseClass*() = ex } private CatchClause clauseHandlesException(ExceptionClass ex, int n) { - exists(CatchClause clause | clause = getCatchClause(n) | - if definitelyHandles(ex, clause) + exists(CatchClause clause | clause = this.getCatchClause(n) | + if this.definitelyHandles(ex, clause) then result = clause else - if maybeHandles(ex, clause) + if this.maybeHandles(ex, clause) then result = clause or - result = clauseHandlesException(ex, n + 1) + result = this.clauseHandlesException(ex, n + 1) else // Does not handle - result = clauseHandlesException(ex, n + 1) + result = this.clauseHandlesException(ex, n + 1) ) } @@ -939,10 +941,10 @@ class TryStmt extends Stmt, @try_stmt { * `try` statement. */ ControlFlowElement getATriedElement() { - result = getBlock() + result = this.getBlock() or exists(ControlFlowElement mid | - mid = getATriedElement() and + mid = this.getATriedElement() and not mid instanceof TryStmt and result = getAChild(mid, mid.getEnclosingCallable()) ) @@ -996,10 +998,10 @@ class CatchClause extends Stmt, @catch { * } * ``` */ - Expr getFilterClause() { result = getChild(2) } + Expr getFilterClause() { result = this.getChild(2) } /** Holds if this `catch` clause has a filter. */ - predicate hasFilterClause() { exists(getFilterClause()) } + predicate hasFilterClause() { exists(this.getFilterClause()) } /** Holds if this is the last `catch` clause in the `try` statement that it belongs to. */ predicate isLast() { @@ -1120,7 +1122,7 @@ class LockStmt extends Stmt, @lock_stmt { override string toString() { result = "lock (...) {...}" } /** Gets the variable being locked, if any. */ - Variable getLockVariable() { result.getAnAccess() = getExpr() } + Variable getLockVariable() { result.getAnAccess() = this.getExpr() } /** Gets a statement in the scope of this `lock` statement. */ Stmt getALockedStmt() { @@ -1128,14 +1130,14 @@ class LockStmt extends Stmt, @lock_stmt { // delegates and lambdas result.getParent() = this or - exists(Stmt mid | mid = getALockedStmt() and result.getParent() = mid) + exists(Stmt mid | mid = this.getALockedStmt() and result.getParent() = mid) } /** Holds if this statement is of the form `lock(this) { ... }`. */ - predicate isLockThis() { getExpr() instanceof ThisAccess } + predicate isLockThis() { this.getExpr() instanceof ThisAccess } /** Gets the type `T` if this statement is of the form `lock(typeof(T)) { ... }`. */ - Type getLockTypeObject() { result = getExpr().(TypeofExpr).getTypeAccess().getTarget() } + Type getLockTypeObject() { result = this.getExpr().(TypeofExpr).getTypeAccess().getTarget() } override string getAPrimaryQlClass() { result = "LockStmt" } } @@ -1453,7 +1455,7 @@ class LocalFunctionStmt extends Stmt, @local_function_stmt { /** Gets the local function defined by this statement. */ LocalFunction getLocalFunction() { local_function_stmts(this, result) } - override string toString() { result = getLocalFunction().getName() + "(...)" } + override string toString() { result = this.getLocalFunction().getName() + "(...)" } override string getAPrimaryQlClass() { result = "LocalFunctionStmt" } } diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll index d7a15000bbf..109c1df00c7 100644 --- a/csharp/ql/lib/semmle/code/csharp/Type.qll +++ b/csharp/ql/lib/semmle/code/csharp/Type.qll @@ -37,7 +37,7 @@ class Type extends DotNet::Type, Member, TypeContainer, @type { predicate containsTypeParameters() { this instanceof TypeParameter or - not this instanceof UnboundGenericType and getAChild().containsTypeParameters() + not this instanceof UnboundGenericType and this.getAChild().containsTypeParameters() } /** Holds if this type is a reference type, or a type parameter that is a reference type. */ @@ -133,8 +133,8 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ /** Gets an immediate base type of this type, if any. */ override ValueOrRefType getABaseType() { - result = getBaseClass() or - result = getABaseInterface() + result = this.getBaseClass() or + result = this.getABaseInterface() } /** Gets an immediate subtype of this type, if any. */ @@ -200,9 +200,9 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ */ pragma[inline] predicate hasCallable(Callable c) { - hasMethod(c) + this.hasMethod(c) or - hasMember(c.(Accessor).getDeclaration()) + this.hasMember(c.(Accessor).getDeclaration()) } /** @@ -234,63 +234,63 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ or hasNonOverriddenMember(this.getBaseClass+(), m) or - hasOverriddenMember(m) + this.hasOverriddenMember(m) } cached private predicate hasOverriddenMember(Virtualizable v) { v.isOverridden() and - v = getAMember() + v = this.getAMember() or - getBaseClass().(ValueOrRefType).hasOverriddenMember(v) and + this.getBaseClass().(ValueOrRefType).hasOverriddenMember(v) and not v.isPrivate() and - not memberOverrides(v) + not this.memberOverrides(v) } // Predicate folding for proper join-order pragma[noinline] private predicate memberOverrides(Virtualizable v) { - getAMember().(Virtualizable).getOverridee() = v + this.getAMember().(Virtualizable).getOverridee() = v } /** Gets a field (or member constant) with the given name. */ - Field getField(string name) { result = getAMember() and result.hasName(name) } + Field getField(string name) { result = this.getAMember() and result.hasName(name) } /** Gets a field (or member constant) of this type, if any. */ Field getAField() { result = this.getField(_) } /** Gets a member constant of this type, if any. */ - MemberConstant getAConstant() { result = getAMember() } + MemberConstant getAConstant() { result = this.getAMember() } /** Gets a method of this type, if any. */ - Method getAMethod() { result = getAMember() } + Method getAMethod() { result = this.getAMember() } /** Gets a method of this type with the given name. */ - Method getAMethod(string name) { result = getAMember() and result.hasName(name) } + Method getAMethod(string name) { result = this.getAMember() and result.hasName(name) } /** Gets a property of this type, if any. */ - Property getAProperty() { result = getAMember() } + Property getAProperty() { result = this.getAMember() } /** Gets a named property of this type. */ - Property getProperty(string name) { result = getAMember() and result.hasName(name) } + Property getProperty(string name) { result = this.getAMember() and result.hasName(name) } /** Gets an indexer of this type, if any. */ - Indexer getAnIndexer() { result = getAMember() } + Indexer getAnIndexer() { result = this.getAMember() } /** Gets an event of this type, if any. */ - Event getAnEvent() { result = getAMember() } + Event getAnEvent() { result = this.getAMember() } /** Gets a user-defined operator of this type, if any. */ - Operator getAnOperator() { result = getAMember() } + Operator getAnOperator() { result = this.getAMember() } /** Gets a static or instance constructor of this type, if any. */ - Constructor getAConstructor() { result = getAMember() } + Constructor getAConstructor() { result = this.getAMember() } /** Gets the static constructor of this type, if any. */ - StaticConstructor getStaticConstructor() { result = getAMember() } + StaticConstructor getStaticConstructor() { result = this.getAMember() } /** Gets a nested type of this type, if any. */ - NestedType getANestedType() { result = getAMember() } + NestedType getANestedType() { result = this.getAMember() } /** Gets the number of types that directly depend on this type. */ int getAfferentCoupling() { afferentCoupling(this, result) } @@ -675,10 +675,10 @@ class Enum extends ValueType, @enum_type { */ class Struct extends ValueType, @struct_type { /** Holds if this `struct` has a `ref` modifier. */ - predicate isRef() { hasModifier("ref") } + predicate isRef() { this.hasModifier("ref") } /** Holds if this `struct` has a `readonly` modifier. */ - predicate isReadonly() { hasModifier("readonly") } + predicate isReadonly() { this.hasModifier("readonly") } override string getAPrimaryQlClass() { result = "Struct" } } @@ -695,7 +695,7 @@ class RefType extends ValueOrRefType, @ref_type { /** Gets a member that overrides a non-abstract member in a super type, if any. */ private Virtualizable getAnOverrider() { - getAMember() = result and + this.getAMember() = result and exists(Virtualizable v | result.getOverridee() = v and not v.isAbstract()) } @@ -897,14 +897,14 @@ class FunctionPointerType extends Type, Parameterizable, @function_pointer_type } /** Gets an unmanaged calling convention. */ - Type getAnUnmanagedCallingConvention() { result = getUnmanagedCallingConvention(_) } + Type getAnUnmanagedCallingConvention() { result = this.getUnmanagedCallingConvention(_) } /** Gets the annotated return type of this function pointer type. */ AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) } override string getAPrimaryQlClass() { result = "FunctionPointerType" } - override string getLabel() { result = getName() } + override string getLabel() { result = this.getName() } } /** @@ -922,13 +922,15 @@ class NullableType extends ValueType, DotNet::ConstructedGeneric, @nullable_type */ Type getUnderlyingType() { nullable_underlying_type(this, getTypeRef(result)) } - override string toStringWithTypes() { result = getUnderlyingType().toStringWithTypes() + "?" } + override string toStringWithTypes() { + result = this.getUnderlyingType().toStringWithTypes() + "?" + } - override Type getChild(int n) { result = getUnderlyingType() and n = 0 } + override Type getChild(int n) { result = this.getUnderlyingType() and n = 0 } - override Location getALocation() { result = getUnderlyingType().getALocation() } + override Location getALocation() { result = this.getUnderlyingType().getALocation() } - override Type getTypeArgument(int p) { p = 0 and result = getUnderlyingType() } + override Type getTypeArgument(int p) { p = 0 and result = this.getUnderlyingType() } override string getAPrimaryQlClass() { result = "NullableType" } @@ -966,8 +968,8 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type { /** Holds if this array type has the same shape (dimension and rank) as `that` array type. */ predicate hasSameShapeAs(ArrayType that) { - getDimension() = that.getDimension() and - getRank() = that.getRank() + this.getDimension() = that.getDimension() and + this.getRank() = that.getRank() } /** @@ -981,7 +983,7 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type { private string getDimensionString(Type elementType) { exists(Type et, string res | et = this.getElementType() and - res = getArraySuffix() and + res = this.getArraySuffix() and if et instanceof ArrayType then result = res + et.(ArrayType).getDimensionString(elementType) else ( @@ -996,7 +998,7 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type { ) } - override Type getChild(int n) { result = getElementType() and n = 0 } + override Type getChild(int n) { result = this.getElementType() and n = 0 } override Location getALocation() { type_location(this, result) @@ -1021,13 +1023,15 @@ class PointerType extends DotNet::PointerType, Type, @pointer_type { override string toStringWithTypes() { result = DotNet::PointerType.super.toStringWithTypes() } - override Type getChild(int n) { result = getReferentType() and n = 0 } + override Type getChild(int n) { result = this.getReferentType() and n = 0 } final override string getName() { types(this, _, result) } - final override string getUndecoratedName() { result = getReferentType().getUndecoratedName() } + final override string getUndecoratedName() { + result = this.getReferentType().getUndecoratedName() + } - override Location getALocation() { result = getReferentType().getALocation() } + override Location getALocation() { result = this.getReferentType().getALocation() } override string toString() { result = DotNet::PointerType.super.toString() } @@ -1082,10 +1086,10 @@ class TupleType extends ValueType, @tuple_type { * Gets the type of the `n`th element of this tuple, indexed from 0. * For example, the 0th (first) element type of `(int, string)` is `int`. */ - Type getElementType(int n) { result = getElement(n).getType() } + Type getElementType(int n) { result = this.getElement(n).getType() } /** Gets an element of this tuple. */ - Field getAnElement() { result = getElement(_) } + Field getAnElement() { result = this.getElement(_) } override Location getALocation() { type_location(this, result) } @@ -1093,23 +1097,27 @@ class TupleType extends ValueType, @tuple_type { * Gets the arity of this tuple. For example, the arity of * `(int, int, double)` is 3. */ - int getArity() { result = count(getAnElement()) } + int getArity() { result = count(this.getAnElement()) } language[monotonicAggregates] override string toStringWithTypes() { result = "(" + - concat(Type t, int i | t = getElement(i).getType() | t.toStringWithTypes(), ", " order by i) - + ")" + concat(Type t, int i | + t = this.getElement(i).getType() + | + t.toStringWithTypes(), ", " order by i + ) + ")" } language[monotonicAggregates] override string getName() { result = - "(" + concat(Type t, int i | t = getElement(i).getType() | t.getName(), "," order by i) + ")" + "(" + concat(Type t, int i | t = this.getElement(i).getType() | t.getName(), "," order by i) + + ")" } - override string getLabel() { result = getUnderlyingType().getLabel() } + override string getLabel() { result = this.getUnderlyingType().getLabel() } override Type getChild(int i) { result = this.getUnderlyingType().getChild(i) } diff --git a/csharp/ql/lib/semmle/code/csharp/Unification.qll b/csharp/ql/lib/semmle/code/csharp/Unification.qll index 3a2c6745f45..d9f39cec603 100644 --- a/csharp/ql/lib/semmle/code/csharp/Unification.qll +++ b/csharp/ql/lib/semmle/code/csharp/Unification.qll @@ -297,7 +297,7 @@ module Gvn { or result = strictconcat(int i, int j | - toStringPart(i, j) + this.toStringPart(i, j) | this.toStringConstructedPart(i, j) order by i desc, j ) diff --git a/csharp/ql/lib/semmle/code/csharp/Variable.qll b/csharp/ql/lib/semmle/code/csharp/Variable.qll index a13175dfeb0..6592320fdd7 100644 --- a/csharp/ql/lib/semmle/code/csharp/Variable.qll +++ b/csharp/ql/lib/semmle/code/csharp/Variable.qll @@ -149,7 +149,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top predicate isIn() { params(this, _, _, _, 5, _, _) } /** Holds if this parameter is an output or reference parameter. */ - predicate isOutOrRef() { isOut() or isRef() } + predicate isOutOrRef() { this.isOut() or this.isRef() } /** * Holds if this parameter is a parameter array. For example, `args` @@ -210,7 +210,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top Expr getDefaultValue() { result = this.getUnboundDeclaration().getChildExpr(0) } /** Holds if this parameter has a default value. */ - predicate hasDefaultValue() { exists(getDefaultValue()) } + predicate hasDefaultValue() { exists(this.getDefaultValue()) } /** Gets the callable to which this parameter belongs, if any. */ override Callable getCallable() { result = this.getDeclaringElement() } @@ -238,7 +238,9 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * `y` is `5`, and the assigned arguments to `z` are `3` and `6`, respectively. */ pragma[nomagic] - Expr getAnAssignedArgument() { result = getCallable().getACall().getArgumentForParameter(this) } + Expr getAnAssignedArgument() { + result = this.getCallable().getACall().getArgumentForParameter(this) + } /** Holds if this parameter is potentially overwritten in the body of its callable. */ predicate isOverwritten() { @@ -323,7 +325,7 @@ class LocalVariable extends LocalScopeVariable, @local_variable { /** Gets the enclosing callable of this local variable. */ Callable getEnclosingCallable() { result = this.getVariableDeclExpr().getEnclosingCallable() } - override Callable getCallable() { result = getEnclosingCallable() } + override Callable getCallable() { result = this.getEnclosingCallable() } override predicate isRef() { localvars(this, 3, _, _, _, _) } diff --git a/csharp/ql/lib/semmle/code/csharp/XML.qll b/csharp/ql/lib/semmle/code/csharp/XML.qll index 4c762f4bf65..76f3b3cb022 100755 --- a/csharp/ql/lib/semmle/code/csharp/XML.qll +++ b/csharp/ql/lib/semmle/code/csharp/XML.qll @@ -108,7 +108,7 @@ class XMLParent extends @xmlparent { } /** Gets the text value contained in this XML parent. */ - string getTextValue() { result = allCharactersString() } + string getTextValue() { result = this.allCharactersString() } /** Gets a printable representation of this XML parent. */ string toString() { result = this.getName() } @@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File { XMLFile() { xmlEncoding(this, _) } /** Gets a printable representation of this XML file. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } /** Gets the name of this XML file. */ override string getName() { result = File.super.getAbsolutePath() } @@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File { * * Gets the path of this XML file. */ - deprecated string getPath() { result = getAbsolutePath() } + deprecated string getPath() { result = this.getAbsolutePath() } /** * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. * * Gets the path of the folder that contains this XML file. */ - deprecated string getFolder() { result = getParentContainer().getAbsolutePath() } + deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() } /** Gets the encoding of this XML file. */ string getEncoding() { xmlEncoding(this, result) } @@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd { */ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { /** Holds if this XML element has the given `name`. */ - predicate hasName(string name) { name = getName() } + predicate hasName(string name) { name = this.getName() } /** Gets the name of this XML element. */ override string getName() { xmlElements(this, result, _, _, _) } @@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } /** Gets a printable representation of this XML element. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll b/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll index d425ec118ed..4f364147395 100644 --- a/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll +++ b/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll @@ -42,7 +42,7 @@ abstract class AssertMethod extends Method { * * Gets the index of a parameter being asserted. */ - deprecated final int getAssertionIndex() { result = getAnAssertionIndex() } + deprecated final int getAssertionIndex() { result = this.getAnAssertionIndex() } /** Gets the parameter at position `i` being asserted. */ final Parameter getAssertedParameter(int i) { @@ -55,7 +55,7 @@ abstract class AssertMethod extends Method { * * Gets a parameter being asserted. */ - deprecated final Parameter getAssertedParameter() { result = getAssertedParameter(_) } + deprecated final Parameter getAssertedParameter() { result = this.getAssertedParameter(_) } /** Gets the failure type if the assertion fails for argument `i`, if any. */ abstract AssertionFailure getAssertionFailure(int i); diff --git a/csharp/ql/lib/semmle/code/csharp/commons/GeneratedCode.qll b/csharp/ql/lib/semmle/code/csharp/commons/GeneratedCode.qll index 42e04ddcbb9..38d559d8ffd 100644 --- a/csharp/ql/lib/semmle/code/csharp/commons/GeneratedCode.qll +++ b/csharp/ql/lib/semmle/code/csharp/commons/GeneratedCode.qll @@ -57,7 +57,7 @@ abstract class GeneratedCodeComment extends CommentLine { } */ class GenericGeneratedCodeComment extends GeneratedCodeComment { GenericGeneratedCodeComment() { - exists(string line, string entity, string was, string automatically | line = getText() | + exists(string line, string entity, string was, string automatically | line = this.getText() | entity = "file|class|interface|art[ei]fact|module|script" and was = "was|is|has been" and automatically = "automatically |mechanically |auto[- ]?" and @@ -70,7 +70,7 @@ class GenericGeneratedCodeComment extends GeneratedCodeComment { /** A comment warning against modifications. */ class DontModifyMarkerComment extends GeneratedCodeComment { DontModifyMarkerComment() { - exists(string line | line = getText() | + exists(string line | line = this.getText() | line.regexpMatch("(?i).*\\bGenerated by\\b.*\\bDo not edit\\b.*") or line.regexpMatch("(?i).*\\bAny modifications to this file will be lost\\b.*") ) diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/BasicBlocks.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/BasicBlocks.qll index b4448a71380..08e5925ad50 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/BasicBlocks.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/BasicBlocks.qll @@ -11,7 +11,7 @@ private import ControlFlow::SuccessorTypes */ class BasicBlock extends TBasicBlockStart { /** Gets an immediate successor of this basic block, if any. */ - BasicBlock getASuccessor() { result.getFirstNode() = getLastNode().getASuccessor() } + BasicBlock getASuccessor() { result.getFirstNode() = this.getLastNode().getASuccessor() } /** Gets an immediate successor of this basic block of a given type, if any. */ BasicBlock getASuccessorByType(ControlFlow::SuccessorType t) { @@ -42,7 +42,7 @@ class BasicBlock extends TBasicBlockStart { * The basic block on line 2 is an immediate `true` successor of the * basic block on line 1. */ - BasicBlock getATrueSuccessor() { result.getFirstNode() = getLastNode().getATrueSuccessor() } + BasicBlock getATrueSuccessor() { result.getFirstNode() = this.getLastNode().getATrueSuccessor() } /** * Gets an immediate `false` successor, if any. @@ -60,25 +60,27 @@ class BasicBlock extends TBasicBlockStart { * The basic block on line 2 is an immediate `false` successor of the * basic block on line 1. */ - BasicBlock getAFalseSuccessor() { result.getFirstNode() = getLastNode().getAFalseSuccessor() } + BasicBlock getAFalseSuccessor() { + result.getFirstNode() = this.getLastNode().getAFalseSuccessor() + } /** Gets the control flow node at a specific (zero-indexed) position in this basic block. */ - ControlFlow::Node getNode(int pos) { bbIndex(getFirstNode(), result, pos) } + ControlFlow::Node getNode(int pos) { bbIndex(this.getFirstNode(), result, pos) } /** Gets a control flow node in this basic block. */ - ControlFlow::Node getANode() { result = getNode(_) } + ControlFlow::Node getANode() { result = this.getNode(_) } /** Gets the first control flow node in this basic block. */ ControlFlow::Node getFirstNode() { this = TBasicBlockStart(result) } /** Gets the last control flow node in this basic block. */ - ControlFlow::Node getLastNode() { result = getNode(length() - 1) } + ControlFlow::Node getLastNode() { result = this.getNode(this.length() - 1) } /** Gets the callable that this basic block belongs to. */ final Callable getCallable() { result = this.getFirstNode().getEnclosingCallable() } /** Gets the length of this basic block. */ - int length() { result = strictcount(getANode()) } + int length() { result = strictcount(this.getANode()) } /** * Holds if this basic block immediately dominates basic block `bb`. @@ -151,7 +153,7 @@ class BasicBlock extends TBasicBlockStart { */ predicate dominates(BasicBlock bb) { bb = this or - strictlyDominates(bb) + this.strictlyDominates(bb) } /** @@ -177,14 +179,14 @@ class BasicBlock extends TBasicBlockStart { * does not dominate the basic block on line 6. */ predicate inDominanceFrontier(BasicBlock df) { - dominatesPredecessor(df) and - not strictlyDominates(df) + this.dominatesPredecessor(df) and + not this.strictlyDominates(df) } /** * Holds if this basic block dominates a predecessor of `df`. */ - private predicate dominatesPredecessor(BasicBlock df) { dominates(df.getAPredecessor()) } + private predicate dominatesPredecessor(BasicBlock df) { this.dominates(df.getAPredecessor()) } /** * Gets the basic block that immediately dominates this basic block, if any. @@ -263,7 +265,7 @@ class BasicBlock extends TBasicBlockStart { * post-dominates itself. */ predicate postDominates(BasicBlock bb) { - strictlyPostDominates(bb) or + this.strictlyPostDominates(bb) or this = bb } @@ -276,10 +278,10 @@ class BasicBlock extends TBasicBlockStart { predicate inLoop() { this.getASuccessor+() = this } /** Gets a textual representation of this basic block. */ - string toString() { result = getFirstNode().toString() } + string toString() { result = this.getFirstNode().toString() } /** Gets the location of this basic block. */ - Location getLocation() { result = getFirstNode().getLocation() } + Location getLocation() { result = this.getFirstNode().getLocation() } } /** @@ -420,7 +422,7 @@ private module JoinBlockPredecessors { /** A basic block with more than one predecessor. */ class JoinBlock extends BasicBlock { - JoinBlock() { getFirstNode().isJoin() } + JoinBlock() { this.getFirstNode().isJoin() } /** * Gets the `i`th predecessor of this join block, with respect to some diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowElement.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowElement.qll index 7601b83f6b8..9e7fd92d2a4 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowElement.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowElement.qll @@ -72,13 +72,14 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { ControlFlowElement getAReachableElement() { // Reachable in same basic block exists(BasicBlock bb, int i, int j | - bb.getNode(i) = getAControlFlowNode() and + bb.getNode(i) = this.getAControlFlowNode() and bb.getNode(j) = result.getAControlFlowNode() and i < j ) or // Reachable in different basic blocks - getAControlFlowNode().getBasicBlock().getASuccessor+().getANode() = result.getAControlFlowNode() + this.getAControlFlowNode().getBasicBlock().getASuccessor+().getANode() = + result.getAControlFlowNode() } pragma[noinline] diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll index 96b73d8978d..c94184b4f66 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll @@ -33,10 +33,10 @@ module ControlFlow { ControlFlowElement getElement() { none() } /** Gets the location of this control flow node. */ - Location getLocation() { result = getElement().getLocation() } + Location getLocation() { result = this.getElement().getLocation() } /** Holds if this control flow node has conditional successors. */ - predicate isCondition() { exists(getASuccessorByType(any(ConditionalSuccessor e))) } + predicate isCondition() { exists(this.getASuccessorByType(any(ConditionalSuccessor e))) } /** Gets the basic block that this control flow node belongs to. */ BasicBlock getBasicBlock() { result.getANode() = this } @@ -67,7 +67,7 @@ module ControlFlow { // potentially very large predicate, so must be inlined pragma[inline] predicate dominates(Node that) { - strictlyDominates(that) + this.strictlyDominates(that) or this = that } @@ -138,7 +138,7 @@ module ControlFlow { // potentially very large predicate, so must be inlined pragma[inline] predicate postDominates(Node that) { - strictlyPostDominates(that) + this.strictlyPostDominates(that) or this = that } @@ -186,13 +186,13 @@ module ControlFlow { Node getASuccessorByType(SuccessorType t) { result = getASuccessor(this, t) } /** Gets an immediate successor, if any. */ - Node getASuccessor() { result = getASuccessorByType(_) } + Node getASuccessor() { result = this.getASuccessorByType(_) } /** Gets an immediate predecessor node of a given flow type, if any. */ Node getAPredecessorByType(SuccessorType t) { result.getASuccessorByType(t) = this } /** Gets an immediate predecessor, if any. */ - Node getAPredecessor() { result = getAPredecessorByType(_) } + Node getAPredecessor() { result = this.getAPredecessorByType(_) } /** * Gets an immediate `true` successor, if any. @@ -211,7 +211,7 @@ module ControlFlow { * on line 1. */ Node getATrueSuccessor() { - result = getASuccessorByType(any(BooleanSuccessor t | t.getValue() = true)) + result = this.getASuccessorByType(any(BooleanSuccessor t | t.getValue() = true)) } /** @@ -231,7 +231,7 @@ module ControlFlow { * on line 1. */ Node getAFalseSuccessor() { - result = getASuccessorByType(any(BooleanSuccessor t | t.getValue() = false)) + result = this.getASuccessorByType(any(BooleanSuccessor t | t.getValue() = false)) } /** Holds if this node has more than one predecessor. */ @@ -285,7 +285,7 @@ module ControlFlow { override Callable getEnclosingCallable() { result = this.getCallable() } - override Location getLocation() { result = getCallable().getLocation() } + override Location getLocation() { result = this.getCallable().getLocation() } override string toString() { exists(string s | @@ -293,7 +293,7 @@ module ControlFlow { or normal = false and s = "abnormal" | - result = "exit " + getCallable() + " (" + s + ")" + result = "exit " + this.getCallable() + " (" + s + ")" ) } } @@ -307,9 +307,9 @@ module ControlFlow { override Callable getEnclosingCallable() { result = this.getCallable() } - override Location getLocation() { result = getCallable().getLocation() } + override Location getLocation() { result = this.getCallable().getLocation() } - override string toString() { result = "exit " + getCallable().toString() } + override string toString() { result = "exit " + this.getCallable().toString() } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll index 5a402717401..5e3f00c3c5e 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll @@ -1740,7 +1740,7 @@ module Internal { e = this.getAChildExpr() or exists(Expr mid | - descendant(mid) and + this.descendant(mid) and not interestingDescendantCandidate(mid) and e = mid.getAChildExpr() ) @@ -1748,7 +1748,7 @@ module Internal { /** Holds if `e` is an interesting descendant of this descendant. */ predicate interestingDescendant(Expr e) { - descendant(e) and + this.descendant(e) and interestingDescendantCandidate(e) } } @@ -1797,7 +1797,7 @@ module Internal { override predicate candidate(ControlFlowElement x, ControlFlowElement y) { exists(BasicBlock bb, Declaration d | - candidateAux(x, d, bb) and + this.candidateAux(x, d, bb) and y = any(AccessOrCallExpr e | e.getAControlFlowNode().getBasicBlock() = bb and diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 8a02fb95dee..82eb5d302ad 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -495,7 +495,7 @@ module Expressions { // Flow from last element of left operand to first element of right operand last(this.getLeftOperand(), pred, c) and c.(NullnessCompletion).isNull() and - first(getRightOperand(), succ) + first(this.getRightOperand(), succ) or // Post-order: flow from last element of left operand to element itself last(this.getLeftOperand(), pred, c) and @@ -504,7 +504,7 @@ module Expressions { not c.(NullnessCompletion).isNull() or // Post-order: flow from last element of right operand to element itself - last(getRightOperand(), pred, c) and + last(this.getRightOperand(), pred, c) and c instanceof NormalCompletion and succ = this } @@ -575,7 +575,7 @@ module Expressions { PostOrderTree.super.last(last, c) or // Qualifier exits with a `null` completion - lastQualifier(last, c) and + this.lastQualifier(last, c) and c.(NullnessCompletion).isNull() } @@ -1483,7 +1483,7 @@ module Statements { ) or // Flow into `finally` block - pred = getAFinallyPredecessor(c, true) and + pred = this.getAFinallyPredecessor(c, true) and first(this.getFinally(), succ) } } diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll index 31155dea0ae..de44808b18e 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll @@ -69,9 +69,9 @@ class PreBasicBlock extends ControlFlowElement { ControlFlowElement getFirstElement() { result = this } - ControlFlowElement getLastElement() { result = this.getElement(length() - 1) } + ControlFlowElement getLastElement() { result = this.getElement(this.length() - 1) } - int length() { result = strictcount(getAnElement()) } + int length() { result = strictcount(this.getAnElement()) } predicate immediatelyDominates(PreBasicBlock bb) { bbIDominates(this, bb) } @@ -117,7 +117,7 @@ class ConditionBlock extends PreBasicBlock { pragma[nomagic] predicate controls(PreBasicBlock controlled, SuccessorTypes::ConditionalSuccessor s) { - exists(PreBasicBlock succ, ConditionalCompletion c | immediatelyControls(succ, c) | + exists(PreBasicBlock succ, ConditionalCompletion c | this.immediatelyControls(succ, c) | succ.dominates(controlled) and s = c.getAMatchingSuccessorType() ) diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/Splitting.qll index 4d1d39de988..83ea302e691 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -628,7 +628,7 @@ module FinallySplitting { */ private predicate exit(ControlFlowElement pred, Completion c, boolean inherited) { exists(TryStmt try, FinallySplitType type | - exit0(pred, try, this.getNestLevel(), c) and + this.exit0(pred, try, this.getNestLevel(), c) and type = this.getType() | if last(try.getFinally(), pred, c) @@ -690,18 +690,18 @@ module FinallySplitting { override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) { succ(pred, succ, c) and ( - exit(pred, c, _) + this.exit(pred, c, _) or - exit(pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion(), _) + this.exit(pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion(), _) ) } override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) { scopeLast(scope, last, c) and ( - exit(last, c, _) + this.exit(last, c, _) or - exit(last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion(), _) + this.exit(last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion(), _) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/SuccessorType.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/SuccessorType.qll index 648c2cd847c..76da2fb62ef 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/SuccessorType.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/SuccessorType.qll @@ -77,7 +77,7 @@ module SuccessorTypes { class BooleanSuccessor extends ConditionalSuccessor, TBooleanSuccessor { override boolean getValue() { this = TBooleanSuccessor(result) } - override string toString() { result = getValue().toString() } + override string toString() { result = this.getValue().toString() } } /** @@ -310,7 +310,7 @@ module SuccessorTypes { /** Gets the type of exception. */ ExceptionClass getExceptionClass() { this = TExceptionSuccessor(result) } - override string toString() { result = "exception(" + getExceptionClass().getName() + ")" } + override string toString() { result = "exception(" + this.getExceptionClass().getName() + ")" } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index f36783f56c6..f405484a55d 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -505,20 +505,20 @@ class SystemBooleanFlow extends LibraryTypeDataFlow, SystemBooleanStruct { CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue ) { - methodFlow(source, sink, c) and + this.methodFlow(source, sink, c) and preservesValue = false } private predicate methodFlow( CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m ) { - m = getParseMethod() and + m = this.getParseMethod() and ( source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() ) or - m = getTryParseMethod() and + m = this.getTryParseMethod() and ( source = TCallableFlowSourceArg(0) and ( @@ -537,12 +537,12 @@ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass { boolean preservesValue ) { ( - constructorFlow(source, sink, c) + this.constructorFlow(source, sink, c) or - methodFlow(source, sink, c) + this.methodFlow(source, sink, c) or exists(Property p | - propertyFlow(p) and + this.propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() @@ -552,7 +552,7 @@ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass { } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() and + c = this.getAMember() and c.getParameter(0).getType() instanceof StringType and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() @@ -567,11 +567,11 @@ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass { } private predicate propertyFlow(Property p) { - p = getPathAndQueryProperty() + p = this.getPathAndQueryProperty() or - p = getQueryProperty() + p = this.getQueryProperty() or - p = getOriginalStringProperty() + p = this.getOriginalStringProperty() } } @@ -582,15 +582,15 @@ class SystemIOStringReaderFlow extends LibraryTypeDataFlow, SystemIOStringReader boolean preservesValue ) { ( - constructorFlow(source, sink, c) + this.constructorFlow(source, sink, c) or - methodFlow(source, sink, c) + this.methodFlow(source, sink, c) ) and preservesValue = false } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() and + c = this.getAMember() and c.getParameter(0).getType() instanceof StringType and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() @@ -599,7 +599,7 @@ class SystemIOStringReaderFlow extends LibraryTypeDataFlow, SystemIOStringReader private predicate methodFlow( CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m ) { - m.getDeclaringType() = getABaseType*() and + m.getDeclaringType() = this.getABaseType*() and m.getName().matches("Read%") and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() @@ -612,17 +612,17 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, SourceDeclarationCallable c, boolean preservesValue ) { - constructorFlow(source, sourceAp, sink, sinkAp, c) and + this.constructorFlow(source, sourceAp, sink, sinkAp, c) and preservesValue = false or - methodFlow(source, sourceAp, sink, sinkAp, c, preservesValue) + this.methodFlow(source, sourceAp, sink, sinkAp, c, preservesValue) } private predicate constructorFlow( CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, Constructor c ) { - c = getAMember() and + c = this.getAMember() and c.getParameter(0).getType().(ArrayType).getElementType() instanceof CharType and source = TCallableFlowSourceArg(0) and sourceAp = AccessPath::element() and @@ -641,14 +641,14 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { sinkAp = AccessPath::empty() and preservesValue = true or - m = getSplitMethod() and + m = this.getSplitMethod() and source = TCallableFlowSourceQualifier() and sourceAp = AccessPath::empty() and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::element() and preservesValue = false or - m = getReplaceMethod() and + m = this.getReplaceMethod() and sourceAp = AccessPath::empty() and sinkAp = AccessPath::empty() and ( @@ -661,21 +661,21 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { preservesValue = false ) or - m = getSubstringMethod() and + m = this.getSubstringMethod() and source = TCallableFlowSourceQualifier() and sourceAp = AccessPath::empty() and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::empty() and preservesValue = false or - m = getCloneMethod() and + m = this.getCloneMethod() and source = TCallableFlowSourceQualifier() and sourceAp = AccessPath::empty() and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::empty() and preservesValue = true or - m = getInsertMethod() and + m = this.getInsertMethod() and sourceAp = AccessPath::empty() and sinkAp = AccessPath::empty() and ( @@ -688,21 +688,21 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { preservesValue = false ) or - m = getNormalizeMethod() and + m = this.getNormalizeMethod() and source = TCallableFlowSourceQualifier() and sourceAp = AccessPath::empty() and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::empty() and preservesValue = false or - m = getRemoveMethod() and + m = this.getRemoveMethod() and source = TCallableFlowSourceQualifier() and sourceAp = AccessPath::empty() and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::empty() and preservesValue = false or - m = getAMethod() and + m = this.getAMethod() and m.getName().regexpMatch("((ToLower|ToUpper)(Invariant)?)|(Trim(Start|End)?)|(Pad(Left|Right))") and source = TCallableFlowSourceQualifier() and sourceAp = AccessPath::empty() and @@ -710,7 +710,7 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { sinkAp = AccessPath::empty() and preservesValue = false or - m = getConcatMethod() and + m = this.getConcatMethod() and exists(int i | source = getFlowSourceArg(m, i, sourceAp) and sink = TCallableFlowSinkReturn() and @@ -718,20 +718,20 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { preservesValue = false ) or - m = getCopyMethod() and + m = this.getCopyMethod() and source = TCallableFlowSourceArg(0) and sourceAp = AccessPath::empty() and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::empty() and preservesValue = true or - m = getJoinMethod() and + m = this.getJoinMethod() and source = getFlowSourceArg(m, [0, 1], sourceAp) and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::empty() and preservesValue = false or - m = getFormatMethod() and + m = this.getFormatMethod() and exists(int i | (m.getParameter(0).getType() instanceof SystemIFormatProviderInterface implies i != 0) and source = getFlowSourceArg(m, i, sourceAp) and @@ -749,10 +749,10 @@ class SystemTextStringBuilderFlow extends LibraryTypeDataFlow, SystemTextStringB SourceDeclarationCallable c, boolean preservesValue ) { ( - constructorFlow(source, sourceAp, sink, sinkAp, c) and + this.constructorFlow(source, sourceAp, sink, sinkAp, c) and preservesValue = true or - methodFlow(source, sourceAp, sink, sinkAp, c, preservesValue) + this.methodFlow(source, sourceAp, sink, sinkAp, c, preservesValue) ) } @@ -760,7 +760,7 @@ class SystemTextStringBuilderFlow extends LibraryTypeDataFlow, SystemTextStringB CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, Constructor c ) { - c = getAMember() and + c = this.getAMember() and c.getParameter(0).getType() instanceof StringType and source = TCallableFlowSourceArg(0) and sourceAp = AccessPath::empty() and @@ -894,7 +894,7 @@ class IEnumerableFlow extends LibraryTypeDataFlow, RefType { ) { preservesValue = true and ( - methodFlowLINQExtensions(source, sourceAp, sink, sinkAp, c) + this.methodFlowLINQExtensions(source, sourceAp, sink, sinkAp, c) or c = this.getFind() and sourceAp = AccessPath::element() and @@ -1674,14 +1674,14 @@ class SystemConvertFlow extends LibraryTypeDataFlow, SystemConvertClass { CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue ) { - methodFlow(source, sink, c) and + this.methodFlow(source, sink, c) and preservesValue = false } private predicate methodFlow( CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m ) { - m = getAMethod() and + m = this.getAMethod() and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() } @@ -1694,7 +1694,7 @@ class SystemWebHttpCookieFlow extends LibraryTypeDataFlow, SystemWebHttpCookie { boolean preservesValue ) { exists(Property p | - propertyFlow(p) and + this.propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() @@ -1703,8 +1703,8 @@ class SystemWebHttpCookieFlow extends LibraryTypeDataFlow, SystemWebHttpCookie { } private predicate propertyFlow(Property p) { - p = getValueProperty() or - p = getValuesProperty() + p = this.getValueProperty() or + p = this.getValuesProperty() } } @@ -1715,7 +1715,7 @@ class SystemNetCookieFlow extends LibraryTypeDataFlow, SystemNetCookieClass { boolean preservesValue ) { exists(Property p | - propertyFlow(p) and + this.propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() @@ -1733,7 +1733,7 @@ class SystemNetIPHostEntryFlow extends LibraryTypeDataFlow, SystemNetIPHostEntry boolean preservesValue ) { exists(Property p | - propertyFlow(p) and + this.propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() @@ -1742,8 +1742,8 @@ class SystemNetIPHostEntryFlow extends LibraryTypeDataFlow, SystemNetIPHostEntry } private predicate propertyFlow(Property p) { - p = getHostNameProperty() or - p = getAliasesProperty() + p = this.getHostNameProperty() or + p = this.getAliasesProperty() } } @@ -1755,7 +1755,7 @@ class SystemWebUIWebControlsTextBoxFlow extends LibraryTypeDataFlow, boolean preservesValue ) { exists(Property p | - propertyFlow(p) and + this.propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() @@ -1763,7 +1763,7 @@ class SystemWebUIWebControlsTextBoxFlow extends LibraryTypeDataFlow, preservesValue = false } - private predicate propertyFlow(Property p) { p = getTextProperty() } + private predicate propertyFlow(Property p) { p = this.getTextProperty() } } /** Data flow for `System.Collections.Generic.KeyValuePair`. */ @@ -1864,11 +1864,11 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT SourceDeclarationCallable c, boolean preservesValue ) { ( - constructorFlow(source, sink, c) and + this.constructorFlow(source, sink, c) and sourceAp = AccessPath::empty() and sinkAp = AccessPath::empty() or - methodFlow(source, sourceAp, sink, sinkAp, c) + this.methodFlow(source, sourceAp, sink, sinkAp, c) ) and preservesValue = true } @@ -1954,9 +1954,9 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow, SystemThreading SourceDeclarationCallable c, boolean preservesValue ) { ( - constructorFlow(source, sourceAp, sink, sinkAp, c) + this.constructorFlow(source, sourceAp, sink, sinkAp, c) or - methodFlow(source, sourceAp, sink, sinkAp, c) + this.methodFlow(source, sourceAp, sink, sinkAp, c) ) and preservesValue = true or @@ -2101,14 +2101,14 @@ private class SystemRuntimeCompilerServicesConfiguredTaskAwaitableTFlow extends class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { SystemThreadingTasksFactoryFlow() { this instanceof SystemThreadingTasksClass and - getName().regexpMatch("TaskFactory(<>)?") + this.getName().regexpMatch("TaskFactory(<>)?") } override predicate callableFlow( CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, SourceDeclarationCallable c, boolean preservesValue ) { - methodFlow(source, sourceAp, sink, sinkAp, c) and + this.methodFlow(source, sourceAp, sink, sinkAp, c) and preservesValue = true } @@ -2236,12 +2236,12 @@ library class SystemTextEncodingFlow extends LibraryTypeDataFlow, SystemTextEnco preservesValue = false and c = this.getAMethod() and exists(Method m | m.getAnOverrider*().getUnboundDeclaration() = c | - m = getGetBytesMethod() and + m = this.getGetBytesMethod() and source = getFlowSourceArg(m, 0, sourceAp) and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::empty() or - m = [getGetStringMethod(), getGetCharsMethod()] and + m = [this.getGetStringMethod(), this.getGetCharsMethod()] and source = TCallableFlowSourceArg(0) and sourceAp = AccessPath::element() and sink = TCallableFlowSinkReturn() and @@ -2257,9 +2257,9 @@ library class SystemIOMemoryStreamFlow extends LibraryTypeDataFlow, SystemIOMemo boolean preservesValue ) { ( - constructorFlow(source, sink, c) + this.constructorFlow(source, sink, c) or - c = getToArrayMethod().getAnOverrider*() and + c = this.getToArrayMethod().getAnOverrider*() and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() ) and @@ -2267,7 +2267,7 @@ library class SystemIOMemoryStreamFlow extends LibraryTypeDataFlow, SystemIOMemo } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() and + c = this.getAMember() and c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() @@ -2281,17 +2281,17 @@ class SystemIOStreamFlow extends LibraryTypeDataFlow, SystemIOStreamClass { boolean preservesValue ) { ( - c = getAReadMethod().getAnOverrider*() and + c = this.getAReadMethod().getAnOverrider*() and c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and sink = TCallableFlowSinkArg(0) and source = TCallableFlowSourceQualifier() or - c = getAWriteMethod().getAnOverrider*() and + c = this.getAWriteMethod().getAnOverrider*() and c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkQualifier() or - c = any(Method m | m = getAMethod() and m.getName().matches("CopyTo%")).getAnOverrider*() and + c = any(Method m | m = this.getAMethod() and m.getName().matches("CopyTo%")).getAnOverrider*() and c.getParameter(0).getType() instanceof SystemIOStreamClass and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkArg(0) @@ -2307,12 +2307,12 @@ class SystemIOCompressionDeflateStreamFlow extends LibraryTypeDataFlow, CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue ) { - constructorFlow(source, sink, c) and + this.constructorFlow(source, sink, c) and preservesValue = false } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() and + c = this.getAMember() and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() } @@ -2324,7 +2324,7 @@ class SystemXmlXmlReaderFlow extends LibraryTypeDataFlow, SystemXmlXmlReaderClas CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue ) { - c = getCreateMethod() and + c = this.getCreateMethod() and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() and preservesValue = false @@ -2337,7 +2337,7 @@ class SystemXmlXmlDocumentFlow extends LibraryTypeDataFlow, SystemXmlXmlDocument CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue ) { - c = getLoadMethod() and + c = this.getLoadMethod() and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkQualifier() and preservesValue = false @@ -2352,13 +2352,13 @@ class SystemXmlXmlNodeFlow extends LibraryTypeDataFlow, SystemXmlXmlNodeClass { ) { ( exists(Property p | - p = getAProperty() and + p = this.getAProperty() and c = p.getGetter() and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() ) or - c = getASelectNodeMethod() and + c = this.getASelectNodeMethod() and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() ) and @@ -2372,7 +2372,7 @@ class SystemXmlXmlNamedNodeMapFlow extends LibraryTypeDataFlow, SystemXmlXmlName CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue ) { - c = getGetNamedItemMethod() and + c = this.getGetNamedItemMethod() and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = true @@ -2385,14 +2385,14 @@ class SystemIOPathFlow extends LibraryTypeDataFlow, SystemIOPathClass { CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, SourceDeclarationCallable c, boolean preservesValue ) { - c = getAMethod("Combine") and + c = this.getAMethod("Combine") and source = getFlowSourceArg(c, _, sourceAp) and sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::empty() and preservesValue = false or exists(Parameter p | - c = getAMethod() and + c = this.getAMethod() and c.getName().matches("Get%") and p = c.getAParameter() and p.hasName("path") and @@ -2411,10 +2411,10 @@ class SystemWebHttpUtilityFlow extends LibraryTypeDataFlow, SystemWebHttpUtility boolean preservesValue ) { ( - c = getAnHtmlAttributeEncodeMethod() or - c = getAnHtmlEncodeMethod() or - c = getAJavaScriptStringEncodeMethod() or - c = getAnUrlEncodeMethod() + c = this.getAnHtmlAttributeEncodeMethod() or + c = this.getAnHtmlEncodeMethod() or + c = this.getAJavaScriptStringEncodeMethod() or + c = this.getAnUrlEncodeMethod() ) and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() and @@ -2429,8 +2429,8 @@ class SystemWebHttpServerUtilityFlow extends LibraryTypeDataFlow, SystemWebHttpS boolean preservesValue ) { ( - c = getAnHtmlEncodeMethod() or - c = getAnUrlEncodeMethod() + c = this.getAnHtmlEncodeMethod() or + c = this.getAnUrlEncodeMethod() ) and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() and @@ -2445,8 +2445,8 @@ class SystemNetWebUtilityFlow extends LibraryTypeDataFlow, SystemNetWebUtility { boolean preservesValue ) { ( - c = getAnHtmlEncodeMethod() or - c = getAnUrlEncodeMethod() + c = this.getAnHtmlEncodeMethod() or + c = this.getAnUrlEncodeMethod() ) and source = TCallableFlowSourceArg(0) and sink = TCallableFlowSinkReturn() and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll index 44307d68e1f..4f70b53275d 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll @@ -76,9 +76,9 @@ module Ssa { override Callable getEnclosingCallable() { this = SsaImpl::TLocalVar(result, _) } - override string toString() { result = getAssignable().getName() } + override string toString() { result = this.getAssignable().getName() } - override Location getLocation() { result = getAssignable().getLocation() } + override Location getLocation() { result = this.getAssignable().getLocation() } } /** A fully qualified field or property. */ @@ -105,7 +105,7 @@ module Ssa { ) } - override Location getLocation() { result = getFirstAccess().getLocation() } + override Location getLocation() { result = this.getFirstAccess().getLocation() } } /** A plain field or property. */ @@ -115,8 +115,8 @@ module Ssa { override string toString() { exists(Assignable f, string prefix | - f = getAssignable() and - result = prefix + "." + getAssignable() + f = this.getAssignable() and + result = prefix + "." + this.getAssignable() | if f.(Modifiable).isStatic() then prefix = f.getDeclaringType().getQualifiedName() @@ -134,7 +134,7 @@ module Ssa { override SourceVariable getQualifier() { this = SsaImpl::TQualifiedFieldOrProp(_, result, _) } - override string toString() { result = getQualifier() + "." + getAssignable() } + override string toString() { result = this.getQualifier() + "." + this.getAssignable() } } } @@ -611,20 +611,20 @@ module Ssa { * and which targets the same assignable as this SSA definition. */ final AssignableDefinition getAPossibleDefinition() { - exists(Callable setter | SsaImpl::updatesNamedFieldOrProp(_, _, getCall(), _, setter) | + exists(Callable setter | SsaImpl::updatesNamedFieldOrProp(_, _, this.getCall(), _, setter) | result.getEnclosingCallable() = setter and result.getTarget() = this.getSourceVariable().getAssignable() ) or - SsaImpl::updatesCapturedVariable(_, _, getCall(), _, result, _) and + SsaImpl::updatesCapturedVariable(_, _, this.getCall(), _, result, _) and result.getTarget() = this.getSourceVariable().getAssignable() } override string toString() { - result = getToStringPrefix(this) + "SSA call def(" + getSourceVariable() + ")" + result = getToStringPrefix(this) + "SSA call def(" + this.getSourceVariable() + ")" } - override Location getLocation() { result = getCall().getLocation() } + override Location getLocation() { result = this.getCall().getLocation() } } /** @@ -649,10 +649,10 @@ module Ssa { final Definition getQualifierDefinition() { result = q } override string toString() { - result = getToStringPrefix(this) + "SSA qualifier def(" + getSourceVariable() + ")" + result = getToStringPrefix(this) + "SSA qualifier def(" + this.getSourceVariable() + ")" } - override Location getLocation() { result = getQualifierDefinition().getLocation() } + override Location getLocation() { result = this.getQualifierDefinition().getLocation() } } /** @@ -699,7 +699,7 @@ module Ssa { } override string toString() { - result = getToStringPrefix(this) + "SSA phi(" + getSourceVariable() + ")" + result = getToStringPrefix(this) + "SSA phi(" + this.getSourceVariable() + ")" } /* 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 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) 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 f43a550af57..494780d2e1b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -937,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { } override predicate relevantFor(DataFlowCallable callable) { - recordDataFlowCallSite(getCall(), callable) + recordDataFlowCallSite(this.getCall(), callable) } override predicate matchesCall(DataFlowCall call) { call = this.getCall() } @@ -1257,7 +1257,7 @@ abstract class AccessPathFront extends TAccessPathFront { TypedContent getHead() { this = TFrontHead(result) } - predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) } + predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll index f007ba939e8..067a9b94f45 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll @@ -419,9 +419,9 @@ module ExprNode { * "else" expression of this conditional expression. */ ExprNode getBranchExpr(boolean branch) { - branch = true and result = getTrueExpr() + branch = true and result = this.getTrueExpr() or - branch = false and result = getFalseExpr() + branch = false and result = this.getFalseExpr() } } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll index 558ecd1b88b..e450c11b5ab 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll @@ -28,7 +28,7 @@ class SsaReadPositionBlock extends SsaReadPosition, TSsaReadPositionBlock { /** Gets the basic block corresponding to this position. */ BasicBlock getBlock() { this = TSsaReadPositionBlock(result) } - override predicate hasReadOfVar(SsaVariable v) { getBlock() = getAReadBasicBlock(v) } + override predicate hasReadOfVar(SsaVariable v) { this.getBlock() = getAReadBasicBlock(v) } override string toString() { result = "block" } } @@ -49,8 +49,8 @@ class SsaReadPositionPhiInputEdge extends SsaReadPosition, TSsaReadPositionPhiIn /** Holds if `inp` is an input to `phi` along this edge. */ predicate phiInput(SsaPhiNode phi, SsaVariable inp) { - phi.hasInputFromBlock(inp, getOrigBlock()) and - getPhiBlock() = phi.getBasicBlock() + phi.hasInputFromBlock(inp, this.getOrigBlock()) and + this.getPhiBlock() = phi.getBasicBlock() } override string toString() { result = "edge" } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index d0b4ef45ce8..509bdfb5e04 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -11,10 +11,10 @@ private import RuntimeCallable /** A call. */ class DispatchCall extends Internal::TDispatchCall { /** Gets a textual representation of this call. */ - string toString() { result = getCall().toString() } + string toString() { result = this.getCall().toString() } /** Gets the location of this call. */ - Location getLocation() { result = getCall().getLocation() } + Location getLocation() { result = this.getCall().getLocation() } /** Gets the underlying expression of this call. */ Expr getCall() { result = Internal::getCall(this) } @@ -209,7 +209,7 @@ private module Internal { abstract Expr getArgument(int i); /** Gets the number of arguments of this call. */ - int getNumberOfArguments() { result = count(int i | exists(getArgument(i))) } + int getNumberOfArguments() { result = count(int i | exists(this.getArgument(i))) } /** Gets the qualifier of this call, if any. */ abstract Expr getQualifier(); @@ -506,12 +506,12 @@ private module Internal { } override RuntimeCallable getADynamicTarget() { - result = getAViableInherited() + result = this.getAViableInherited() or - result = getAViableOverrider() + result = this.getAViableOverrider() or // Simple case: target method cannot be overridden - result = getAStaticTarget() and + result = this.getAStaticTarget() and not result instanceof OverridableCallable } @@ -779,9 +779,9 @@ private module Internal { ) } - override Expr getQualifier() { result = getCall().getQualifier() } + override Expr getQualifier() { result = this.getCall().getQualifier() } - override Method getAStaticTarget() { result = getCall().getTarget() } + override Method getAStaticTarget() { result = this.getCall().getTarget() } } /** @@ -793,24 +793,24 @@ private module Internal { private class DispatchAccessorCall extends DispatchMethodOrAccessorCall, TDispatchAccessorCall { override AccessorCall getCall() { this = TDispatchAccessorCall(result) } - override Expr getArgument(int i) { result = getCall().getArgument(i) } + override Expr getArgument(int i) { result = this.getCall().getArgument(i) } - override Expr getQualifier() { result = getCall().(MemberAccess).getQualifier() } + override Expr getQualifier() { result = this.getCall().(MemberAccess).getQualifier() } - override Accessor getAStaticTarget() { result = getCall().getTarget() } + override Accessor getAStaticTarget() { result = this.getCall().getTarget() } override RuntimeAccessor getADynamicTarget() { result = DispatchMethodOrAccessorCall.super.getADynamicTarget() and // Calls to accessors may have `dynamic` expression arguments, // so we need to check that the types match - forall(Type argumentType, int i | hasDynamicArg(i, argumentType) | + forall(Type argumentType, int i | this.hasDynamicArg(i, argumentType) | argumentType.isImplicitlyConvertibleTo(result.getParameter(i).getType()) ) } private predicate hasDynamicArg(int i, Type argumentType) { exists(Expr argument | - argument = getArgument(i) and + argument = this.getArgument(i) and argument.stripImplicitCasts().getType() instanceof DynamicType and argumentType = getAPossibleType(argument, _) ) @@ -896,7 +896,7 @@ private module Internal { // names and number of parameters. This set is further reduced in // `getADynamicTarget()` by taking type information into account. override Callable getAStaticTarget() { - result = getACallableWithMatchingName() and + result = this.getACallableWithMatchingName() and exists(int minArgs | minArgs = count(Parameter p | @@ -904,16 +904,19 @@ private module Internal { not p.hasDefaultValue() and not p.isParams() ) and - getNumberOfArguments() >= minArgs and - (result.(Method).hasParams() or getNumberOfArguments() <= result.getNumberOfParameters()) + this.getNumberOfArguments() >= minArgs and + ( + result.(Method).hasParams() or + this.getNumberOfArguments() <= result.getNumberOfParameters() + ) ) } private RuntimeCallable getACallableWithMatchingName() { - result.(Operator).getFunctionName() = getName() + result.(Operator).getFunctionName() = this.getName() or not result instanceof Operator and - result.getUndecoratedName() = getName() + result.getUndecoratedName() = this.getName() } // A callable is viable if the following conditions are all satisfied: @@ -987,7 +990,7 @@ private module Internal { * type of one of the arguments. */ RuntimeCallable getADynamicTargetCandidate() { - result = getAStaticTarget() and + result = this.getAStaticTarget() and ( result = getADynamicTargetCandidateInstanceMethod(this.getAQualifierType()) or @@ -999,13 +1002,13 @@ private module Internal { result instanceof RuntimeInstanceAccessor and this.hasUnknownQualifierType() or - result = getADynamicTargetCandidateOperator() + result = this.getADynamicTargetCandidateOperator() ) } pragma[noinline] private RuntimeOperator getADynamicTargetCandidateOperator() { - result = getAStaticTarget() and + result = this.getAStaticTarget() and result.getDeclaringType() = result.getAParameter().getType() } } @@ -1138,8 +1141,8 @@ private module Internal { result = DispatchReflectionOrDynamicCall.super.getADynamicTargetCandidate() or // Static callables can be called using reflection as well - result = getAStaticTarget() and - result.getDeclaringType() = getStaticType() and + result = this.getAStaticTarget() and + result.getDeclaringType() = this.getStaticType() and result.(Modifiable).isStatic() } @@ -1147,7 +1150,7 @@ private module Internal { override Expr getArgument(int i) { exists(int args, ArrayCreation ac | this = TDispatchReflectionCall(_, _, _, _, args) and - ac = getAMethodCallArgSource(getCall().getArgument(args)) and + ac = getAMethodCallArgSource(this.getCall().getArgument(args)) and result = ac.getInitializer().getElement(i) ) } @@ -1158,20 +1161,20 @@ private module Internal { TDispatchDynamicMethodCall { override DynamicMethodCall getCall() { this = TDispatchDynamicMethodCall(result) } - override string getName() { result = getCall().getLateBoundTargetName() } + override string getName() { result = this.getCall().getLateBoundTargetName() } - override Expr getQualifier() { result = getCall().getQualifier() } + override Expr getQualifier() { result = this.getCall().getQualifier() } override RuntimeMethod getADynamicTargetCandidate() { - if exists(getCall().getTarget()) + if exists(this.getCall().getTarget()) then // static method call - result = getCall().getTarget() + result = this.getCall().getTarget() else result = DispatchReflectionOrDynamicCall.super.getADynamicTargetCandidate() } // Does not take named arguments into account - override Expr getArgument(int i) { result = getCall().getArgument(i) } + override Expr getArgument(int i) { result = this.getCall().getArgument(i) } } /** An operator call using dynamic types. */ @@ -1181,14 +1184,14 @@ private module Internal { override string getName() { exists(Operator o | - o.getName() = getCall().getLateBoundTargetName() and + o.getName() = this.getCall().getLateBoundTargetName() and result = o.getFunctionName() ) } override Expr getQualifier() { none() } - override Expr getArgument(int i) { result = getCall().getArgument(i) } + override Expr getArgument(int i) { result = this.getCall().getArgument(i) } } /** A (potential) call to a property accessor using dynamic types. */ @@ -1255,7 +1258,7 @@ private module Internal { any(DynamicMemberAccess dma | this = TDispatchDynamicEventAccess(_, dma, _)).getQualifier() } - override Expr getArgument(int i) { i = 0 and result = getCall().getRValue() } + override Expr getArgument(int i) { i = 0 and result = this.getCall().getRValue() } } /** A call to a constructor using dynamic types. */ @@ -1267,9 +1270,9 @@ private module Internal { override Expr getQualifier() { none() } - override Expr getArgument(int i) { result = getCall().getArgument(i) } + override Expr getArgument(int i) { result = this.getCall().getArgument(i) } - override RuntimeCallable getADynamicTargetCandidate() { result = getCall().getTarget() } + override RuntimeCallable getADynamicTargetCandidate() { result = this.getCall().getTarget() } } /** A call where the target can be resolved statically. */ @@ -1285,8 +1288,8 @@ private module Internal { ) } - override Callable getAStaticTarget() { result = getCall().getTarget() } + override Callable getAStaticTarget() { result = this.getCall().getTarget() } - override RuntimeCallable getADynamicTarget() { result = getCall().getTarget() } + override RuntimeCallable getADynamicTarget() { result = this.getCall().getTarget() } } } diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll index 4913ea2bc3c..dc963881cbf 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll @@ -58,13 +58,13 @@ class OverridableCallable extends Callable { * `I.M.getAnImplementorSubType(D) = C.M`. */ private Callable getAnImplementorSubType(ValueOrRefType t) { - result = getAnImplementor(t) + result = this.getAnImplementor(t) or exists(ValueOrRefType mid | - result = getAnImplementorSubType(mid) and + result = this.getAnImplementorSubType(mid) and t.getBaseClass() = mid and // There must be no other implementation of this callable in `t` - forall(Callable other | other = getAnImplementor(t) | other = result) + forall(Callable other | other = this.getAnImplementor(t) | other = result) ) } @@ -107,8 +107,8 @@ class OverridableCallable extends Callable { * implements this interface callable, if any. */ private Callable getAnOverridingImplementor() { - result = getAnUltimateImplementor() and - not result = getAnImplementor(_) + result = this.getAnUltimateImplementor() and + not result = this.getAnImplementor(_) } /** @@ -150,10 +150,10 @@ class OverridableCallable extends Callable { } private Callable getInherited1(ValueOrRefType t) { - result = getInherited0(t) + result = this.getInherited0(t) or // An interface implementation - result = getAnImplementorSubType(t) + result = this.getAnImplementorSubType(t) } pragma[noinline] @@ -171,7 +171,7 @@ class OverridableCallable extends Callable { private predicate isDeclaringSubType(ValueOrRefType t) { t = this.getDeclaringType() or - exists(ValueOrRefType mid | isDeclaringSubType(mid) | t = mid.getASubType()) + exists(ValueOrRefType mid | this.isDeclaringSubType(mid) | t = mid.getASubType()) } pragma[noinline] @@ -232,7 +232,7 @@ class OverridableAccessor extends Accessor, OverridableCallable { override Accessor getAnImplementor(ValueOrRefType t) { exists(Virtualizable implementor, int kind | - getAnImplementorAux(t, implementor, kind) and + this.getAnImplementorAux(t, implementor, kind) and result.getDeclaration() = implementor and getAccessorKind(result) = kind ) @@ -241,7 +241,7 @@ class OverridableAccessor extends Accessor, OverridableCallable { // predicate folding to get proper join order private predicate getAnImplementorAux(ValueOrRefType t, Virtualizable implementor, int kind) { exists(Virtualizable implementee | - implementee = getDeclaration() and + implementee = this.getDeclaration() and kind = getAccessorKind(this) and implementor = implementee.getAnImplementor(t) ) @@ -249,7 +249,7 @@ class OverridableAccessor extends Accessor, OverridableCallable { override Accessor getAnUltimateImplementor() { exists(Virtualizable implementor, int kind | - getAnUltimateImplementorAux(implementor, kind) and + this.getAnUltimateImplementorAux(implementor, kind) and result.getDeclaration() = implementor and getAccessorKind(result) = kind ) @@ -258,7 +258,7 @@ class OverridableAccessor extends Accessor, OverridableCallable { // predicate folding to get proper join order private predicate getAnUltimateImplementorAux(Virtualizable implementor, int kind) { exists(Virtualizable implementee | - implementee = getDeclaration() and + implementee = this.getDeclaration() and kind = getAccessorKind(this) and implementor = implementee.getAnUltimateImplementor() ) diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll index ab3ea182056..9d7cf3a5867 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll @@ -115,7 +115,7 @@ class MemberAccess extends Access, QualifiableExpr, @member_access_expr { not exists(MemberInitializer mi | mi.getLValue() = this) } - override Member getQualifiedDeclaration() { result = getTarget() } + override Member getQualifiedDeclaration() { result = this.getTarget() } override Member getTarget() { none() } } @@ -147,8 +147,8 @@ class AssignableAccess extends Access, @assignable_access_expr { * or a `ref` argument in a method call. */ predicate isOutOrRefArgument() { - isOutArgument() or - isRefArgument() + this.isOutArgument() or + this.isRefArgument() } /** @@ -507,7 +507,7 @@ class ElementAccess extends AssignableAccess, QualifiableExpr, @element_access_e * Gets an index expression of this element access, for example * `1` in `x[0, 1]`. */ - Expr getAnIndex() { result = getIndex(_) } + Expr getAnIndex() { result = this.getIndex(_) } /** * Gets the `i`th index expression of this element access, for example the @@ -515,7 +515,7 @@ class ElementAccess extends AssignableAccess, QualifiableExpr, @element_access_e */ Expr getIndex(int i) { result = this.getChild(i) and i >= 0 } - override Assignable getQualifiedDeclaration() { result = getTarget() } + override Assignable getQualifiedDeclaration() { result = this.getTarget() } } /** @@ -615,7 +615,7 @@ class IndexerWrite extends IndexerAccess, ElementWrite { } * ``` */ class VirtualIndexerAccess extends IndexerAccess { - VirtualIndexerAccess() { targetIsOverridableOrImplementable() } + VirtualIndexerAccess() { this.targetIsOverridableOrImplementable() } } /** @@ -647,7 +647,7 @@ library class EventAccessExpr extends Expr, @event_access_expr { * ``` */ class EventAccess extends AssignableMemberAccess, EventAccessExpr { - override Event getTarget() { result = getEvent() } + override Event getTarget() { result = this.getEvent() } override string getAPrimaryQlClass() { result = "EventAccess" } } @@ -707,7 +707,7 @@ class EventWrite extends EventAccess, AssignableWrite { } * ``` */ class VirtualEventAccess extends EventAccess { - VirtualEventAccess() { targetIsOverridableOrImplementable() } + VirtualEventAccess() { this.targetIsOverridableOrImplementable() } } /** @@ -787,7 +787,7 @@ class LocalFunctionAccess extends CallableAccess { * ``` */ class VirtualMethodAccess extends MethodAccess { - VirtualMethodAccess() { targetIsOverridableOrImplementable() } + VirtualMethodAccess() { this.targetIsOverridableOrImplementable() } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/ArithmeticOperation.qll b/csharp/ql/lib/semmle/code/csharp/exprs/ArithmeticOperation.qll index ac98c0eafcf..f20bfba1589 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/ArithmeticOperation.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/ArithmeticOperation.qll @@ -138,10 +138,10 @@ class DivExpr extends BinaryArithmeticOperation, @div_expr { override string getOperator() { result = "/" } /** Gets the numerator of this division operation. */ - Expr getNumerator() { result = getLeftOperand() } + Expr getNumerator() { result = this.getLeftOperand() } /** Gets the denominator of this division operation. */ - Expr getDenominator() { result = getRightOperand() } + Expr getDenominator() { result = this.getRightOperand() } override string getAPrimaryQlClass() { result = "DivExpr" } } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll index 88ef770160a..562a4dd9cd5 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll @@ -27,7 +27,7 @@ class Assignment extends Operation, @assign_expr { Expr getRValue() { result = this.getChild(0) } /** Gets the variable being assigned to, if any. */ - Variable getTargetVariable() { result.getAnAccess() = getLValue() } + Variable getTargetVariable() { result.getAnAccess() = this.getLValue() } override string getOperator() { none() } } @@ -38,7 +38,7 @@ class Assignment extends Operation, @assign_expr { class LocalVariableDeclAndInitExpr extends LocalVariableDeclExpr, Assignment { override string getOperator() { result = "=" } - override LocalVariable getTargetVariable() { result = getVariable() } + override LocalVariable getTargetVariable() { result = this.getVariable() } override LocalVariableAccess getLValue() { result = Assignment.super.getLValue() } @@ -86,7 +86,7 @@ class AssignOperation extends Assignment, @assign_op_expr { * If an expanded version exists, then it is used in the control * flow graph. */ - predicate hasExpandedAssignment() { exists(getExpandedAssignment()) } + predicate hasExpandedAssignment() { exists(this.getExpandedAssignment()) } override string toString() { result = "... " + this.getOperator() + " ..." } } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll index 6dc88e941ef..a4c4ab1b670 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll @@ -47,7 +47,7 @@ class Call extends DotNet::Call, Expr, @call { override Expr getRawArgument(int i) { result = this.getArgument(i) } - override Expr getAnArgument() { result = getArgument(_) } + override Expr getAnArgument() { result = this.getArgument(_) } /** Gets the number of arguments of this call. */ int getNumberOfArguments() { result = count(this.getAnArgument()) } @@ -80,7 +80,7 @@ class Call extends DotNet::Call, Expr, @call { */ cached override Expr getArgumentForParameter(DotNet::Parameter p) { - getTarget().getAParameter() = p and + this.getTarget().getAParameter() = p and ( // Appears in the positional part of the call result = this.getImplicitArgument(p.getPosition()) and @@ -94,7 +94,7 @@ class Call extends DotNet::Call, Expr, @call { ) or // Appears in the named part of the call - result = getExplicitArgument(p.getName()) and + result = this.getExplicitArgument(p.getName()) and (p.(Parameter).isParams() implies isValidExplicitParamsType(p, result.getType())) ) } @@ -112,13 +112,13 @@ class Call extends DotNet::Call, Expr, @call { pragma[noinline] private Expr getImplicitArgument(int pos) { - result = getArgument(pos) and + result = this.getArgument(pos) and not exists(result.getExplicitArgumentName()) } pragma[nomagic] private Expr getExplicitArgument(string name) { - result = getAnArgument() and + result = this.getAnArgument() and result.getExplicitArgumentName() = name } @@ -131,7 +131,7 @@ class Call extends DotNet::Call, Expr, @call { */ Expr getArgumentForName(string name) { exists(Parameter p | - result = getArgumentForParameter(p) and + result = this.getArgumentForParameter(p) and p.hasName(name) ) } @@ -219,7 +219,7 @@ class Call extends DotNet::Call, Expr, @call { */ Expr getRuntimeArgumentForParameter(Parameter p) { exists(Callable c | - c = getARuntimeTarget() and + c = this.getARuntimeTarget() and p = c.getAParameter() and result = this.getRuntimeArgument(p.getPosition()) ) @@ -231,7 +231,7 @@ class Call extends DotNet::Call, Expr, @call { */ Expr getRuntimeArgumentForName(string name) { exists(Parameter p | - result = getRuntimeArgumentForParameter(p) and + result = this.getRuntimeArgumentForParameter(p) and p.hasName(name) ) } @@ -240,19 +240,19 @@ class Call extends DotNet::Call, Expr, @call { * Gets an argument that corresponds to a parameter of a potential * run-time target of this call. */ - Expr getARuntimeArgument() { result = getRuntimeArgument(_) } + Expr getARuntimeArgument() { result = this.getRuntimeArgument(_) } /** * Gets the number of arguments that correspond to a parameter of a potential * run-time target of this call. */ - int getNumberOfRuntimeArguments() { result = count(getARuntimeArgument()) } + int getNumberOfRuntimeArguments() { result = count(this.getARuntimeArgument()) } /** * Holds if this call has no arguments that correspond to a parameter of a * potential (run-time) target of this call. */ - predicate hasNoRuntimeArguments() { not exists(getARuntimeArgument()) } + predicate hasNoRuntimeArguments() { not exists(this.getARuntimeArgument()) } override string toString() { result = "call" } } @@ -295,19 +295,19 @@ private predicate isValidExplicitParamsType(Parameter p, Type t) { class MethodCall extends Call, QualifiableExpr, LateBindableExpr, @method_invocation_expr { override Method getTarget() { expr_call(this, result) } - override Method getQualifiedDeclaration() { result = getTarget() } + override Method getQualifiedDeclaration() { result = this.getTarget() } override string toString() { result = "call to method " + concat(this.getTarget().getName()) } override string getAPrimaryQlClass() { result = "MethodCall" } override Expr getRawArgument(int i) { - if exists(getQualifier()) + if exists(this.getQualifier()) then - i = 0 and result = getQualifier() + i = 0 and result = this.getQualifier() or - result = getArgument(i - 1) - else result = getArgument(i) + result = this.getArgument(i - 1) + else result = this.getArgument(i) } } @@ -336,7 +336,7 @@ class ExtensionMethodCall extends MethodCall { override Expr getArgument(int i) { exists(int j | result = this.getChildExpr(j) | - if isOrdinaryStaticCall() then (j = i and j >= 0) else (j = i - 1 and j >= -1) + if this.isOrdinaryStaticCall() then (j = i and j >= 0) else (j = i - 1 and j >= -1) ) } @@ -379,8 +379,8 @@ class ExtensionMethodCall extends MethodCall { */ class VirtualMethodCall extends MethodCall { VirtualMethodCall() { - not getQualifier() instanceof BaseAccess and - getTarget().isOverridableOrImplementable() + not this.getQualifier() instanceof BaseAccess and + this.getTarget().isOverridableOrImplementable() } } @@ -573,7 +573,7 @@ class DelegateLikeCall extends Call, DelegateLikeCall_ { ) } - override Expr getRuntimeArgument(int i) { result = getArgument(i) } + override Expr getRuntimeArgument(int i) { result = this.getArgument(i) } } /** @@ -618,11 +618,11 @@ class DelegateCall extends DelegateLikeCall, @delegate_invocation_expr { } deprecated private AddEventSource getAnAddEventSourceSameEnclosingCallable() { - result = getAnAddEventSource(this.getEnclosingCallable()) + result = this.getAnAddEventSource(this.getEnclosingCallable()) } deprecated private AddEventSource getAnAddEventSourceDifferentEnclosingCallable() { - exists(Callable c | result = getAnAddEventSource(c) | c != this.getEnclosingCallable()) + exists(Callable c | result = this.getAnAddEventSource(c) | c != this.getEnclosingCallable()) } /** @@ -683,7 +683,7 @@ class AccessorCall extends Call, QualifiableExpr, @call_access_expr { */ class PropertyCall extends AccessorCall, PropertyAccessExpr { override Accessor getTarget() { - exists(PropertyAccess pa, Property p | pa = this and p = getProperty() | + exists(PropertyAccess pa, Property p | pa = this and p = this.getProperty() | pa instanceof AssignableRead and result = p.getGetter() or pa instanceof AssignableWrite and result = p.getSetter() @@ -718,7 +718,7 @@ class PropertyCall extends AccessorCall, PropertyAccessExpr { */ class IndexerCall extends AccessorCall, IndexerAccessExpr { override Accessor getTarget() { - exists(IndexerAccess ia, Indexer i | ia = this and i = getIndexer() | + exists(IndexerAccess ia, Indexer i | ia = this and i = this.getIndexer() | ia instanceof AssignableRead and result = i.getGetter() or ia instanceof AssignableWrite and result = i.getSetter() @@ -761,7 +761,7 @@ class IndexerCall extends AccessorCall, IndexerAccessExpr { class EventCall extends AccessorCall, EventAccessExpr { override EventAccessor getTarget() { exists(Event e, AddOrRemoveEventExpr aoree | - e = getEvent() and + e = this.getEvent() and aoree.getLValue() = this | aoree instanceof AddEventExpr and result = e.getAddEventAccessor() @@ -799,7 +799,7 @@ class EventCall extends AccessorCall, EventAccessExpr { class LocalFunctionCall extends Call, @local_function_invocation_expr { override LocalFunction getTarget() { expr_call(this, result) } - override string toString() { result = "call to local function " + getTarget().getName() } + override string toString() { result = "call to local function " + this.getTarget().getName() } override string getAPrimaryQlClass() { result = "LocalFunctionCall" } } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll index c9ae3919004..84bcf7b87bc 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll @@ -45,7 +45,7 @@ class ObjectInitializer extends ObjectOrCollectionInitializer, @object_init_expr * } * ``` */ - MemberInitializer getAMemberInitializer() { result = getMemberInitializer(_) } + MemberInitializer getAMemberInitializer() { result = this.getMemberInitializer(_) } /** * Gets the `i`th member initializer of this object initializer. For example, @@ -122,7 +122,7 @@ class CollectionInitializer extends ObjectOrCollectionInitializer, @collection_i * }; * ``` */ - ElementInitializer getAnElementInitializer() { result = getElementInitializer(_) } + ElementInitializer getAnElementInitializer() { result = this.getElementInitializer(_) } /** * Gets the `i`th element initializer of this collection initializer, for @@ -180,7 +180,7 @@ class ElementInitializer extends MethodCall { */ class ObjectCreation extends Call, LateBindableExpr, @object_creation_expr { /** Gets the type of the newly created object. */ - ValueOrRefType getObjectType() { result = getType() } + ValueOrRefType getObjectType() { result = this.getType() } override Constructor getTarget() { expr_call(this, result) } @@ -320,7 +320,7 @@ class ArrayInitializer extends Expr, @array_init_expr { * }; * ``` */ - Expr getAnElement() { result = getElement(_) } + Expr getAnElement() { result = this.getElement(_) } /** * Gets the `i`th element of this array initializer, for example the second @@ -365,7 +365,7 @@ class ArrayCreation extends Expr, @array_creation_expr { * new int[5, 10] * ``` */ - Expr getALengthArgument() { result = getLengthArgument(_) } + Expr getALengthArgument() { result = this.getLengthArgument(_) } /** * Gets the `i`th dimension's length argument of this array creation, for @@ -427,7 +427,7 @@ class AnonymousFunctionExpr extends Expr, Callable, Modifiable, @anonymous_funct override string toString() { result = Expr.super.toString() } - override string toStringWithTypes() { result = toString() } + override string toStringWithTypes() { result = this.toString() } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll index ea6012ca3e1..eda31432f38 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll @@ -15,7 +15,7 @@ private import semmle.code.csharp.dispatch.Dispatch * (`DynamicAccessorCall`), or a dynamic element access (`DynamicElementAccess`). */ class DynamicExpr extends LateBindableExpr { - DynamicExpr() { isLateBound() } + DynamicExpr() { this.isLateBound() } } /** @@ -67,7 +67,7 @@ class DynamicObjectCreation extends DynamicExpr, ObjectCreation { * may not be known at compile-time (as in the example above). */ class DynamicMethodCall extends DynamicExpr, MethodCall { - override string toString() { result = "dynamic call to method " + getLateBoundTargetName() } + override string toString() { result = "dynamic call to method " + this.getLateBoundTargetName() } override string getAPrimaryQlClass() { result = "DynamicMethodCall" } } @@ -97,7 +97,9 @@ class DynamicMethodCall extends DynamicExpr, MethodCall { * target operator may not be known at compile-time (as in the example above). */ class DynamicOperatorCall extends DynamicExpr, OperatorCall { - override string toString() { result = "dynamic call to operator " + getLateBoundTargetName() } + override string toString() { + result = "dynamic call to operator " + this.getLateBoundTargetName() + } override string getAPrimaryQlClass() { result = "DynamicOperatorCall" } } @@ -189,7 +191,9 @@ class DynamicAccess extends DynamicExpr { */ class DynamicMemberAccess extends DynamicAccess, MemberAccess, AssignableAccess, @dynamic_member_access_expr { - override string toString() { result = "dynamic access to member " + getLateBoundTargetName() } + override string toString() { + result = "dynamic access to member " + this.getLateBoundTargetName() + } override string getAPrimaryQlClass() { result = "DynamicMemberAccess" } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll index 0988bb84340..47477afe2b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll @@ -103,7 +103,7 @@ class Expr extends DotNet::Expr, ControlFlowElement, @expr { class LateBindableExpr extends Expr, @late_bindable_expr { /** Holds if this expression is late bound. */ predicate isLateBound() { - exists(getLateBoundTargetName()) or + exists(this.getLateBoundTargetName()) or isDynamicMemberAccess(this) or isDynamicElementAccess(this) } @@ -221,9 +221,9 @@ class BinaryOperation extends Operation, @bin_op { /** Gets the other operand of this binary operation, given operand `o`. */ Expr getOtherOperand(Expr o) { - o = getLeftOperand() and result = getRightOperand() + o = this.getLeftOperand() and result = this.getRightOperand() or - o = getRightOperand() and result = getLeftOperand() + o = this.getRightOperand() and result = this.getLeftOperand() } override string getOperator() { none() } @@ -368,7 +368,7 @@ class RelationalPatternExpr extends PatternExpr, @relational_pattern_expr { /** Gets the expression of this relational pattern. */ Expr getExpr() { result = this.getChild(0) } - override string toString() { result = getOperator() + " ..." } + override string toString() { result = this.getOperator() + " ..." } } /** A less-than pattern, for example `< 10` in `x is < 10`. */ @@ -520,7 +520,7 @@ class NotPatternExpr extends UnaryPatternExpr, @not_pattern_expr { /** A binary pattern. For example, `1 or 2`. */ class BinaryPatternExpr extends PatternExpr, @binary_pattern_expr { /** Gets a pattern. */ - PatternExpr getAnOperand() { result = getLeftOperand() or result = getRightOperand() } + PatternExpr getAnOperand() { result = this.getLeftOperand() or result = this.getRightOperand() } /** Gets the left pattern. */ PatternExpr getLeftOperand() { result = this.getChild(0) } @@ -743,7 +743,7 @@ class DefaultValueExpr extends Expr, @default_expr { TypeAccess getTypeAccess() { result = this.getChild(0) } override string toString() { - if exists(getTypeAccess()) then result = "default(...)" else result = "default" + if exists(this.getTypeAccess()) then result = "default(...)" else result = "default" } override string getAPrimaryQlClass() { result = "DefaultValueExpr" } @@ -757,7 +757,7 @@ class SizeofExpr extends UnaryOperation, @sizeof_expr { * Gets the type access in this `sizeof` expression, for example `int` in * `sizeof(int)`. */ - TypeAccess getTypeAccess() { result = getOperand() } + TypeAccess getTypeAccess() { result = this.getOperand() } override string getOperator() { result = "sizeof(..)" } @@ -830,7 +830,7 @@ class AddressOfExpr extends UnaryOperation, @address_of_expr { */ class AwaitExpr extends Expr, @await_expr { /** Gets the expression being awaited. */ - Expr getExpr() { result = getChild(0) } + Expr getExpr() { result = this.getChild(0) } override string toString() { result = "await ..." } @@ -881,7 +881,7 @@ class InterpolatedStringExpr extends Expr, @interpolated_string_expr { * element (`getText(0)` gets the text). */ Expr getInsert(int i) { - result = getChild(i) and + result = this.getChild(i) and not result instanceof StringLiteral } @@ -891,13 +891,13 @@ class InterpolatedStringExpr extends Expr, @interpolated_string_expr { * `$"Hello, {name}!"`. Note that there is no text element at index `i = 1`, * but instead an insert (`getInsert(1)` gets the insert). */ - StringLiteral getText(int i) { result = getChild(i) } + StringLiteral getText(int i) { result = this.getChild(i) } /** Gets an insert in this interpolated string. */ - Expr getAnInsert() { result = getInsert(_) } + Expr getAnInsert() { result = this.getInsert(_) } /** Gets a text element in this interpolated string. */ - StringLiteral getAText() { result = getText(_) } + StringLiteral getAText() { result = this.getText(_) } } /** @@ -914,7 +914,7 @@ class ThrowElement extends ControlFlowElement, DotNet::Throw, @throw_element { /** Gets the type of exception being thrown. */ Class getThrownExceptionType() { - result = getExpr().getType() + result = this.getExpr().getType() or // Corner case: `throw null` this.getExpr().getType() instanceof NullType and @@ -958,7 +958,7 @@ class QualifiableExpr extends Expr, @qualifiable_expr { Expr getQualifier() { result = this.getChildExpr(-1) } /** Holds if this expression is qualified. */ - final predicate hasQualifier() { exists(getQualifier()) } + final predicate hasQualifier() { exists(this.getQualifier()) } /** Holds if this expression has an implicit `this` qualifier. */ predicate hasImplicitThisQualifier() { this.getQualifier().(ThisAccess).isImplicit() } @@ -1029,10 +1029,10 @@ class TupleExpr extends Expr, @tuple_expr { override string toString() { result = "(..., ...)" } /** Gets the `i`th argument of this tuple. */ - Expr getArgument(int i) { result = getChild(i) } + Expr getArgument(int i) { result = this.getChild(i) } /** Gets an argument of this tuple. */ - Expr getAnArgument() { result = getArgument(_) } + Expr getAnArgument() { result = this.getArgument(_) } /** Holds if this tuple is a read access. */ deprecated predicate isReadAccess() { not this = getAnAssignOrForeachChild() } @@ -1057,11 +1057,11 @@ class TupleExpr extends Expr, @tuple_expr { */ class RefExpr extends Expr, @ref_expr { /** Gets the expression being referenced. */ - Expr getExpr() { result = getChild(0) } + Expr getExpr() { result = this.getChild(0) } override string toString() { result = "ref ..." } - override Type getType() { result = getExpr().getType() } + override Type getType() { result = this.getExpr().getType() } override string getAPrimaryQlClass() { result = "RefExpr" } } @@ -1154,7 +1154,7 @@ class DefineSymbolExpr extends Expr, @define_symbol_expr { /** Gets the name of the symbol. */ string getName() { directive_define_symbols(this, result) } - override string toString() { result = getName() } + override string toString() { result = this.getName() } override string getAPrimaryQlClass() { result = "DefineSymbolExpr" } } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Literal.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Literal.qll index 0ca9f6d0db0..842e27fb96b 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Literal.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Literal.qll @@ -23,9 +23,9 @@ class Literal extends DotNet::Literal, Expr, @literal_expr { class BoolLiteral extends Literal, @bool_literal_expr { /** Gets the value of this Boolean literal. */ boolean getBoolValue() { - getValue() = "true" and result = true + this.getValue() = "true" and result = true or - getValue() = "false" and result = false + this.getValue() = "false" and result = false } override string getAPrimaryQlClass() { result = "BoolLiteral" } @@ -105,7 +105,7 @@ class DecimalLiteral extends RealLiteral, @decimal_literal_expr { * A `string` literal, for example `"Hello, World!"`. */ class StringLiteral extends DotNet::StringLiteral, Literal, @string_literal_expr { - override string toString() { result = "\"" + getValue().replaceAll("\"", "\\\"") + "\"" } + override string toString() { result = "\"" + this.getValue().replaceAll("\"", "\\\"") + "\"" } override string getAPrimaryQlClass() { result = "StringLiteral" } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll index 36882d3b12e..ab35b32d43e 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll @@ -317,7 +317,7 @@ module EntityFramework { dist = 0 ) or - step(_, _, c1, t1, dist - 1) and + this.step(_, _, c1, t1, dist - 1) and dist < DataFlowPrivate::accessPathLimit() - 1 and not isNotMapped(t2) and ( @@ -374,11 +374,11 @@ module EntityFramework { } private predicate stepRev(Content c1, Type t1, Content c2, Type t2, int dist) { - step(c1, t1, c2, t2, dist) and - c2.(PropertyContent).getProperty() = getAColumnProperty(dist) + this.step(c1, t1, c2, t2, dist) and + c2.(PropertyContent).getProperty() = this.getAColumnProperty(dist) or - stepRev(c2, t2, _, _, dist + 1) and - step(c1, t1, c2, t2, dist) + this.stepRev(c2, t2, _, _, dist + 1) and + this.step(c1, t1, c2, t2, dist) } /** Gets a `SaveChanges[Async]` method. */ @@ -453,8 +453,8 @@ module EntityFramework { ) { exists(Property mapped | preservesValue = true and - input(input, mapped) and - output(output, mapped) + this.input(input, mapped) and + this.output(output, mapped) ) } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll index 3c659d86d46..2ffbfe6e7e1 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll @@ -155,13 +155,13 @@ class InvalidFormatString extends StringLiteral { int oldstartcolumn, int padding | this.getLocation().hasLocationInfo(filepath, startline, oldstartcolumn, endline, endcolumn) and - startcolumn = padding + oldstartcolumn + getInvalidOffset() and + startcolumn = padding + oldstartcolumn + this.getInvalidOffset() and toUrl(filepath, startline, startcolumn, endline, endcolumn, result) | // Single-line string literal beginning " or @" // Figure out the correct indent. startline = endline and - padding = endcolumn - oldstartcolumn - getValue().length() + padding = endcolumn - oldstartcolumn - this.getValue().length() or // Multi-line literal beginning @" startline != endline and diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/JsonNET.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/JsonNET.qll index abd820bdfe4..575f78bd524 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/JsonNET.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/JsonNET.qll @@ -62,25 +62,25 @@ module JsonNET { boolean preservesValue ) { // ToString methods - c = getAToStringMethod() and + c = this.getAToStringMethod() and preservesValue = false and source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and sink instanceof CallableFlowSinkReturn or // Deserialize methods - c = getADeserializeMethod() and + c = this.getADeserializeMethod() and preservesValue = false and source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and sink instanceof CallableFlowSinkReturn or // Serialize methods - c = getASerializeMethod() and + c = this.getASerializeMethod() and preservesValue = false and source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and sink instanceof CallableFlowSinkReturn or // Populate methods - c = getAPopulateMethod() and + c = this.getAPopulateMethod() and preservesValue = false and source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and sink = any(CallableFlowSinkArg arg | arg.getArgumentIndex() = 1) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll index 92811122696..e0705ac7d98 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll @@ -21,7 +21,7 @@ class ReturnsMethod extends Method { */ Expr getAReturnedExpr() { exists(MethodCall mc, Expr arg | - mc = getACall() and + mc = this.getACall() and arg = mc.getArgument(0) | if arg instanceof LambdaExpr then arg.(LambdaExpr).canReturn(result) else result = arg diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/System.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/System.qll index 20ab350ffd4..e33004f109d 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/System.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/System.qll @@ -157,7 +157,7 @@ class SystemIComparableTInterface extends SystemUnboundGenericInterface { result.getDeclaringType() = this and result.hasName("CompareTo") and result.getNumberOfParameters() = 1 and - result.getParameter(0).getType() = getTypeParameter(0) and + result.getParameter(0).getType() = this.getTypeParameter(0) and result.getReturnType() instanceof IntType } } @@ -171,7 +171,7 @@ class SystemIEquatableTInterface extends SystemUnboundGenericInterface { result.getDeclaringType() = this and result.hasName("Equals") and result.getNumberOfParameters() = 1 and - result.getParameter(0).getType() = getTypeParameter(0) and + result.getParameter(0).getType() = this.getTypeParameter(0) and result.getReturnType() instanceof BoolType } } @@ -239,7 +239,7 @@ class SystemLazyClass extends SystemUnboundGenericClass { Property getValueProperty() { result.getDeclaringType() = this and result.hasName("Value") and - result.getType() = getTypeParameter(0) + result.getType() = this.getTypeParameter(0) } } @@ -254,7 +254,7 @@ class SystemNullableStruct extends SystemUnboundGenericStruct { Property getValueProperty() { result.getDeclaringType() = this and result.hasName("Value") and - result.getType() = getTypeParameter(0) + result.getType() = this.getTypeParameter(0) } /** Gets the `HasValue` property. */ @@ -268,7 +268,7 @@ class SystemNullableStruct extends SystemUnboundGenericStruct { Method getAGetValueOrDefaultMethod() { result.getDeclaringType() = this and result.hasName("GetValueOrDefault") and - result.getReturnType() = getTypeParameter(0) + result.getReturnType() = this.getTypeParameter(0) } } @@ -588,7 +588,7 @@ class IEquatableEqualsMethod extends Method { m = any(SystemIEquatableTInterface i).getAConstructedGeneric().getAMethod() and m.getUnboundDeclaration() = any(SystemIEquatableTInterface i).getEqualsMethod() | - this = m or getAnUltimateImplementee() = m + this = m or this.getAnUltimateImplementee() = m ) } } @@ -677,7 +677,7 @@ class DisposeMethod extends Method { /** A method with the signature `void Dispose(bool)`. */ library class DisposeBoolMethod extends Method { DisposeBoolMethod() { - hasName("Dispose") and + this.hasName("Dispose") and this.getReturnType() instanceof VoidType and this.getNumberOfParameters() = 1 and this.getParameter(0).getType() instanceof BoolType diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/WCF.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/WCF.qll index 655648d88c9..befb5f3ae1f 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/WCF.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/WCF.qll @@ -49,7 +49,7 @@ class OperationMethod extends Method { i.getAnAttribute() instanceof ServiceContractAttribute and m.getDeclaringType() = i and m.getAnAttribute() instanceof OperationContractAttribute and - getImplementee() = m + this.getImplementee() = m ) } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll index 5fe6665bd47..a918b603818 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll @@ -6,129 +6,133 @@ import semmle.code.csharp.frameworks.Microsoft /** The `Microsoft.AspNetCore` namespace. */ class MicrosoftAspNetCoreNamespace extends Namespace { MicrosoftAspNetCoreNamespace() { - getParentNamespace() instanceof MicrosoftNamespace and - hasName("AspNetCore") + this.getParentNamespace() instanceof MicrosoftNamespace and + this.hasName("AspNetCore") } } /** The `Microsoft.AspNetCore.Mvc` namespace. */ class MicrosoftAspNetCoreMvcNamespace extends Namespace { MicrosoftAspNetCoreMvcNamespace() { - getParentNamespace() instanceof MicrosoftAspNetCoreNamespace and - hasName("Mvc") + this.getParentNamespace() instanceof MicrosoftAspNetCoreNamespace and + this.hasName("Mvc") } } /** The 'Microsoft.AspNetCore.Mvc.ViewFeatures' namespace. */ class MicrosoftAspNetCoreMvcViewFeatures extends Namespace { MicrosoftAspNetCoreMvcViewFeatures() { - getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and - hasName("ViewFeatures") + this.getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + this.hasName("ViewFeatures") } } /** The 'Microsoft.AspNetCore.Mvc.Rendering' namespace. */ class MicrosoftAspNetCoreMvcRendering extends Namespace { MicrosoftAspNetCoreMvcRendering() { - getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and - hasName("Rendering") + this.getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + this.hasName("Rendering") } } /** An attribute whose type is in the `Microsoft.AspNetCore.Mvc` namespace. */ class MicrosoftAspNetCoreMvcAttribute extends Attribute { MicrosoftAspNetCoreMvcAttribute() { - getType().getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace + this.getType().getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace } } /** A `Microsoft.AspNetCore.Mvc.HttpPost` attribute. */ class MicrosoftAspNetCoreMvcHttpPostAttribute extends MicrosoftAspNetCoreMvcAttribute { - MicrosoftAspNetCoreMvcHttpPostAttribute() { getType().hasName("HttpPostAttribute") } + MicrosoftAspNetCoreMvcHttpPostAttribute() { this.getType().hasName("HttpPostAttribute") } } /** A `Microsoft.AspNetCore.Mvc.HttpPut` attribute. */ class MicrosoftAspNetCoreMvcHttpPutAttribute extends MicrosoftAspNetCoreMvcAttribute { - MicrosoftAspNetCoreMvcHttpPutAttribute() { getType().hasName("HttpPutAttribute") } + MicrosoftAspNetCoreMvcHttpPutAttribute() { this.getType().hasName("HttpPutAttribute") } } /** A `Microsoft.AspNetCore.Mvc.HttpDelete` attribute. */ class MicrosoftAspNetCoreMvcHttpDeleteAttribute extends MicrosoftAspNetCoreMvcAttribute { - MicrosoftAspNetCoreMvcHttpDeleteAttribute() { getType().hasName("HttpDeleteAttribute") } + MicrosoftAspNetCoreMvcHttpDeleteAttribute() { this.getType().hasName("HttpDeleteAttribute") } } /** A `Microsoft.AspNetCore.Mvc.NonAction` attribute. */ class MicrosoftAspNetCoreMvcNonActionAttribute extends MicrosoftAspNetCoreMvcAttribute { - MicrosoftAspNetCoreMvcNonActionAttribute() { getType().hasName("NonActionAttribute") } + MicrosoftAspNetCoreMvcNonActionAttribute() { this.getType().hasName("NonActionAttribute") } } /** The `Microsoft.AspNetCore.Antiforgery` namespace. */ class MicrosoftAspNetCoreAntiforgeryNamespace extends Namespace { MicrosoftAspNetCoreAntiforgeryNamespace() { - getParentNamespace() instanceof MicrosoftAspNetCoreNamespace and - hasName("Antiforgery") + this.getParentNamespace() instanceof MicrosoftAspNetCoreNamespace and + this.hasName("Antiforgery") } } /** The `Microsoft.AspNetCore.Mvc.Filters` namespace. */ class MicrosoftAspNetCoreMvcFilters extends Namespace { MicrosoftAspNetCoreMvcFilters() { - getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and - hasName("Filters") + this.getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + this.hasName("Filters") } } /** The `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadataInterface` interface. */ class MicrosoftAspNetCoreMvcIFilterMetadataInterface extends Interface { MicrosoftAspNetCoreMvcIFilterMetadataInterface() { - getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and - hasName("IFilterMetadata") + this.getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and + this.hasName("IFilterMetadata") } } /** The `Microsoft.AspNetCore.IAuthorizationFilter` interface. */ class MicrosoftAspNetCoreIAuthorizationFilterInterface extends Interface { MicrosoftAspNetCoreIAuthorizationFilterInterface() { - getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and - hasName("IAsyncAuthorizationFilter") + this.getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and + this.hasName("IAsyncAuthorizationFilter") } /** Gets the `OnAuthorizationAsync` method. */ - Method getOnAuthorizationMethod() { result = getAMethod("OnAuthorizationAsync") } + Method getOnAuthorizationMethod() { result = this.getAMethod("OnAuthorizationAsync") } } /** The `Microsoft.AspNetCore.IAntiforgery` interface. */ class MicrosoftAspNetCoreIAntiForgeryInterface extends Interface { MicrosoftAspNetCoreIAntiForgeryInterface() { - getNamespace() instanceof MicrosoftAspNetCoreAntiforgeryNamespace and - hasName("IAntiforgery") + this.getNamespace() instanceof MicrosoftAspNetCoreAntiforgeryNamespace and + this.hasName("IAntiforgery") } /** Gets the `ValidateRequestAsync` method. */ - Method getValidateMethod() { result = getAMethod("ValidateRequestAsync") } + Method getValidateMethod() { result = this.getAMethod("ValidateRequestAsync") } } /** The `Microsoft.AspNetCore.DefaultAntiForgery` class, or another user-supplied class that implements `IAntiForgery`. */ class AntiForgeryClass extends Class { - AntiForgeryClass() { getABaseInterface*() instanceof MicrosoftAspNetCoreIAntiForgeryInterface } + AntiForgeryClass() { + this.getABaseInterface*() instanceof MicrosoftAspNetCoreIAntiForgeryInterface + } /** Gets the `ValidateRequestAsync` method. */ - Method getValidateMethod() { result = getAMethod("ValidateRequestAsync") } + Method getValidateMethod() { result = this.getAMethod("ValidateRequestAsync") } } /** An authorization filter class defined by AspNetCore or the user. */ class AuthorizationFilterClass extends Class { AuthorizationFilterClass() { - getABaseInterface*() instanceof MicrosoftAspNetCoreIAuthorizationFilterInterface + this.getABaseInterface*() instanceof MicrosoftAspNetCoreIAuthorizationFilterInterface } /** Gets the `OnAuthorization` method provided by this filter. */ - Method getOnAuthorizationMethod() { result = getAMethod("OnAuthorizationAsync") } + Method getOnAuthorizationMethod() { result = this.getAMethod("OnAuthorizationAsync") } } /** An attribute whose type has a name like `[Auto...]Validate[...]Anti[Ff]orgery[...Token]Attribute`. */ class ValidateAntiForgeryAttribute extends Attribute { - ValidateAntiForgeryAttribute() { getType().getName().matches("%Validate%Anti_orgery%Attribute") } + ValidateAntiForgeryAttribute() { + this.getType().getName().matches("%Validate%Anti_orgery%Attribute") + } } /** @@ -137,43 +141,43 @@ class ValidateAntiForgeryAttribute extends Attribute { */ class ValidateAntiforgeryTokenAuthorizationFilter extends Class { ValidateAntiforgeryTokenAuthorizationFilter() { - getABaseInterface*() instanceof MicrosoftAspNetCoreMvcIFilterMetadataInterface and - getName().matches("%Validate%Anti_orgery%") + this.getABaseInterface*() instanceof MicrosoftAspNetCoreMvcIFilterMetadataInterface and + this.getName().matches("%Validate%Anti_orgery%") } } /** The `Microsoft.AspNetCore.Mvc.Filters.FilterCollection` class. */ class MicrosoftAspNetCoreMvcFilterCollection extends Class { MicrosoftAspNetCoreMvcFilterCollection() { - getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and - hasName("FilterCollection") + this.getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and + this.hasName("FilterCollection") } /** Gets an `Add` method. */ Method getAddMethod() { - result = getAMethod("Add") or - result = getABaseType().getAMethod("Add") + result = this.getAMethod("Add") or + result = this.getABaseType().getAMethod("Add") } } /** The `Microsoft.AspNetCore.Mvc.MvcOptions` class. */ class MicrosoftAspNetCoreMvcOptions extends Class { MicrosoftAspNetCoreMvcOptions() { - getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and - hasName("MvcOptions") + this.getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + this.hasName("MvcOptions") } /** Gets the `Filters` property. */ - Property getFilterCollectionProperty() { result = getProperty("Filters") } + Property getFilterCollectionProperty() { result = this.getProperty("Filters") } } /** The base class for controllers in MVC, i.e. `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase` class. */ class MicrosoftAspNetCoreMvcControllerBaseClass extends Class { MicrosoftAspNetCoreMvcControllerBaseClass() { - getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + this.getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and ( - hasName("Controller") or - hasName("ControllerBase") + this.hasName("Controller") or + this.hasName("ControllerBase") ) } } @@ -181,12 +185,12 @@ class MicrosoftAspNetCoreMvcControllerBaseClass extends Class { /** A subtype of `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase`. */ class MicrosoftAspNetCoreMvcController extends Class { MicrosoftAspNetCoreMvcController() { - getABaseType*() instanceof MicrosoftAspNetCoreMvcControllerBaseClass + this.getABaseType*() instanceof MicrosoftAspNetCoreMvcControllerBaseClass } /** Gets an action method for this controller. */ Method getAnActionMethod() { - result = getAMethod() and + result = this.getAMethod() and result.isPublic() and not result.isStatic() and not result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcNonActionAttribute @@ -208,12 +212,12 @@ class MicrosoftAspNetCoreMvcController extends Class { /** The `Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper` interface. */ class MicrosoftAspNetCoreMvcRenderingIHtmlHelperInterface extends Interface { MicrosoftAspNetCoreMvcRenderingIHtmlHelperInterface() { - getNamespace() instanceof MicrosoftAspNetCoreMvcRendering and - hasName("IHtmlHelper") + this.getNamespace() instanceof MicrosoftAspNetCoreMvcRendering and + this.hasName("IHtmlHelper") } /** Gets the `Raw` method. */ - Method getRawMethod() { result = getAMethod("Raw") } + Method getRawMethod() { result = this.getAMethod("Raw") } } /** A class deriving from `Microsoft.AspNetCore.Mvc.Razor.RazorPageBase`, implements Razor page in ASPNET Core. */ @@ -223,7 +227,7 @@ class MicrosoftAspNetCoreMvcRazorPageBase extends Class { } /** Gets the `WriteLiteral` method. */ - Method getWriteLiteralMethod() { result = getAMethod("WriteLiteral") } + Method getWriteLiteralMethod() { result = this.getAMethod("WriteLiteral") } } /** A class deriving from `Microsoft.AspNetCore.Http.HttpRequest`, implements `HttpRequest` in ASP.NET Core. */ diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Generic.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Generic.qll index a3616e57522..2b632d2b07c 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Generic.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Generic.qll @@ -41,8 +41,8 @@ class SystemCollectionsGenericIComparerTInterface extends SystemCollectionsGener result.getDeclaringType() = this and result.hasName("Compare") and result.getNumberOfParameters() = 2 and - result.getParameter(0).getType() = getTypeParameter(0) and - result.getParameter(1).getType() = getTypeParameter(0) and + result.getParameter(0).getType() = this.getTypeParameter(0) and + result.getParameter(1).getType() = this.getTypeParameter(0) and result.getReturnType() instanceof IntType } } @@ -56,8 +56,8 @@ class SystemCollectionsGenericIEqualityComparerTInterface extends SystemCollecti result.getDeclaringType() = this and result.hasName("Equals") and result.getNumberOfParameters() = 2 and - result.getParameter(0).getType() = getTypeParameter(0) and - result.getParameter(1).getType() = getTypeParameter(0) and + result.getParameter(0).getType() = this.getTypeParameter(0) and + result.getParameter(1).getType() = this.getTypeParameter(0) and result.getReturnType() instanceof BoolType } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/data/SqlClient.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/data/SqlClient.qll index 858100fe7f7..c3b6f1fdd6d 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/data/SqlClient.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/data/SqlClient.qll @@ -13,7 +13,7 @@ class SystemDataSqlClientNamespace extends Namespace { /** A class in the `System.Data.SqlClient` namespace. */ class SystemDataSqlClientClass extends Class { - SystemDataSqlClientClass() { getNamespace() instanceof SystemDataSqlClientNamespace } + SystemDataSqlClientClass() { this.getNamespace() instanceof SystemDataSqlClientNamespace } } /** The `System.Data.SqlClient.SqlDataAdapter` class. */ diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll index 1820192da11..531fa6ef721 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll @@ -67,7 +67,7 @@ class RegexOperation extends Call { */ Expr getInput() { if this instanceof MethodCall - then result = getArgumentForName("input") + then result = this.getArgumentForName("input") else exists(MethodCall call | call.getTarget() = any(SystemTextRegularExpressionsRegexClass rs).getAMethod() and diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/web/Mvc.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/web/Mvc.qll index 78aaa6dc065..b2051a8464f 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/web/Mvc.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/web/Mvc.qll @@ -6,8 +6,8 @@ private import semmle.code.csharp.frameworks.system.Web /** The `System.Web.Mvc` namespace. */ class SystemWebMvcNamespace extends Namespace { SystemWebMvcNamespace() { - getParentNamespace() instanceof SystemWebNamespace and - hasName("Mvc") + this.getParentNamespace() instanceof SystemWebNamespace and + this.hasName("Mvc") } } @@ -31,7 +31,7 @@ class SystemWebMvcHtmlHelperClass extends SystemWebMvcClass { /** An attribute whose type is in the `System.Web.Mvc` namespace. */ class SystemWebMvcAttribute extends Attribute { - SystemWebMvcAttribute() { getType().getNamespace() instanceof SystemWebMvcNamespace } + SystemWebMvcAttribute() { this.getType().getNamespace() instanceof SystemWebMvcNamespace } } /** An attribute whose type is `System.Web.Mvc.HttpPost`. */ diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/web/WebPages.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/web/WebPages.qll index 0d43f76719b..915acbfe41f 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/web/WebPages.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/web/WebPages.qll @@ -6,16 +6,16 @@ private import semmle.code.csharp.frameworks.system.Web /** The `System.Web.WebPages` namespace. */ class SystemWebWebPagesNamespace extends Namespace { SystemWebWebPagesNamespace() { - getParentNamespace() instanceof SystemWebNamespace and - hasName("WebPages") + this.getParentNamespace() instanceof SystemWebNamespace and + this.hasName("WebPages") } } /** The `System.Web.WebPages.WebPageExecutingBase` class. */ class SystemWebWebPagesWebPageExecutingBaseClass extends Class { SystemWebWebPagesWebPageExecutingBaseClass() { - getNamespace() instanceof SystemWebWebPagesNamespace and - hasName("WebPageExecutingBase") + this.getNamespace() instanceof SystemWebWebPagesNamespace and + this.hasName("WebPageExecutingBase") } } @@ -24,8 +24,8 @@ class WebPageClass extends Class { WebPageClass() { this.getBaseClass*() instanceof SystemWebWebPagesWebPageExecutingBaseClass } /** Gets the `WriteLiteral` method. */ - Method getWriteLiteralMethod() { result = getAMethod("WriteLiteral") } + Method getWriteLiteralMethod() { result = this.getAMethod("WriteLiteral") } /** Gets the `WriteLiteralTo` method. */ - Method getWriteLiteralToMethod() { result = getAMethod("WriteLiteralTo") } + Method getWriteLiteralToMethod() { result = this.getAMethod("WriteLiteralTo") } } diff --git a/csharp/ql/lib/semmle/code/csharp/security/SensitiveActions.qll b/csharp/ql/lib/semmle/code/csharp/security/SensitiveActions.qll index cc7701ad318..483000895aa 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/SensitiveActions.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/SensitiveActions.qll @@ -72,7 +72,7 @@ class SensitiveProperty extends Property { /** A parameter to a library method that may hold a sensitive value. */ class SensitiveLibraryParameter extends Parameter { SensitiveLibraryParameter() { - fromLibrary() and + this.fromLibrary() and exists(string s | this.getName().toLowerCase() = s | s.matches(suspicious())) } } diff --git a/csharp/ql/lib/semmle/code/csharp/security/cryptography/HardcodedSymmetricEncryptionKey.qll b/csharp/ql/lib/semmle/code/csharp/security/cryptography/HardcodedSymmetricEncryptionKey.qll index 915dae12a9f..3cf3fa107bf 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/cryptography/HardcodedSymmetricEncryptionKey.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/cryptography/HardcodedSymmetricEncryptionKey.qll @@ -21,7 +21,7 @@ module HardcodedSymmetricEncryptionKey { abstract class Sanitizer extends DataFlow::ExprNode { } private class ByteArrayType extends ArrayType { - ByteArrayType() { getElementType() instanceof ByteType } + ByteArrayType() { this.getElementType() instanceof ByteType } } private class ByteArrayLiteralSource extends Source { @@ -49,7 +49,7 @@ module HardcodedSymmetricEncryptionKey { private class SymmetricEncryptionCreateEncryptorSink extends Sink { SymmetricEncryptionCreateEncryptorSink() { exists(SymmetricAlgorithm ag, MethodCall mc | mc = ag.getASymmetricEncryptor() | - asExpr() = mc.getArgumentForName("rgbKey") + this.asExpr() = mc.getArgumentForName("rgbKey") ) } @@ -59,7 +59,7 @@ module HardcodedSymmetricEncryptionKey { private class SymmetricEncryptionCreateDecryptorSink extends Sink { SymmetricEncryptionCreateDecryptorSink() { exists(SymmetricAlgorithm ag, MethodCall mc | mc = ag.getASymmetricDecryptor() | - asExpr() = mc.getArgumentForName("rgbKey") + this.asExpr() = mc.getArgumentForName("rgbKey") ) } diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/ExternalAPIsQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/ExternalAPIsQuery.qll index bccd71d7096..fd643b5b7f0 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/ExternalAPIsQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/ExternalAPIsQuery.qll @@ -69,7 +69,7 @@ class ExternalAPIDataNode extends DataFlow::Node { int getIndex() { result = i } /** Gets the description of the callable being called. */ - string getCallableDescription() { result = getCallable().getQualifiedName() } + string getCallableDescription() { result = this.getCallable().getQualifiedName() } } /** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */ @@ -108,7 +108,7 @@ class ExternalAPIUsedWithUntrustedData extends TExternalAPI { /** Gets the number of untrusted sources used with this external API. */ int getNumberOfUntrustedSources() { - result = count(getUntrustedDataNode().getAnUntrustedSource()) + result = count(this.getUntrustedDataNode().getAnUntrustedSource()) } /** Gets a textual representation of this element. */ diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSSinks.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSSinks.qll index 4be005be4de..2ea9b60c28a 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSSinks.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSSinks.qll @@ -166,7 +166,7 @@ class AspInlineMember extends AspInlineCode { Member getMember() { result = member } /** Gets the type of this member. */ - Type getType() { result = getMemberType(getMember()) } + Type getType() { result = getMemberType(this.getMember()) } } /** Gets a value that is written to the member accessed by the given `AspInlineMember`. */ diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll index 25647e50f2e..b3e8d14c4c6 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll @@ -86,7 +86,7 @@ class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSourc /** A data flow source of remote user input (ASP.NET user input). */ class AspNetUserInputRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { - AspNetUserInputRemoteFlowSource() { getType() instanceof SystemWebUIWebControlsTextBoxClass } + AspNetUserInputRemoteFlowSource() { this.getType() instanceof SystemWebUIWebControlsTextBoxClass } override string getSourceType() { result = "ASP.NET user input" } } @@ -113,7 +113,7 @@ class AspNetServiceRemoteFlowSource extends RemoteFlowSource, DataFlow::Paramete /** A data flow source of remote user input (ASP.NET request message). */ class SystemNetHttpRequestMessageRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { SystemNetHttpRequestMessageRemoteFlowSource() { - getType() instanceof SystemWebHttpRequestMessageClass + this.getType() instanceof SystemWebHttpRequestMessageClass } override string getSourceType() { result = "ASP.NET request message" } diff --git a/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll index 2483452113a..17856d3e7e8 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll @@ -157,8 +157,8 @@ module XmlReader { override predicate isUnsafe(string reason) { exists(string dtdReason, string resolverReason | - dtdEnabled(dtdReason, _) and - insecureResolver(resolverReason, _) and + this.dtdEnabled(dtdReason, _) and + this.insecureResolver(resolverReason, _) and reason = dtdReason + ", " + resolverReason ) } diff --git a/csharp/ql/lib/semmle/code/dotnet/Callable.qll b/csharp/ql/lib/semmle/code/dotnet/Callable.qll index 2beccfe422c..0a63e5c95cd 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Callable.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Callable.qll @@ -75,7 +75,7 @@ class Callable extends Parameterizable, @dotnet_callable { } private string getReturnTypeLabel() { - result = getReturnType().getLabel() + result = this.getReturnType().getLabel() or not exists(this.getReturnType()) and result = "System.Void" } diff --git a/csharp/ql/lib/semmle/code/dotnet/Declaration.qll b/csharp/ql/lib/semmle/code/dotnet/Declaration.qll index 7f78077d766..60e434f9ae6 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Declaration.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Declaration.qll @@ -16,7 +16,7 @@ class Declaration extends NamedElement, @dotnet_declaration { string getUndecoratedName() { none() } /** Holds if this element has undecorated name 'name'. */ - final predicate hasUndecoratedName(string name) { name = getUndecoratedName() } + final predicate hasUndecoratedName(string name) { name = this.getUndecoratedName() } /** Gets the type containing this declaration, if any. */ Type getDeclaringType() { none() } diff --git a/csharp/ql/lib/semmle/code/dotnet/Element.qll b/csharp/ql/lib/semmle/code/dotnet/Element.qll index 3b1955887f9..d8c27f88e10 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Element.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Element.qll @@ -35,7 +35,7 @@ class Element extends @dotnet_element { * Gets the "language" of this program element, as defined by the extension of the filename. * For example, C# has language "cs", and Visual Basic has language "vb". */ - final string getLanguage() { result = getLocation().getFile().getExtension() } + final string getLanguage() { result = this.getLocation().getFile().getExtension() } /** Gets the full textual representation of this element, including type information. */ string toStringWithTypes() { result = this.toString() } @@ -43,7 +43,7 @@ class Element extends @dotnet_element { /** * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */ - final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") } + final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") } /** * Gets the name of a primary CodeQL class to which this element belongs. @@ -66,7 +66,7 @@ class NamedElement extends Element, @dotnet_named_element { string getName() { none() } /** Holds if this element has name 'name'. */ - final predicate hasName(string name) { name = getName() } + final predicate hasName(string name) { name = this.getName() } /** * Gets the fully qualified name of this element, for example the diff --git a/csharp/ql/lib/semmle/code/dotnet/Expr.qll b/csharp/ql/lib/semmle/code/dotnet/Expr.qll index e5bea3a52d7..15d658f54c2 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Expr.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Expr.qll @@ -45,7 +45,7 @@ class Call extends Expr, @dotnet_call { Expr getArgument(int i) { none() } /** Gets an argument to this call. */ - Expr getAnArgument() { result = getArgument(_) } + Expr getAnArgument() { result = this.getArgument(_) } /** Gets the expression that is supplied for parameter `p`. */ Expr getArgumentForParameter(Parameter p) { none() } diff --git a/csharp/ql/lib/semmle/code/dotnet/Generics.qll b/csharp/ql/lib/semmle/code/dotnet/Generics.qll index 9b236cdbfb9..f84718d4b82 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Generics.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Generics.qll @@ -14,7 +14,7 @@ abstract class UnboundGeneric extends Generic { abstract TypeParameter getTypeParameter(int i); /** Gets a type parameter. */ - TypeParameter getATypeParameter() { result = getTypeParameter(_) } + TypeParameter getATypeParameter() { result = this.getTypeParameter(_) } /** * Gets one of the constructed versions of this declaration, @@ -32,7 +32,7 @@ abstract class ConstructedGeneric extends Generic { abstract Type getTypeArgument(int i); /** Gets a type argument. */ - Type getATypeArgument() { result = getTypeArgument(_) } + Type getATypeArgument() { result = this.getTypeArgument(_) } /** * Gets the unbound generic declaration from which this declaration was diff --git a/csharp/ql/lib/semmle/code/dotnet/Namespace.qll b/csharp/ql/lib/semmle/code/dotnet/Namespace.qll index 55b42e737db..324448728de 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Namespace.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Namespace.qll @@ -33,7 +33,7 @@ class Namespace extends Declaration, @namespace { override string toString() { result = this.getQualifiedName() } /** Holds if this is the global namespace. */ - final predicate isGlobalNamespace() { getName() = "" } + final predicate isGlobalNamespace() { this.getName() = "" } /** Gets the simple name of this namespace, for example `IO` in `System.IO`. */ final override string getName() { namespaces(this, result) } diff --git a/csharp/ql/lib/semmle/code/dotnet/Type.qll b/csharp/ql/lib/semmle/code/dotnet/Type.qll index 5dc9c409c18..81fefa96550 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Type.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Type.qll @@ -24,11 +24,11 @@ class ValueOrRefType extends Type, @dotnet_valueorreftype { Namespace getDeclaringNamespace() { none() } private string getPrefixWithTypes() { - result = getDeclaringType().getLabel() + "." + result = this.getDeclaringType().getLabel() + "." or - if getDeclaringNamespace().isGlobalNamespace() + if this.getDeclaringNamespace().isGlobalNamespace() then result = "" - else result = getDeclaringNamespace().getQualifiedName() + "." + else result = this.getDeclaringNamespace().getQualifiedName() + "." } pragma[noinline] @@ -64,9 +64,9 @@ class TypeParameter extends Type, @dotnet_type_parameter { /** Gets the index of this type parameter. For example the index of `U` in `Func<T,U>` is 1. */ int getIndex() { none() } - final override string getLabel() { result = "!" + getIndex() } + final override string getLabel() { result = "!" + this.getIndex() } - override string getUndecoratedName() { result = "!" + getIndex() } + override string getUndecoratedName() { result = "!" + this.getIndex() } } /** A pointer type. */ @@ -76,9 +76,9 @@ class PointerType extends Type, @dotnet_pointer_type { override string getName() { result = this.getReferentType().getName() + "*" } - final override string getLabel() { result = getReferentType().getLabel() + "*" } + final override string getLabel() { result = this.getReferentType().getLabel() + "*" } - override string toStringWithTypes() { result = getReferentType().toStringWithTypes() + "*" } + override string toStringWithTypes() { result = this.getReferentType().toStringWithTypes() + "*" } } /** An array type. */ @@ -86,7 +86,7 @@ class ArrayType extends ValueOrRefType, @dotnet_array_type { /** Gets the type of the array element. */ Type getElementType() { none() } - final override string getLabel() { result = getElementType().getLabel() + "[]" } + final override string getLabel() { result = this.getElementType().getLabel() + "[]" } - override string toStringWithTypes() { result = getElementType().toStringWithTypes() + "[]" } + override string toStringWithTypes() { result = this.getElementType().toStringWithTypes() + "[]" } } diff --git a/csharp/ql/lib/semmle/code/dotnet/Variable.qll b/csharp/ql/lib/semmle/code/dotnet/Variable.qll index 9f9a12e7d98..ee9ccebbbe6 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Variable.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Variable.qll @@ -15,10 +15,10 @@ class Field extends Variable, Member, @dotnet_field { } /** A parameter to a .Net callable, property or function pointer type. */ class Parameter extends Variable, @dotnet_parameter { /** Gets the raw position of this parameter, including the `this` parameter at index 0. */ - final int getRawPosition() { this = getDeclaringElement().getRawParameter(result) } + final int getRawPosition() { this = this.getDeclaringElement().getRawParameter(result) } /** Gets the position of this parameter, excluding the `this` parameter. */ - int getPosition() { this = getDeclaringElement().getParameter(result) } + int getPosition() { this = this.getDeclaringElement().getParameter(result) } /** Gets the callable defining this parameter. */ Callable getCallable() { result = this.getDeclaringElement() } diff --git a/csharp/ql/src/Diagnostics/DiagnosticExtractionErrors.ql b/csharp/ql/src/Diagnostics/DiagnosticExtractionErrors.ql index 23943d8491f..e9e2a42bfa8 100644 --- a/csharp/ql/src/Diagnostics/DiagnosticExtractionErrors.ql +++ b/csharp/ql/src/Diagnostics/DiagnosticExtractionErrors.ql @@ -21,8 +21,8 @@ abstract private class DiagnosticError extends TDiagnosticError { abstract Location getLocation(); string getLocationMessage() { - if getLocation().getFile().fromSource() - then result = " in " + getLocation().getFile() + if this.getLocation().getFile().fromSource() + then result = " in " + this.getLocation().getFile() else result = "" } } diff --git a/csharp/ql/src/Stubs/Stubs.qll b/csharp/ql/src/Stubs/Stubs.qll index 6f92fb12f55..968e5255eaa 100644 --- a/csharp/ql/src/Stubs/Stubs.qll +++ b/csharp/ql/src/Stubs/Stubs.qll @@ -161,7 +161,7 @@ abstract private class GeneratedType extends Type, GeneratedElement { if this instanceof Enum then result = "" else - if exists(getAnInterestingBaseType()) + if exists(this.getAnInterestingBaseType()) then result = " : " + @@ -220,15 +220,15 @@ abstract private class GeneratedType extends Type, GeneratedElement { } final Type getAGeneratedType() { - result = getAnInterestingBaseType() + result = this.getAnInterestingBaseType() or - result = getAGeneratedMember().(Callable).getReturnType() + result = this.getAGeneratedMember().(Callable).getReturnType() or - result = getAGeneratedMember().(Callable).getAParameter().getType() + result = this.getAGeneratedMember().(Callable).getAParameter().getType() or - result = getAGeneratedMember().(Property).getType() + result = this.getAGeneratedMember().(Property).getType() or - result = getAGeneratedMember().(Field).getType() + result = this.getAGeneratedMember().(Field).getType() } } @@ -331,7 +331,8 @@ private class GeneratedNamespace extends Namespace, GeneratedElement { final string getStubs(Assembly assembly) { result = - getPreamble() + getTypeStubs(assembly) + getSubNamespaceStubs(assembly) + getPostAmble() + this.getPreamble() + this.getTypeStubs(assembly) + this.getSubNamespaceStubs(assembly) + + this.getPostAmble() } /** Gets the `n`th generated child namespace, indexed from 0. */ @@ -358,7 +359,7 @@ private class GeneratedNamespace extends Namespace, GeneratedElement { this.isInAssembly(assembly) and result = concat(GeneratedNamespace child, int i | - child = getChildNamespace(i) and child.isInAssembly(assembly) + child = this.getChildNamespace(i) and child.isInAssembly(assembly) | child.getStubs(assembly) order by i ) diff --git a/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll b/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll index 4b86f9a7cec..bb8630a5e0c 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll @@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock { final string toString() { result = getFirstInstruction(this).toString() } /** Gets the source location of the first non-`Phi` instruction in this block. */ - final Language::Location getLocation() { result = getFirstInstruction().getLocation() } + final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() } /** * INTERNAL: Do not use. @@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock { ) and this = rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = getEnclosingFunction() and + funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and // Ensure that the block containing `EnterFunction` always comes first. if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction @@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock { * Get the `Phi` instructions that appear at the start of this block. */ final PhiInstruction getAPhiInstruction() { - Construction::getPhiInstructionBlockStart(result) = getFirstInstruction() + Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction() } /** * Gets an instruction in this block. This includes `Phi` instructions. */ final Instruction getAnInstruction() { - result = getInstruction(_) or - result = getAPhiInstruction() + result = this.getInstruction(_) or + result = this.getAPhiInstruction() } /** @@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock { /** * Gets the last instruction in this block. */ - final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) } + final Instruction getLastInstruction() { + result = this.getInstruction(this.getInstructionCount() - 1) + } /** * Gets the number of non-`Phi` instructions in this block. @@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase { * Block `A` dominates block `B` if any control flow path from the entry block of the function to * block `B` must pass through block `A`. A block always dominates itself. */ - final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block } + final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block } /** * Gets a block on the dominance frontier of this block. @@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock dominanceFrontier() { - dominates(result.getAPredecessor()) and - not strictlyDominates(result) + this.dominates(result.getAPredecessor()) and + not this.strictlyDominates(result) } /** @@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase { * Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the * function must pass through block `A`. A block always post-dominates itself. */ - final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block } + final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block } /** * Gets a block on the post-dominance frontier of this block. @@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock postPominanceFrontier() { - postDominates(result.getASuccessor()) and - not strictlyPostDominates(result) + this.postDominates(result.getASuccessor()) and + not this.strictlyPostDominates(result) } /** * Holds if this block is reachable from the entry block of its function. */ final predicate isReachableFromFunctionEntry() { - this = getEnclosingIRFunction().getEntryBlock() or - getAPredecessor().isReachableFromFunctionEntry() + this = this.getEnclosingIRFunction().getEntryBlock() or + this.getAPredecessor().isReachableFromFunctionEntry() } } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll index 6f471d8a7e8..88a973fc5a8 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll @@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction { } /** Gets a textual representation of this element. */ - final string toString() { result = getOpcode().toString() + ": " + getAST().toString() } + final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() } /** * Gets a string showing the result, opcode, and operands of the instruction, equivalent to what @@ -50,7 +50,8 @@ class Instruction extends Construction::TStageInstruction { * `mu0_28(int) = Store r0_26, r0_27` */ final string getDumpString() { - result = getResultString() + " = " + getOperationString() + " " + getOperandsString() + result = + this.getResultString() + " = " + this.getOperationString() + " " + this.getOperandsString() } private predicate shouldGenerateDumpStrings() { @@ -66,10 +67,13 @@ class Instruction extends Construction::TStageInstruction { * VariableAddress[x] */ final string getOperationString() { - shouldGenerateDumpStrings() and - if exists(getImmediateString()) - then result = getOperationPrefix() + getOpcode().toString() + "[" + getImmediateString() + "]" - else result = getOperationPrefix() + getOpcode().toString() + this.shouldGenerateDumpStrings() and + if exists(this.getImmediateString()) + then + result = + this.getOperationPrefix() + this.getOpcode().toString() + "[" + this.getImmediateString() + + "]" + else result = this.getOperationPrefix() + this.getOpcode().toString() } /** @@ -78,17 +82,17 @@ class Instruction extends Construction::TStageInstruction { string getImmediateString() { none() } private string getOperationPrefix() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and if this instanceof SideEffectInstruction then result = "^" else result = "" } private string getResultPrefix() { - shouldGenerateDumpStrings() and - if getResultIRType() instanceof IRVoidType + this.shouldGenerateDumpStrings() and + if this.getResultIRType() instanceof IRVoidType then result = "v" else - if hasMemoryResult() - then if isResultModeled() then result = "m" else result = "mu" + if this.hasMemoryResult() + then if this.isResultModeled() then result = "m" else result = "mu" else result = "r" } @@ -97,7 +101,7 @@ class Instruction extends Construction::TStageInstruction { * used by debugging and printing code only. */ int getDisplayIndexInBlock() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and exists(IRBlock block | this = block.getInstruction(result) or @@ -111,12 +115,12 @@ class Instruction extends Construction::TStageInstruction { } private int getLineRank() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and this = rank[result](Instruction instr | instr = - getAnInstructionAtLine(getEnclosingIRFunction(), getLocation().getFile(), - getLocation().getStartLine()) + getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), + this.getLocation().getStartLine()) | instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() ) @@ -130,8 +134,9 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1` */ string getResultId() { - shouldGenerateDumpStrings() and - result = getResultPrefix() + getAST().getLocation().getStartLine() + "_" + getLineRank() + this.shouldGenerateDumpStrings() and + result = + this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank() } /** @@ -142,8 +147,8 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1(int*)` */ final string getResultString() { - shouldGenerateDumpStrings() and - result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")" + this.shouldGenerateDumpStrings() and + result = this.getResultId() + "(" + this.getResultLanguageType().getDumpString() + ")" } /** @@ -153,10 +158,10 @@ class Instruction extends Construction::TStageInstruction { * Example: `func:r3_4, this:r3_5` */ string getOperandsString() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and result = concat(Operand operand | - operand = getAnOperand() + operand = this.getAnOperand() | operand.getDumpString(), ", " order by operand.getDumpSortOrder() ) @@ -190,7 +195,7 @@ class Instruction extends Construction::TStageInstruction { * Gets the function that contains this instruction. */ final Language::Function getEnclosingFunction() { - result = getEnclosingIRFunction().getFunction() + result = this.getEnclosingIRFunction().getFunction() } /** @@ -208,7 +213,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the location of the source code for this instruction. */ - final Language::Location getLocation() { result = getAST().getLocation() } + final Language::Location getLocation() { result = this.getAST().getLocation() } /** * Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a @@ -243,7 +248,7 @@ class Instruction extends Construction::TStageInstruction { * a result, its result type will be `IRVoidType`. */ cached - final IRType getResultIRType() { result = getResultLanguageType().getIRType() } + final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() } /** * Gets the type of the result produced by this instruction. If the @@ -254,7 +259,7 @@ class Instruction extends Construction::TStageInstruction { */ final Language::Type getResultType() { exists(Language::LanguageType resultType | - resultType = getResultLanguageType() and + resultType = this.getResultLanguageType() and ( resultType.hasUnspecifiedType(result, _) or @@ -283,7 +288,7 @@ class Instruction extends Construction::TStageInstruction { * result of the `Load` instruction is a prvalue of type `int`, representing * the integer value loaded from variable `x`. */ - final predicate isGLValue() { getResultLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getResultLanguageType().hasType(_, true) } /** * Gets the size of the result produced by this instruction, in bytes. If the @@ -292,7 +297,7 @@ class Instruction extends Construction::TStageInstruction { * If `this.isGLValue()` holds for this instruction, the value of * `getResultSize()` will always be the size of a pointer. */ - final int getResultSize() { result = getResultLanguageType().getByteSize() } + final int getResultSize() { result = this.getResultLanguageType().getByteSize() } /** * Gets the opcode that specifies the operation performed by this instruction. @@ -314,14 +319,16 @@ class Instruction extends Construction::TStageInstruction { /** * Holds if this instruction produces a memory result. */ - final predicate hasMemoryResult() { exists(getResultMemoryAccess()) } + final predicate hasMemoryResult() { exists(this.getResultMemoryAccess()) } /** * Gets the kind of memory access performed by this instruction's result. * Holds only for instructions with a memory result. */ pragma[inline] - final MemoryAccessKind getResultMemoryAccess() { result = getOpcode().getWriteMemoryAccess() } + final MemoryAccessKind getResultMemoryAccess() { + result = this.getOpcode().getWriteMemoryAccess() + } /** * Holds if the memory access performed by this instruction's result will not always write to @@ -332,7 +339,7 @@ class Instruction extends Construction::TStageInstruction { * (for example, the global side effects of a function call). */ pragma[inline] - final predicate hasResultMayMemoryAccess() { getOpcode().hasMayWriteMemoryAccess() } + final predicate hasResultMayMemoryAccess() { this.getOpcode().hasMayWriteMemoryAccess() } /** * Gets the operand that holds the memory address to which this instruction stores its @@ -340,7 +347,7 @@ class Instruction extends Construction::TStageInstruction { * is `r1`. */ final AddressOperand getResultAddressOperand() { - getResultMemoryAccess().usesAddressOperand() and + this.getResultMemoryAccess().usesAddressOperand() and result.getUse() = this } @@ -349,7 +356,7 @@ class Instruction extends Construction::TStageInstruction { * result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()` * is the instruction that defines `r1`. */ - final Instruction getResultAddress() { result = getResultAddressOperand().getDef() } + final Instruction getResultAddress() { result = this.getResultAddressOperand().getDef() } /** * Holds if the result of this instruction is precisely modeled in SSA. Always @@ -368,7 +375,7 @@ class Instruction extends Construction::TStageInstruction { */ final predicate isResultModeled() { // Register results are always in SSA form. - not hasMemoryResult() or + not this.hasMemoryResult() or Construction::hasModeledMemoryResult(this) } @@ -412,7 +419,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct successors of this instruction. */ - final Instruction getASuccessor() { result = getSuccessor(_) } + final Instruction getASuccessor() { result = this.getSuccessor(_) } /** * Gets a predecessor of this instruction such that the predecessor reaches @@ -423,7 +430,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct predecessors of this instruction. */ - final Instruction getAPredecessor() { result = getPredecessor(_) } + final Instruction getAPredecessor() { result = this.getPredecessor(_) } } /** @@ -543,7 +550,7 @@ class IndexedInstruction extends Instruction { * at this instruction. This instruction has no predecessors. */ class EnterFunctionInstruction extends Instruction { - EnterFunctionInstruction() { getOpcode() instanceof Opcode::EnterFunction } + EnterFunctionInstruction() { this.getOpcode() instanceof Opcode::EnterFunction } } /** @@ -554,7 +561,7 @@ class EnterFunctionInstruction extends Instruction { * struct, or union, see `FieldAddressInstruction`. */ class VariableAddressInstruction extends VariableInstruction { - VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress } + VariableAddressInstruction() { this.getOpcode() instanceof Opcode::VariableAddress } } /** @@ -566,7 +573,7 @@ class VariableAddressInstruction extends VariableInstruction { * The result has an `IRFunctionAddress` type. */ class FunctionAddressInstruction extends FunctionInstruction { - FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress } + FunctionAddressInstruction() { this.getOpcode() instanceof Opcode::FunctionAddress } } /** @@ -577,7 +584,7 @@ class FunctionAddressInstruction extends FunctionInstruction { * initializes that parameter. */ class InitializeParameterInstruction extends VariableInstruction { - InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter } + InitializeParameterInstruction() { this.getOpcode() instanceof Opcode::InitializeParameter } /** * Gets the parameter initialized by this instruction. @@ -603,7 +610,7 @@ class InitializeParameterInstruction extends VariableInstruction { * initialized elsewhere, would not otherwise have a definition in this function. */ class InitializeNonLocalInstruction extends Instruction { - InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal } + InitializeNonLocalInstruction() { this.getOpcode() instanceof Opcode::InitializeNonLocal } } /** @@ -611,7 +618,7 @@ class InitializeNonLocalInstruction extends Instruction { * with the value of that memory on entry to the function. */ class InitializeIndirectionInstruction extends VariableInstruction { - InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + InitializeIndirectionInstruction() { this.getOpcode() instanceof Opcode::InitializeIndirection } /** * Gets the parameter initialized by this instruction. @@ -635,24 +642,24 @@ class InitializeIndirectionInstruction extends VariableInstruction { * An instruction that initializes the `this` pointer parameter of the enclosing function. */ class InitializeThisInstruction extends Instruction { - InitializeThisInstruction() { getOpcode() instanceof Opcode::InitializeThis } + InitializeThisInstruction() { this.getOpcode() instanceof Opcode::InitializeThis } } /** * An instruction that computes the address of a non-static field of an object. */ class FieldAddressInstruction extends FieldInstruction { - FieldAddressInstruction() { getOpcode() instanceof Opcode::FieldAddress } + FieldAddressInstruction() { this.getOpcode() instanceof Opcode::FieldAddress } /** * Gets the operand that provides the address of the object containing the field. */ - final UnaryOperand getObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the object containing the field. */ - final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() } + final Instruction getObjectAddress() { result = this.getObjectAddressOperand().getDef() } } /** @@ -661,17 +668,19 @@ class FieldAddressInstruction extends FieldInstruction { * This instruction is used for element access to C# arrays. */ class ElementsAddressInstruction extends UnaryInstruction { - ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress } + ElementsAddressInstruction() { this.getOpcode() instanceof Opcode::ElementsAddress } /** * Gets the operand that provides the address of the array object. */ - final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getArrayObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the array object. */ - final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() } + final Instruction getArrayObjectAddress() { + result = this.getArrayObjectAddressOperand().getDef() + } } /** @@ -685,7 +694,7 @@ class ElementsAddressInstruction extends UnaryInstruction { * taken may want to ignore any function that contains an `ErrorInstruction`. */ class ErrorInstruction extends Instruction { - ErrorInstruction() { getOpcode() instanceof Opcode::Error } + ErrorInstruction() { this.getOpcode() instanceof Opcode::Error } } /** @@ -695,7 +704,7 @@ class ErrorInstruction extends Instruction { * an initializer, or whose initializer only partially initializes the variable. */ class UninitializedInstruction extends VariableInstruction { - UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized } + UninitializedInstruction() { this.getOpcode() instanceof Opcode::Uninitialized } /** * Gets the variable that is uninitialized. @@ -710,7 +719,7 @@ class UninitializedInstruction extends VariableInstruction { * least one instruction, even when the AST has no semantic effect. */ class NoOpInstruction extends Instruction { - NoOpInstruction() { getOpcode() instanceof Opcode::NoOp } + NoOpInstruction() { this.getOpcode() instanceof Opcode::NoOp } } /** @@ -732,32 +741,32 @@ class NoOpInstruction extends Instruction { * `void`-returning function. */ class ReturnInstruction extends Instruction { - ReturnInstruction() { getOpcode() instanceof ReturnOpcode } + ReturnInstruction() { this.getOpcode() instanceof ReturnOpcode } } /** * An instruction that returns control to the caller of the function, without returning a value. */ class ReturnVoidInstruction extends ReturnInstruction { - ReturnVoidInstruction() { getOpcode() instanceof Opcode::ReturnVoid } + ReturnVoidInstruction() { this.getOpcode() instanceof Opcode::ReturnVoid } } /** * An instruction that returns control to the caller of the function, including a return value. */ class ReturnValueInstruction extends ReturnInstruction { - ReturnValueInstruction() { getOpcode() instanceof Opcode::ReturnValue } + ReturnValueInstruction() { this.getOpcode() instanceof Opcode::ReturnValue } /** * Gets the operand that provides the value being returned by the function. */ - final LoadOperand getReturnValueOperand() { result = getAnOperand() } + final LoadOperand getReturnValueOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value being returned by the function, if an * exact definition is available. */ - final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } + final Instruction getReturnValue() { result = this.getReturnValueOperand().getDef() } } /** @@ -770,28 +779,28 @@ class ReturnValueInstruction extends ReturnInstruction { * that the caller initialized the memory pointed to by the parameter before the call. */ class ReturnIndirectionInstruction extends VariableInstruction { - ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + ReturnIndirectionInstruction() { this.getOpcode() instanceof Opcode::ReturnIndirection } /** * Gets the operand that provides the value of the pointed-to memory. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the pointed-to memory, if an exact * definition is available. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** * Gets the operand that provides the address of the pointed-to memory. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the pointed-to memory. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } /** * Gets the parameter for which this instruction reads the final pointed-to value within the @@ -826,7 +835,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * - `StoreInstruction` - Copies a register operand to a memory result. */ class CopyInstruction extends Instruction { - CopyInstruction() { getOpcode() instanceof CopyOpcode } + CopyInstruction() { this.getOpcode() instanceof CopyOpcode } /** * Gets the operand that provides the input value of the copy. @@ -837,16 +846,16 @@ class CopyInstruction extends Instruction { * Gets the instruction whose result provides the input value of the copy, if an exact definition * is available. */ - final Instruction getSourceValue() { result = getSourceValueOperand().getDef() } + final Instruction getSourceValue() { result = this.getSourceValueOperand().getDef() } } /** * An instruction that returns a register result containing a copy of its register operand. */ class CopyValueInstruction extends CopyInstruction, UnaryInstruction { - CopyValueInstruction() { getOpcode() instanceof Opcode::CopyValue } + CopyValueInstruction() { this.getOpcode() instanceof Opcode::CopyValue } - final override UnaryOperand getSourceValueOperand() { result = getAnOperand() } + final override UnaryOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -863,47 +872,49 @@ private string getAddressOperandDescription(AddressOperand operand) { * An instruction that returns a register result containing a copy of its memory operand. */ class LoadInstruction extends CopyInstruction { - LoadInstruction() { getOpcode() instanceof Opcode::Load } + LoadInstruction() { this.getOpcode() instanceof Opcode::Load } final override string getImmediateString() { - result = getAddressOperandDescription(getSourceAddressOperand()) + result = getAddressOperandDescription(this.getSourceAddressOperand()) } /** * Gets the operand that provides the address of the value being loaded. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the value being loaded. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } - final override LoadOperand getSourceValueOperand() { result = getAnOperand() } + final override LoadOperand getSourceValueOperand() { result = this.getAnOperand() } } /** * An instruction that returns a memory result containing a copy of its register operand. */ class StoreInstruction extends CopyInstruction { - StoreInstruction() { getOpcode() instanceof Opcode::Store } + StoreInstruction() { this.getOpcode() instanceof Opcode::Store } final override string getImmediateString() { - result = getAddressOperandDescription(getDestinationAddressOperand()) + result = getAddressOperandDescription(this.getDestinationAddressOperand()) } /** * Gets the operand that provides the address of the location to which the value will be stored. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the location to which the value will * be stored, if an exact definition is available. */ - final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + final Instruction getDestinationAddress() { + result = this.getDestinationAddressOperand().getDef() + } - final override StoreValueOperand getSourceValueOperand() { result = getAnOperand() } + final override StoreValueOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -911,27 +922,27 @@ class StoreInstruction extends CopyInstruction { * operand. */ class ConditionalBranchInstruction extends Instruction { - ConditionalBranchInstruction() { getOpcode() instanceof Opcode::ConditionalBranch } + ConditionalBranchInstruction() { this.getOpcode() instanceof Opcode::ConditionalBranch } /** * Gets the operand that provides the Boolean condition controlling the branch. */ - final ConditionOperand getConditionOperand() { result = getAnOperand() } + final ConditionOperand getConditionOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the Boolean condition controlling the branch. */ - final Instruction getCondition() { result = getConditionOperand().getDef() } + final Instruction getCondition() { result = this.getConditionOperand().getDef() } /** * Gets the instruction to which control will flow if the condition is true. */ - final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) } + final Instruction getTrueSuccessor() { result = this.getSuccessor(EdgeKind::trueEdge()) } /** * Gets the instruction to which control will flow if the condition is false. */ - final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) } + final Instruction getFalseSuccessor() { result = this.getSuccessor(EdgeKind::falseEdge()) } } /** @@ -943,14 +954,14 @@ class ConditionalBranchInstruction extends Instruction { * successors. */ class ExitFunctionInstruction extends Instruction { - ExitFunctionInstruction() { getOpcode() instanceof Opcode::ExitFunction } + ExitFunctionInstruction() { this.getOpcode() instanceof Opcode::ExitFunction } } /** * An instruction whose result is a constant value. */ class ConstantInstruction extends ConstantValueInstruction { - ConstantInstruction() { getOpcode() instanceof Opcode::Constant } + ConstantInstruction() { this.getOpcode() instanceof Opcode::Constant } } /** @@ -959,7 +970,7 @@ class ConstantInstruction extends ConstantValueInstruction { class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { exists(IRType resultType | - resultType = getResultIRType() and + resultType = this.getResultIRType() and (resultType instanceof IRIntegerType or resultType instanceof IRBooleanType) ) } @@ -969,7 +980,7 @@ class IntegerConstantInstruction extends ConstantInstruction { * An instruction whose result is a constant value of floating-point type. */ class FloatConstantInstruction extends ConstantInstruction { - FloatConstantInstruction() { getResultIRType() instanceof IRFloatingPointType } + FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType } } /** @@ -978,7 +989,9 @@ class FloatConstantInstruction extends ConstantInstruction { class StringConstantInstruction extends VariableInstruction { override IRStringLiteral var; - final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } + final override string getImmediateString() { + result = Language::getStringLiteralText(this.getValue()) + } /** * Gets the string literal whose address is returned by this instruction. @@ -990,37 +1003,37 @@ class StringConstantInstruction extends VariableInstruction { * An instruction whose result is computed from two operands. */ class BinaryInstruction extends Instruction { - BinaryInstruction() { getOpcode() instanceof BinaryOpcode } + BinaryInstruction() { this.getOpcode() instanceof BinaryOpcode } /** * Gets the left operand of this binary instruction. */ - final LeftOperand getLeftOperand() { result = getAnOperand() } + final LeftOperand getLeftOperand() { result = this.getAnOperand() } /** * Gets the right operand of this binary instruction. */ - final RightOperand getRightOperand() { result = getAnOperand() } + final RightOperand getRightOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the left operand of this binary * instruction. */ - final Instruction getLeft() { result = getLeftOperand().getDef() } + final Instruction getLeft() { result = this.getLeftOperand().getDef() } /** * Gets the instruction whose result provides the value of the right operand of this binary * instruction. */ - final Instruction getRight() { result = getRightOperand().getDef() } + final Instruction getRight() { result = this.getRightOperand().getDef() } /** * Holds if this instruction's operands are `op1` and `op2`, in either order. */ final predicate hasOperands(Operand op1, Operand op2) { - op1 = getLeftOperand() and op2 = getRightOperand() + op1 = this.getLeftOperand() and op2 = this.getRightOperand() or - op1 = getRightOperand() and op2 = getLeftOperand() + op1 = this.getRightOperand() and op2 = this.getLeftOperand() } } @@ -1028,7 +1041,7 @@ class BinaryInstruction extends Instruction { * An instruction that computes the result of an arithmetic operation. */ class ArithmeticInstruction extends Instruction { - ArithmeticInstruction() { getOpcode() instanceof ArithmeticOpcode } + ArithmeticInstruction() { this.getOpcode() instanceof ArithmeticOpcode } } /** @@ -1050,7 +1063,7 @@ class UnaryArithmeticInstruction extends ArithmeticInstruction, UnaryInstruction * performed according to IEEE-754. */ class AddInstruction extends BinaryArithmeticInstruction { - AddInstruction() { getOpcode() instanceof Opcode::Add } + AddInstruction() { this.getOpcode() instanceof Opcode::Add } } /** @@ -1061,7 +1074,7 @@ class AddInstruction extends BinaryArithmeticInstruction { * according to IEEE-754. */ class SubInstruction extends BinaryArithmeticInstruction { - SubInstruction() { getOpcode() instanceof Opcode::Sub } + SubInstruction() { this.getOpcode() instanceof Opcode::Sub } } /** @@ -1072,7 +1085,7 @@ class SubInstruction extends BinaryArithmeticInstruction { * performed according to IEEE-754. */ class MulInstruction extends BinaryArithmeticInstruction { - MulInstruction() { getOpcode() instanceof Opcode::Mul } + MulInstruction() { this.getOpcode() instanceof Opcode::Mul } } /** @@ -1083,7 +1096,7 @@ class MulInstruction extends BinaryArithmeticInstruction { * to IEEE-754. */ class DivInstruction extends BinaryArithmeticInstruction { - DivInstruction() { getOpcode() instanceof Opcode::Div } + DivInstruction() { this.getOpcode() instanceof Opcode::Div } } /** @@ -1093,7 +1106,7 @@ class DivInstruction extends BinaryArithmeticInstruction { * division by zero or integer overflow is undefined. */ class RemInstruction extends BinaryArithmeticInstruction { - RemInstruction() { getOpcode() instanceof Opcode::Rem } + RemInstruction() { this.getOpcode() instanceof Opcode::Rem } } /** @@ -1104,14 +1117,14 @@ class RemInstruction extends BinaryArithmeticInstruction { * is performed according to IEEE-754. */ class NegateInstruction extends UnaryArithmeticInstruction { - NegateInstruction() { getOpcode() instanceof Opcode::Negate } + NegateInstruction() { this.getOpcode() instanceof Opcode::Negate } } /** * An instruction that computes the result of a bitwise operation. */ class BitwiseInstruction extends Instruction { - BitwiseInstruction() { getOpcode() instanceof BitwiseOpcode } + BitwiseInstruction() { this.getOpcode() instanceof BitwiseOpcode } } /** @@ -1130,7 +1143,7 @@ class UnaryBitwiseInstruction extends BitwiseInstruction, UnaryInstruction { } * Both operands must have the same integer type, which will also be the result type. */ class BitAndInstruction extends BinaryBitwiseInstruction { - BitAndInstruction() { getOpcode() instanceof Opcode::BitAnd } + BitAndInstruction() { this.getOpcode() instanceof Opcode::BitAnd } } /** @@ -1139,7 +1152,7 @@ class BitAndInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitOrInstruction extends BinaryBitwiseInstruction { - BitOrInstruction() { getOpcode() instanceof Opcode::BitOr } + BitOrInstruction() { this.getOpcode() instanceof Opcode::BitOr } } /** @@ -1148,7 +1161,7 @@ class BitOrInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitXorInstruction extends BinaryBitwiseInstruction { - BitXorInstruction() { getOpcode() instanceof Opcode::BitXor } + BitXorInstruction() { this.getOpcode() instanceof Opcode::BitXor } } /** @@ -1159,7 +1172,7 @@ class BitXorInstruction extends BinaryBitwiseInstruction { * rightmost bits are zero-filled. */ class ShiftLeftInstruction extends BinaryBitwiseInstruction { - ShiftLeftInstruction() { getOpcode() instanceof Opcode::ShiftLeft } + ShiftLeftInstruction() { this.getOpcode() instanceof Opcode::ShiftLeft } } /** @@ -1172,7 +1185,7 @@ class ShiftLeftInstruction extends BinaryBitwiseInstruction { * of the left operand. */ class ShiftRightInstruction extends BinaryBitwiseInstruction { - ShiftRightInstruction() { getOpcode() instanceof Opcode::ShiftRight } + ShiftRightInstruction() { this.getOpcode() instanceof Opcode::ShiftRight } } /** @@ -1183,7 +1196,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { int elementSize; PointerArithmeticInstruction() { - getOpcode() instanceof PointerArithmeticOpcode and + this.getOpcode() instanceof PointerArithmeticOpcode and elementSize = Raw::getInstructionElementSize(this) } @@ -1206,7 +1219,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { * An instruction that adds or subtracts an integer offset from a pointer. */ class PointerOffsetInstruction extends PointerArithmeticInstruction { - PointerOffsetInstruction() { getOpcode() instanceof PointerOffsetOpcode } + PointerOffsetInstruction() { this.getOpcode() instanceof PointerOffsetOpcode } } /** @@ -1217,7 +1230,7 @@ class PointerOffsetInstruction extends PointerArithmeticInstruction { * overflow is undefined. */ class PointerAddInstruction extends PointerOffsetInstruction { - PointerAddInstruction() { getOpcode() instanceof Opcode::PointerAdd } + PointerAddInstruction() { this.getOpcode() instanceof Opcode::PointerAdd } } /** @@ -1228,7 +1241,7 @@ class PointerAddInstruction extends PointerOffsetInstruction { * pointer underflow is undefined. */ class PointerSubInstruction extends PointerOffsetInstruction { - PointerSubInstruction() { getOpcode() instanceof Opcode::PointerSub } + PointerSubInstruction() { this.getOpcode() instanceof Opcode::PointerSub } } /** @@ -1241,31 +1254,31 @@ class PointerSubInstruction extends PointerOffsetInstruction { * undefined. */ class PointerDiffInstruction extends PointerArithmeticInstruction { - PointerDiffInstruction() { getOpcode() instanceof Opcode::PointerDiff } + PointerDiffInstruction() { this.getOpcode() instanceof Opcode::PointerDiff } } /** * An instruction whose result is computed from a single operand. */ class UnaryInstruction extends Instruction { - UnaryInstruction() { getOpcode() instanceof UnaryOpcode } + UnaryInstruction() { this.getOpcode() instanceof UnaryOpcode } /** * Gets the sole operand of this instruction. */ - final UnaryOperand getUnaryOperand() { result = getAnOperand() } + final UnaryOperand getUnaryOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the sole operand of this instruction. */ - final Instruction getUnary() { result = getUnaryOperand().getDef() } + final Instruction getUnary() { result = this.getUnaryOperand().getDef() } } /** * An instruction that converts the value of its operand to a value of a different type. */ class ConvertInstruction extends UnaryInstruction { - ConvertInstruction() { getOpcode() instanceof Opcode::Convert } + ConvertInstruction() { this.getOpcode() instanceof Opcode::Convert } } /** @@ -1279,7 +1292,7 @@ class ConvertInstruction extends UnaryInstruction { * `as` expression. */ class CheckedConvertOrNullInstruction extends UnaryInstruction { - CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull } + CheckedConvertOrNullInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrNull } } /** @@ -1293,7 +1306,7 @@ class CheckedConvertOrNullInstruction extends UnaryInstruction { * expression. */ class CheckedConvertOrThrowInstruction extends UnaryInstruction { - CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow } + CheckedConvertOrThrowInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrThrow } } /** @@ -1306,7 +1319,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction { * the most-derived object. */ class CompleteObjectAddressInstruction extends UnaryInstruction { - CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress } + CompleteObjectAddressInstruction() { this.getOpcode() instanceof Opcode::CompleteObjectAddress } } /** @@ -1351,7 +1364,7 @@ class InheritanceConversionInstruction extends UnaryInstruction { * An instruction that converts from the address of a derived class to the address of a base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } + ConvertToBaseInstruction() { this.getOpcode() instanceof ConvertToBaseOpcode } } /** @@ -1361,7 +1374,9 @@ class ConvertToBaseInstruction extends InheritanceConversionInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } + ConvertToNonVirtualBaseInstruction() { + this.getOpcode() instanceof Opcode::ConvertToNonVirtualBase + } } /** @@ -1371,7 +1386,7 @@ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } + ConvertToVirtualBaseInstruction() { this.getOpcode() instanceof Opcode::ConvertToVirtualBase } } /** @@ -1381,7 +1396,7 @@ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { - ConvertToDerivedInstruction() { getOpcode() instanceof Opcode::ConvertToDerived } + ConvertToDerivedInstruction() { this.getOpcode() instanceof Opcode::ConvertToDerived } } /** @@ -1390,7 +1405,7 @@ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { * The operand must have an integer type, which will also be the result type. */ class BitComplementInstruction extends UnaryBitwiseInstruction { - BitComplementInstruction() { getOpcode() instanceof Opcode::BitComplement } + BitComplementInstruction() { this.getOpcode() instanceof Opcode::BitComplement } } /** @@ -1399,14 +1414,14 @@ class BitComplementInstruction extends UnaryBitwiseInstruction { * The operand must have a Boolean type, which will also be the result type. */ class LogicalNotInstruction extends UnaryInstruction { - LogicalNotInstruction() { getOpcode() instanceof Opcode::LogicalNot } + LogicalNotInstruction() { this.getOpcode() instanceof Opcode::LogicalNot } } /** * An instruction that compares two numeric operands. */ class CompareInstruction extends BinaryInstruction { - CompareInstruction() { getOpcode() instanceof CompareOpcode } + CompareInstruction() { this.getOpcode() instanceof CompareOpcode } } /** @@ -1417,7 +1432,7 @@ class CompareInstruction extends BinaryInstruction { * unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareEQInstruction extends CompareInstruction { - CompareEQInstruction() { getOpcode() instanceof Opcode::CompareEQ } + CompareEQInstruction() { this.getOpcode() instanceof Opcode::CompareEQ } } /** @@ -1428,14 +1443,14 @@ class CompareEQInstruction extends CompareInstruction { * `left == right`. Floating-point comparison is performed according to IEEE-754. */ class CompareNEInstruction extends CompareInstruction { - CompareNEInstruction() { getOpcode() instanceof Opcode::CompareNE } + CompareNEInstruction() { this.getOpcode() instanceof Opcode::CompareNE } } /** * An instruction that does a relative comparison of two values, such as `<` or `>=`. */ class RelationalInstruction extends CompareInstruction { - RelationalInstruction() { getOpcode() instanceof RelationalOpcode } + RelationalInstruction() { this.getOpcode() instanceof RelationalOpcode } /** * Gets the operand on the "greater" (or "greater-or-equal") side @@ -1467,11 +1482,11 @@ class RelationalInstruction extends CompareInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLTInstruction extends RelationalInstruction { - CompareLTInstruction() { getOpcode() instanceof Opcode::CompareLT } + CompareLTInstruction() { this.getOpcode() instanceof Opcode::CompareLT } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { any() } } @@ -1484,11 +1499,11 @@ class CompareLTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGTInstruction extends RelationalInstruction { - CompareGTInstruction() { getOpcode() instanceof Opcode::CompareGT } + CompareGTInstruction() { this.getOpcode() instanceof Opcode::CompareGT } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { any() } } @@ -1502,11 +1517,11 @@ class CompareGTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLEInstruction extends RelationalInstruction { - CompareLEInstruction() { getOpcode() instanceof Opcode::CompareLE } + CompareLEInstruction() { this.getOpcode() instanceof Opcode::CompareLE } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { none() } } @@ -1520,11 +1535,11 @@ class CompareLEInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGEInstruction extends RelationalInstruction { - CompareGEInstruction() { getOpcode() instanceof Opcode::CompareGE } + CompareGEInstruction() { this.getOpcode() instanceof Opcode::CompareGE } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { none() } } @@ -1543,78 +1558,78 @@ class CompareGEInstruction extends RelationalInstruction { * of any case edge. */ class SwitchInstruction extends Instruction { - SwitchInstruction() { getOpcode() instanceof Opcode::Switch } + SwitchInstruction() { this.getOpcode() instanceof Opcode::Switch } /** Gets the operand that provides the integer value controlling the switch. */ - final ConditionOperand getExpressionOperand() { result = getAnOperand() } + final ConditionOperand getExpressionOperand() { result = this.getAnOperand() } /** Gets the instruction whose result provides the integer value controlling the switch. */ - final Instruction getExpression() { result = getExpressionOperand().getDef() } + final Instruction getExpression() { result = this.getExpressionOperand().getDef() } /** Gets the successor instructions along the case edges of the switch. */ - final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) } + final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = this.getSuccessor(edge)) } /** Gets the successor instruction along the default edge of the switch, if any. */ - final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) } + final Instruction getDefaultSuccessor() { result = this.getSuccessor(EdgeKind::defaultEdge()) } } /** * An instruction that calls a function. */ class CallInstruction extends Instruction { - CallInstruction() { getOpcode() instanceof Opcode::Call } + CallInstruction() { this.getOpcode() instanceof Opcode::Call } final override string getImmediateString() { - result = getStaticCallTarget().toString() + result = this.getStaticCallTarget().toString() or - not exists(getStaticCallTarget()) and result = "?" + not exists(this.getStaticCallTarget()) and result = "?" } /** * Gets the operand the specifies the target function of the call. */ - final CallTargetOperand getCallTargetOperand() { result = getAnOperand() } + final CallTargetOperand getCallTargetOperand() { result = this.getAnOperand() } /** * Gets the `Instruction` that computes the target function of the call. This is usually a * `FunctionAddress` instruction, but can also be an arbitrary instruction that produces a * function pointer. */ - final Instruction getCallTarget() { result = getCallTargetOperand().getDef() } + final Instruction getCallTarget() { result = this.getCallTargetOperand().getDef() } /** * Gets all of the argument operands of the call, including the `this` pointer, if any. */ - final ArgumentOperand getAnArgumentOperand() { result = getAnOperand() } + final ArgumentOperand getAnArgumentOperand() { result = this.getAnOperand() } /** * Gets the `Function` that the call targets, if this is statically known. */ final Language::Function getStaticCallTarget() { - result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() + result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() } /** * Gets all of the arguments of the call, including the `this` pointer, if any. */ - final Instruction getAnArgument() { result = getAnArgumentOperand().getDef() } + final Instruction getAnArgument() { result = this.getAnArgumentOperand().getDef() } /** * Gets the `this` pointer argument operand of the call, if any. */ - final ThisArgumentOperand getThisArgumentOperand() { result = getAnOperand() } + final ThisArgumentOperand getThisArgumentOperand() { result = this.getAnOperand() } /** * Gets the `this` pointer argument of the call, if any. */ - final Instruction getThisArgument() { result = getThisArgumentOperand().getDef() } + final Instruction getThisArgument() { result = this.getThisArgumentOperand().getDef() } /** * Gets the argument operand at the specified index. */ pragma[noinline] final PositionalArgumentOperand getPositionalArgumentOperand(int index) { - result = getAnOperand() and + result = this.getAnOperand() and result.getIndex() = index } @@ -1623,7 +1638,7 @@ class CallInstruction extends Instruction { */ pragma[noinline] final Instruction getPositionalArgument(int index) { - result = getPositionalArgumentOperand(index).getDef() + result = this.getPositionalArgumentOperand(index).getDef() } /** @@ -1631,16 +1646,16 @@ class CallInstruction extends Instruction { */ pragma[noinline] final ArgumentOperand getArgumentOperand(int index) { - index >= 0 and result = getPositionalArgumentOperand(index) + index >= 0 and result = this.getPositionalArgumentOperand(index) or - index = -1 and result = getThisArgumentOperand() + index = -1 and result = this.getThisArgumentOperand() } /** * Gets the argument at the specified index, or `this` if `index` is `-1`. */ pragma[noinline] - final Instruction getArgument(int index) { result = getArgumentOperand(index).getDef() } + final Instruction getArgument(int index) { result = this.getArgumentOperand(index).getDef() } /** * Gets the number of arguments of the call, including the `this` pointer, if any. @@ -1665,7 +1680,7 @@ class CallInstruction extends Instruction { * An instruction representing a side effect of a function call. */ class SideEffectInstruction extends Instruction { - SideEffectInstruction() { getOpcode() instanceof SideEffectOpcode } + SideEffectInstruction() { this.getOpcode() instanceof SideEffectOpcode } /** * Gets the instruction whose execution causes this side effect. @@ -1680,7 +1695,7 @@ class SideEffectInstruction extends Instruction { * accessed by that call. */ class CallSideEffectInstruction extends SideEffectInstruction { - CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect } + CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } } /** @@ -1691,7 +1706,7 @@ class CallSideEffectInstruction extends SideEffectInstruction { * call target cannot write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { - CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } + CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } } /** @@ -1699,33 +1714,33 @@ class CallReadSideEffectInstruction extends SideEffectInstruction { * specific parameter. */ class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + ReadSideEffectInstruction() { this.getOpcode() instanceof ReadSideEffectOpcode } /** Gets the operand for the value that will be read from this instruction, if known. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** Gets the value that will be read from this instruction, if known. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** Gets the operand for the address from which this instruction may read. */ - final AddressOperand getArgumentOperand() { result = getAnOperand() } + final AddressOperand getArgumentOperand() { result = this.getAnOperand() } /** Gets the address from which this instruction may read. */ - final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } + final Instruction getArgumentDef() { result = this.getArgumentOperand().getDef() } } /** * An instruction representing the read of an indirect parameter within a function call. */ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { - IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } + IndirectReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::IndirectReadSideEffect } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } + BufferReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::BufferReadSideEffect } } /** @@ -1733,18 +1748,18 @@ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferReadSideEffect + this.getOpcode() instanceof Opcode::SizedBufferReadSideEffect } /** * Gets the operand that holds the number of bytes read from the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes read from the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1752,17 +1767,17 @@ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } + WriteSideEffectInstruction() { this.getOpcode() instanceof WriteSideEffectOpcode } /** * Get the operand that holds the address of the memory to be written. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the memory to be written. */ - Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + Instruction getDestinationAddress() { result = this.getDestinationAddressOperand().getDef() } } /** @@ -1770,7 +1785,7 @@ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstructi */ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMustWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMustWriteSideEffect } } @@ -1780,7 +1795,7 @@ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction */ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { BufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::BufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::BufferMustWriteSideEffect } } @@ -1790,18 +1805,18 @@ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1812,7 +1827,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi */ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMayWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMayWriteSideEffect } } @@ -1822,7 +1837,9 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { * Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten. */ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { - BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect } + BufferMayWriteSideEffectInstruction() { + this.getOpcode() instanceof Opcode::BufferMayWriteSideEffect + } } /** @@ -1832,18 +1849,18 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1852,80 +1869,80 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio */ class InitializeDynamicAllocationInstruction extends SideEffectInstruction { InitializeDynamicAllocationInstruction() { - getOpcode() instanceof Opcode::InitializeDynamicAllocation + this.getOpcode() instanceof Opcode::InitializeDynamicAllocation } /** * Gets the operand that represents the address of the allocation this instruction is initializing. */ - final AddressOperand getAllocationAddressOperand() { result = getAnOperand() } + final AddressOperand getAllocationAddressOperand() { result = this.getAnOperand() } /** * Gets the address for the allocation this instruction is initializing. */ - final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() } + final Instruction getAllocationAddress() { result = this.getAllocationAddressOperand().getDef() } } /** * An instruction representing a GNU or MSVC inline assembly statement. */ class InlineAsmInstruction extends Instruction { - InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm } + InlineAsmInstruction() { this.getOpcode() instanceof Opcode::InlineAsm } } /** * An instruction that throws an exception. */ class ThrowInstruction extends Instruction { - ThrowInstruction() { getOpcode() instanceof ThrowOpcode } + ThrowInstruction() { this.getOpcode() instanceof ThrowOpcode } } /** * An instruction that throws a new exception. */ class ThrowValueInstruction extends ThrowInstruction { - ThrowValueInstruction() { getOpcode() instanceof Opcode::ThrowValue } + ThrowValueInstruction() { this.getOpcode() instanceof Opcode::ThrowValue } /** * Gets the address operand of the exception thrown by this instruction. */ - final AddressOperand getExceptionAddressOperand() { result = getAnOperand() } + final AddressOperand getExceptionAddressOperand() { result = this.getAnOperand() } /** * Gets the address of the exception thrown by this instruction. */ - final Instruction getExceptionAddress() { result = getExceptionAddressOperand().getDef() } + final Instruction getExceptionAddress() { result = this.getExceptionAddressOperand().getDef() } /** * Gets the operand for the exception thrown by this instruction. */ - final LoadOperand getExceptionOperand() { result = getAnOperand() } + final LoadOperand getExceptionOperand() { result = this.getAnOperand() } /** * Gets the exception thrown by this instruction. */ - final Instruction getException() { result = getExceptionOperand().getDef() } + final Instruction getException() { result = this.getExceptionOperand().getDef() } } /** * An instruction that re-throws the current exception. */ class ReThrowInstruction extends ThrowInstruction { - ReThrowInstruction() { getOpcode() instanceof Opcode::ReThrow } + ReThrowInstruction() { this.getOpcode() instanceof Opcode::ReThrow } } /** * An instruction that exits the current function by propagating an exception. */ class UnwindInstruction extends Instruction { - UnwindInstruction() { getOpcode() instanceof Opcode::Unwind } + UnwindInstruction() { this.getOpcode() instanceof Opcode::Unwind } } /** * An instruction that starts a `catch` handler. */ class CatchInstruction extends Instruction { - CatchInstruction() { getOpcode() instanceof CatchOpcode } + CatchInstruction() { this.getOpcode() instanceof CatchOpcode } } /** @@ -1935,7 +1952,7 @@ class CatchByTypeInstruction extends CatchInstruction { Language::LanguageType exceptionType; CatchByTypeInstruction() { - getOpcode() instanceof Opcode::CatchByType and + this.getOpcode() instanceof Opcode::CatchByType and exceptionType = Raw::getInstructionExceptionType(this) } @@ -1951,21 +1968,21 @@ class CatchByTypeInstruction extends CatchInstruction { * An instruction that catches any exception. */ class CatchAnyInstruction extends CatchInstruction { - CatchAnyInstruction() { getOpcode() instanceof Opcode::CatchAny } + CatchAnyInstruction() { this.getOpcode() instanceof Opcode::CatchAny } } /** * An instruction that initializes all escaped memory. */ class AliasedDefinitionInstruction extends Instruction { - AliasedDefinitionInstruction() { getOpcode() instanceof Opcode::AliasedDefinition } + AliasedDefinitionInstruction() { this.getOpcode() instanceof Opcode::AliasedDefinition } } /** * An instruction that consumes all escaped memory on exit from the function. */ class AliasedUseInstruction extends Instruction { - AliasedUseInstruction() { getOpcode() instanceof Opcode::AliasedUse } + AliasedUseInstruction() { this.getOpcode() instanceof Opcode::AliasedUse } } /** @@ -1979,7 +1996,7 @@ class AliasedUseInstruction extends Instruction { * runtime. */ class PhiInstruction extends Instruction { - PhiInstruction() { getOpcode() instanceof Opcode::Phi } + PhiInstruction() { this.getOpcode() instanceof Opcode::Phi } /** * Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block. @@ -2047,29 +2064,29 @@ class PhiInstruction extends Instruction { * https://link.springer.com/content/pdf/10.1007%2F3-540-61053-7_66.pdf. */ class ChiInstruction extends Instruction { - ChiInstruction() { getOpcode() instanceof Opcode::Chi } + ChiInstruction() { this.getOpcode() instanceof Opcode::Chi } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final ChiTotalOperand getTotalOperand() { result = getAnOperand() } + final ChiTotalOperand getTotalOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final Instruction getTotal() { result = getTotalOperand().getDef() } + final Instruction getTotal() { result = this.getTotalOperand().getDef() } /** * Gets the operand that represents the new value written by the memory write. */ - final ChiPartialOperand getPartialOperand() { result = getAnOperand() } + final ChiPartialOperand getPartialOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the new value written by the memory write. */ - final Instruction getPartial() { result = getPartialOperand().getDef() } + final Instruction getPartial() { result = this.getPartialOperand().getDef() } /** * Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand. @@ -2093,7 +2110,7 @@ class ChiInstruction extends Instruction { * or `Switch` instruction where that particular edge is infeasible. */ class UnreachedInstruction extends Instruction { - UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached } + UnreachedInstruction() { this.getOpcode() instanceof Opcode::Unreached } } /** @@ -2106,7 +2123,7 @@ class BuiltInOperationInstruction extends Instruction { Language::BuiltInOperation operation; BuiltInOperationInstruction() { - getOpcode() instanceof BuiltInOperationOpcode and + this.getOpcode() instanceof BuiltInOperationOpcode and operation = Raw::getInstructionBuiltInOperation(this) } @@ -2122,9 +2139,9 @@ class BuiltInOperationInstruction extends Instruction { * actual operation is specified by the `getBuiltInOperation()` predicate. */ class BuiltInInstruction extends BuiltInOperationInstruction { - BuiltInInstruction() { getOpcode() instanceof Opcode::BuiltIn } + BuiltInInstruction() { this.getOpcode() instanceof Opcode::BuiltIn } - final override string getImmediateString() { result = getBuiltInOperation().toString() } + final override string getImmediateString() { result = this.getBuiltInOperation().toString() } } /** @@ -2135,7 +2152,7 @@ class BuiltInInstruction extends BuiltInOperationInstruction { * to the `...` parameter. */ class VarArgsStartInstruction extends UnaryInstruction { - VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart } + VarArgsStartInstruction() { this.getOpcode() instanceof Opcode::VarArgsStart } } /** @@ -2145,7 +2162,7 @@ class VarArgsStartInstruction extends UnaryInstruction { * a result. */ class VarArgsEndInstruction extends UnaryInstruction { - VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd } + VarArgsEndInstruction() { this.getOpcode() instanceof Opcode::VarArgsEnd } } /** @@ -2155,7 +2172,7 @@ class VarArgsEndInstruction extends UnaryInstruction { * argument. */ class VarArgInstruction extends UnaryInstruction { - VarArgInstruction() { getOpcode() instanceof Opcode::VarArg } + VarArgInstruction() { this.getOpcode() instanceof Opcode::VarArg } } /** @@ -2166,7 +2183,7 @@ class VarArgInstruction extends UnaryInstruction { * argument of the `...` parameter. */ class NextVarArgInstruction extends UnaryInstruction { - NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg } + NextVarArgInstruction() { this.getOpcode() instanceof Opcode::NextVarArg } } /** @@ -2180,5 +2197,5 @@ class NextVarArgInstruction extends UnaryInstruction { * The result is the address of the newly allocated object. */ class NewObjInstruction extends Instruction { - NewObjInstruction() { getOpcode() instanceof Opcode::NewObj } + NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj } } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll b/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll index d7cf89ca9aa..85d217bd361 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll @@ -46,12 +46,12 @@ class Operand extends TStageOperand { /** * Gets the location of the source code for this operand. */ - final Language::Location getLocation() { result = getUse().getLocation() } + final Language::Location getLocation() { result = this.getUse().getLocation() } /** * Gets the function that contains this operand. */ - final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() } + final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() } /** * Gets the `Instruction` that consumes this operand. @@ -74,7 +74,7 @@ class Operand extends TStageOperand { */ final Instruction getDef() { result = this.getAnyDef() and - getDefinitionOverlap() instanceof MustExactlyOverlap + this.getDefinitionOverlap() instanceof MustExactlyOverlap } /** @@ -82,7 +82,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` that consumes this operand. */ - deprecated final Instruction getUseInstruction() { result = getUse() } + deprecated final Instruction getUseInstruction() { result = this.getUse() } /** * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this @@ -91,7 +91,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` whose result is the value of the operand. */ - deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() } + deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } /** * Gets the overlap relationship between the operand's definition and its use. @@ -101,7 +101,9 @@ class Operand extends TStageOperand { /** * Holds if the result of the definition instruction does not exactly overlap this use. */ - final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap } + final predicate isDefinitionInexact() { + not this.getDefinitionOverlap() instanceof MustExactlyOverlap + } /** * Gets a prefix to use when dumping the operand in an operand list. @@ -121,7 +123,7 @@ class Operand extends TStageOperand { * For example: `this:r3_5` */ final string getDumpString() { - result = getDumpLabel() + getInexactSpecifier() + getDefinitionId() + result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId() } /** @@ -129,9 +131,9 @@ class Operand extends TStageOperand { * definition is not modeled in SSA. */ private string getDefinitionId() { - result = getAnyDef().getResultId() + result = this.getAnyDef().getResultId() or - not exists(getAnyDef()) and result = "m?" + not exists(this.getAnyDef()) and result = "m?" } /** @@ -140,7 +142,7 @@ class Operand extends TStageOperand { * the empty string. */ private string getInexactSpecifier() { - if isDefinitionInexact() then result = "~" else result = "" + if this.isDefinitionInexact() then result = "~" else result = "" } /** @@ -155,7 +157,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() } + Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() } /** * Gets the language-neutral type of the value consumed by this operand. This is usually the same @@ -164,7 +166,7 @@ class Operand extends TStageOperand { * from the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final IRType getIRType() { result = getLanguageType().getIRType() } + final IRType getIRType() { result = this.getLanguageType().getIRType() } /** * Gets the type of the value consumed by this operand. This is usually the same as the @@ -173,7 +175,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final Language::Type getType() { getLanguageType().hasType(result, _) } + final Language::Type getType() { this.getLanguageType().hasType(result, _) } /** * Holds if the value consumed by this operand is a glvalue. If this @@ -182,13 +184,13 @@ class Operand extends TStageOperand { * not hold, the value of the operand represents a value whose type is * given by `getType()`. */ - final predicate isGLValue() { getLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getLanguageType().hasType(_, true) } /** * Gets the size of the value consumed by this operand, in bytes. If the operand does not have * a known constant size, this predicate does not hold. */ - final int getSize() { result = getLanguageType().getByteSize() } + final int getSize() { result = this.getLanguageType().getByteSize() } } /** @@ -205,7 +207,7 @@ class MemoryOperand extends Operand { /** * Gets the kind of memory access performed by the operand. */ - MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() } + MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() } /** * Holds if the memory access performed by this operand will not always read from every bit in the @@ -215,7 +217,7 @@ class MemoryOperand extends Operand { * conservative estimate of the memory that might actually be accessed at runtime (for example, * the global side effects of a function call). */ - predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() } + predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() } /** * Returns the operand that holds the memory address from which the current operand loads its @@ -223,8 +225,8 @@ class MemoryOperand extends Operand { * is `r1`. */ final AddressOperand getAddressOperand() { - getMemoryAccess().usesAddressOperand() and - result.getUse() = getUse() + this.getMemoryAccess().usesAddressOperand() and + result.getUse() = this.getUse() } } @@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe result = unique(Instruction defInstr | hasDefinition(defInstr, _)) } - final override Overlap getDefinitionOverlap() { hasDefinition(_, result) } + final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) } pragma[noinline] private predicate hasDefinition(Instruction defInstr, Overlap overlap) { @@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand { final override Overlap getDefinitionOverlap() { result = overlap } - final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() } - - final override string getDumpLabel() { - result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" + final override int getDumpSortOrder() { + result = 11 + this.getPredecessorBlock().getDisplayIndex() } - final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() } + final override string getDumpLabel() { + result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":" + } + + final override string getDumpId() { + result = this.getPredecessorBlock().getDisplayIndex().toString() + } /** * Gets the predecessor block from which this value comes. diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll index a172800b377..99833c70d0b 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll @@ -139,13 +139,13 @@ class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation { override LogicalOrExpr expr; override Instruction getChildTrueSuccessor(ConditionBase child) { - child = getAnOperand() and + child = this.getAnOperand() and result = this.getConditionContext().getChildTrueSuccessor(this) } override Instruction getChildFalseSuccessor(ConditionBase child) { child = this.getLeftOperand() and - result = getRightOperand().getFirstInstruction() + result = this.getRightOperand().getFirstInstruction() or child = this.getRightOperand() and result = this.getConditionContext().getChildFalseSuccessor(this) diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll index 86cbdbb4360..9b4fbbba723 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll @@ -48,7 +48,7 @@ class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration, override LocalVariable getDeclVar() { result = var } - override Type getVarType() { result = getVariableType(getDeclVar()) } + override Type getVarType() { result = getVariableType(this.getDeclVar()) } override Type getTargetType() { result = getVariableType(var) } @@ -58,7 +58,7 @@ class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration, or this.hasUninitializedInstruction() and tag = InitializerStoreTag() ) and - result = getIRUserVariable(getFunction(), getDeclVar()) + result = getIRUserVariable(this.getFunction(), this.getDeclVar()) } override TranslatedInitialization getInitialization() { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedElement.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedElement.qll index 04e05dc9814..ea1ad7931cb 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedElement.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedElement.qll @@ -456,7 +456,7 @@ abstract class TranslatedElement extends TTranslatedElement { * there is no enclosing `try`. */ Instruction getExceptionSuccessorInstruction() { - result = getParent().getExceptionSuccessorInstruction() + result = this.getParent().getExceptionSuccessorInstruction() } /** @@ -558,7 +558,7 @@ abstract class TranslatedElement extends TTranslatedElement { * Gets the temporary variable generated by this element with tag `tag`. */ final IRTempVariable getTempVariable(TempVariableTag tag) { - result.getAST() = getAST() and + result.getAST() = this.getAST() and result.getTag() = tag and this.hasTempVariable(tag, _) } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll index 72c408a3f2a..362ed3e0d2b 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll @@ -98,7 +98,7 @@ abstract class TranslatedCoreExpr extends TranslatedExpr { } final CSharpType getResultCSharpType() { - if isResultLValue() = true + if this.isResultLValue() = true then result = getTypeForGLValue(expr.getType()) else result = getTypeForPRValue(expr.getType()) } @@ -138,18 +138,18 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, tag = ConditionValueFalseConstantTag() ) and opcode instanceof Opcode::Constant and - resultType = getResultCSharpType() + resultType = this.getResultCSharpType() or ( tag = ConditionValueTrueStoreTag() or tag = ConditionValueFalseStoreTag() ) and opcode instanceof Opcode::Store and - resultType = getResultCSharpType() + resultType = this.getResultCSharpType() or tag = ConditionValueResultLoadTag() and opcode instanceof Opcode::Load and - resultType = getResultCSharpType() + resultType = this.getResultCSharpType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { @@ -258,7 +258,7 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) { tag = LoadTag() and opcode instanceof Opcode::Load and - if producesExprResult() + if this.producesExprResult() then resultType = getTypeForPRValue(expr.getType()) else resultType = getTypeForGLValue(expr.getType()) } @@ -542,7 +542,7 @@ class TranslatedArrayAccess extends TranslatedNonConstantExpr { } final override TranslatedElement getChild(int id) { - id = -1 and result = getBaseOperand() + id = -1 and result = this.getBaseOperand() or result = this.getOffsetOperand(id) } @@ -559,7 +559,7 @@ class TranslatedArrayAccess extends TranslatedNonConstantExpr { or // The successor of the last `PointerAdd` instruction is // the successor of the `TranslatedArrayAccess`. - tag = PointerAddTag(getRank() - 1) and + tag = PointerAddTag(this.getRank() - 1) and result = this.getParent().getChildSuccessor(this) or // The successor of an `ElementsAddress` instruction is @@ -582,27 +582,29 @@ class TranslatedArrayAccess extends TranslatedNonConstantExpr { result = this.getInstruction(PointerAddTag(child.getAST().getIndex())) } - override Instruction getResult() { result = this.getInstruction(PointerAddTag(getRank() - 1)) } + override Instruction getResult() { + result = this.getInstruction(PointerAddTag(this.getRank() - 1)) + } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) { exists(int index | - inBounds(index) and + this.inBounds(index) and tag = PointerAddTag(index) and opcode instanceof Opcode::PointerAdd and - resultType = getTypeForPRValue(getArrayOfDim(getRank() - index, expr.getType())) + resultType = getTypeForPRValue(getArrayOfDim(this.getRank() - index, expr.getType())) ) or exists(int index | - inBounds(index) and + this.inBounds(index) and tag = ElementsAddressTag(index) and opcode instanceof Opcode::ElementsAddress and - resultType = getTypeForPRValue(getArrayOfDim(getRank() - index, expr.getType())) + resultType = getTypeForPRValue(getArrayOfDim(this.getRank() - index, expr.getType())) ) } override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { exists(int index | - inBounds(index) and + this.inBounds(index) and tag = PointerAddTag(index) and ( operandTag instanceof LeftOperandTag and @@ -632,7 +634,7 @@ class TranslatedArrayAccess extends TranslatedNonConstantExpr { override int getInstructionElementSize(InstructionTag tag) { exists(int index | - inBounds(index) and + this.inBounds(index) and tag = PointerAddTag(index) and result = Language::getTypeSize(expr.getQualifier().getType().(ArrayType).getElementType()) ) @@ -989,9 +991,9 @@ abstract class TranslatedSingleInstructionExpr extends TranslatedNonConstantExpr abstract Opcode getOpcode(); final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) { - opcode = getOpcode() and + opcode = this.getOpcode() and tag = OnlyInstructionTag() and - resultType = getResultCSharpType() + resultType = this.getResultCSharpType() } final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } @@ -1189,7 +1191,7 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { override int getInstructionElementSize(InstructionTag tag) { tag = OnlyInstructionTag() and exists(Opcode opcode | - opcode = getOpcode() and + opcode = this.getOpcode() and ( opcode instanceof Opcode::PointerAdd or opcode instanceof Opcode::PointerSub or @@ -1200,7 +1202,9 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { } private TranslatedExpr getPointerOperand() { - if swapOperandsOnOp() then result = this.getRightOperand() else result = this.getLeftOperand() + if this.swapOperandsOnOp() + then result = this.getRightOperand() + else result = this.getLeftOperand() } private predicate swapOperandsOnOp() { @@ -1425,7 +1429,7 @@ class TranslatedAssignOperation extends TranslatedAssignment { resultType = getTypeForPRValue(this.getLeftOperand().getResultType()) or tag = AssignOperationOpTag() and - opcode = getOpcode() and + opcode = this.getOpcode() and resultType = getTypeForPRValue(this.getConvertedLeftOperandType()) or tag = AssignmentStoreTag() and @@ -1452,7 +1456,7 @@ class TranslatedAssignOperation extends TranslatedAssignment { opcode instanceof Opcode::PointerSub ) ) and - result = Language::getTypeSize(getResultType().(PointerType).getReferentType()) + result = Language::getTypeSize(this.getResultType().(PointerType).getReferentType()) } override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { @@ -1799,7 +1803,7 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr { result = this.getInstruction(GeneratedConstantTag()) ) or - hasVar() and + this.hasVar() and tag = GeneratedBranchTag() and operandTag instanceof ConditionOperandTag and result = this.getInstruction(GeneratedNEQTag()) @@ -1848,7 +1852,7 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and + child = this.getInitialization() and result = this.getInstruction(LoadTag()) } @@ -1922,7 +1926,7 @@ class TranslatedDelegateCall extends TranslatedNonConstantExpr { override Instruction getChildSuccessor(TranslatedElement child) { child = this.getInvokeCall() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) { @@ -1973,7 +1977,7 @@ abstract class TranslatedCreation extends TranslatedCoreExpr, TTranslatedCreatio else result = this.getInstruction(NewObjTag()) } - override Instruction getReceiver() { result = getInstruction(NewObjTag()) } + override Instruction getReceiver() { result = this.getInstruction(NewObjTag()) } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and @@ -1998,11 +2002,11 @@ abstract class TranslatedCreation extends TranslatedCoreExpr, TTranslatedCreatio child = this.getConstructorCall() and if exists(this.getInitializerExpr()) then result = this.getInitializerExpr().getFirstInstruction() - else result = getLoadOrChildSuccessor() + else result = this.getLoadOrChildSuccessor() ) or child = this.getInitializerExpr() and - result = getLoadOrChildSuccessor() + result = this.getLoadOrChildSuccessor() } private Instruction getLoadOrChildSuccessor() { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedFunction.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedFunction.qll index 65488a1b95d..94b48b0985d 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedFunction.qll @@ -68,20 +68,20 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { or ( tag = AliasedDefinitionTag() and - if exists(getThisType()) + if exists(this.getThisType()) then result = this.getInstruction(InitializeThisTag()) else - if exists(getParameter(0)) + if exists(this.getParameter(0)) then result = this.getParameter(0).getFirstInstruction() else result = this.getBodyOrReturn() ) or ( tag = InitializeThisTag() and - if exists(getParameter(0)) + if exists(this.getParameter(0)) then result = this.getParameter(0).getFirstInstruction() else - if exists(getConstructorInitializer()) + if exists(this.getConstructorInitializer()) then result = this.getConstructorInitializer().getFirstInstruction() else result = this.getBodyOrReturn() ) @@ -106,7 +106,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { if exists(callable.getParameter(paramIndex + 1)) then result = this.getParameter(paramIndex + 1).getFirstInstruction() else - if exists(getConstructorInitializer()) + if exists(this.getConstructorInitializer()) then result = this.getConstructorInitializer().getFirstInstruction() else result = this.getBodyOrReturn() ) @@ -136,12 +136,12 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { or tag = InitializeThisTag() and opcode instanceof Opcode::InitializeThis and - resultType = getTypeForGLValue(getThisType()) + resultType = getTypeForGLValue(this.getThisType()) or tag = ReturnValueAddressTag() and opcode instanceof Opcode::VariableAddress and - not getReturnType() instanceof VoidType and - resultType = getTypeForGLValue(getReturnType()) + not this.getReturnType() instanceof VoidType and + resultType = getTypeForGLValue(this.getReturnType()) or ( tag = ReturnTag() and @@ -201,7 +201,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { final override predicate hasTempVariable(TempVariableTag tag, CSharpType type) { tag = ReturnValueTempVar() and type = getTypeForPRValue(this.getReturnType()) and - not getReturnType() instanceof VoidType + not this.getReturnType() instanceof VoidType } /** @@ -320,7 +320,7 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter { tag = InitializerStoreTag() or tag = InitializerVariableAddressTag() ) and - result = getIRUserVariable(getFunction(), param) + result = getIRUserVariable(this.getFunction(), param) } final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll index cbe0e7c1d2a..77e41c15e72 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -139,7 +139,7 @@ class TranslatedDirectInitialization extends TranslatedInitialization { opcode instanceof Opcode::Store and resultType = getTypeForPRValue(this.getContext().getTargetType()) or - needsConversion() and + this.needsConversion() and tag = AssignmentConvertRightTag() and // For now only use `Opcode::Convert` to // crudely represent conversions. Could @@ -153,9 +153,9 @@ class TranslatedDirectInitialization extends TranslatedInitialization { result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge or - needsConversion() and + this.needsConversion() and tag = AssignmentConvertRightTag() and - result = getInstruction(InitializerStoreTag()) and + result = this.getInstruction(InitializerStoreTag()) and kind instanceof GotoEdge } @@ -203,7 +203,7 @@ abstract class TranslatedElementInitialization extends TranslatedElement { ArrayInitializer initList; final override string toString() { - result = initList.toString() + "[" + getElementIndex().toString() + "]" + result = initList.toString() + "[" + this.getElementIndex().toString() + "]" } final override Language::AST getAST() { result = initList } @@ -211,54 +211,54 @@ abstract class TranslatedElementInitialization extends TranslatedElement { final override Callable getFunction() { result = initList.getEnclosingCallable() } final override Instruction getFirstInstruction() { - result = this.getInstruction(getElementIndexTag()) + result = this.getInstruction(this.getElementIndexTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType 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 = this.getInstruction(getElementAddressTag()) and + tag = this.getElementIndexTag() and + result = this.getInstruction(this.getElementAddressTag()) and kind instanceof GotoEdge } override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { - tag = getElementAddressTag() and + tag = this.getElementAddressTag() and ( operandTag instanceof LeftOperandTag and result = this.getParent().(InitializationContext).getTargetAddress() or operandTag instanceof RightOperandTag and - result = this.getInstruction(getElementIndexTag()) + result = this.getInstruction(this.getElementIndexTag()) ) } override int getInstructionElementSize(InstructionTag tag) { - tag = getElementAddressTag() and - result = Language::getTypeSize(getElementType()) + tag = this.getElementAddressTag() and + result = Language::getTypeSize(this.getElementType()) } override string getInstructionConstantValue(InstructionTag tag) { - tag = getElementIndexTag() and - result = getElementIndex().toString() + tag = this.getElementIndexTag() and + result = this.getElementIndex().toString() } abstract int getElementIndex(); final InstructionTag getElementAddressTag() { - result = InitializerElementAddressTag(getElementIndex()) + result = InitializerElementAddressTag(this.getElementIndex()) } final InstructionTag getElementIndexTag() { - result = InitializerElementIndexTag(getElementIndex()) + result = InitializerElementIndexTag(this.getElementIndex()) } final ArrayInitializer getInitList() { result = initList } @@ -278,14 +278,16 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ this = TTranslatedExplicitElementInitialization(initList, elementIndex) } - override Instruction getTargetAddress() { result = this.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 + tag = this.getElementAddressTag() and result = this.getInitialization().getFirstInstruction() and kind instanceof GotoEdge } @@ -340,7 +342,7 @@ class TranslatedConstructorInitializer extends TranslatedConstructorCallFromCons override string toString() { result = "constructor init: " + call.toString() } override Instruction getFirstInstruction() { - if needsConversion() + if this.needsConversion() then result = this.getInstruction(OnlyInstructionTag()) else result = this.getConstructorCall().getFirstInstruction() } @@ -361,13 +363,13 @@ class TranslatedConstructorInitializer extends TranslatedConstructorCallFromCons override Instruction getReceiver() { if this.needsConversion() then result = this.getInstruction(OnlyInstructionTag()) - else result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() + else result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction() } override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and - result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() + result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction() } predicate needsConversion() { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedStmt.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedStmt.qll index 81de9a6b7c9..2f91484094a 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedStmt.qll @@ -79,7 +79,7 @@ class TranslatedDeclStmt extends TranslatedStmt { override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | child = this.getLocalDeclaration(index) and - if index = (getChildCount() - 1) + if index = (this.getChildCount() - 1) then result = this.getParent().getChildSuccessor(this) else result = this.getLocalDeclaration(index + 1).getFirstInstruction() ) @@ -276,14 +276,14 @@ class TranslatedBlock extends TranslatedStmt { override TranslatedElement getChild(int id) { result = this.getStmt(id) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) { - isEmpty() and + this.isEmpty() and opcode instanceof Opcode::NoOp and tag = OnlyInstructionTag() and resultType = getVoidType() } override Instruction getFirstInstruction() { - if isEmpty() + if this.isEmpty() then result = this.getInstruction(OnlyInstructionTag()) else result = this.getStmt(0).getFirstInstruction() } @@ -303,7 +303,7 @@ class TranslatedBlock extends TranslatedStmt { override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | child = this.getStmt(index) and - if index = (getStmtCount() - 1) + if index = (this.getStmtCount() - 1) then result = this.getParent().getChildSuccessor(this) else result = this.getStmt(index + 1).getFirstInstruction() ) @@ -347,7 +347,7 @@ class TranslatedCatchByTypeClause extends TranslatedClause { } override TranslatedElement getChild(int id) { - id = 0 and result = getParameter() + id = 0 and result = this.getParameter() or result = super.getChild(id) } @@ -355,14 +355,14 @@ class TranslatedCatchByTypeClause extends TranslatedClause { override Instruction getChildSuccessor(TranslatedElement child) { result = super.getChildSuccessor(child) or - child = getParameter() and result = this.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 = this.getParent().(TranslatedTryStmt).getNextHandler(this) @@ -559,8 +559,8 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext { final TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getBody()) } final Instruction getFirstConditionInstruction() { - if hasCondition() - then result = getCondition().getFirstInstruction() + if this.hasCondition() + then result = this.getCondition().getFirstInstruction() else result = this.getBody().getFirstInstruction() } @@ -611,13 +611,13 @@ class TranslatedForStmt extends TranslatedLoop { override ForStmt stmt; override TranslatedElement getChild(int id) { - initializerIndex(id) and result = this.getDeclAndInit(id) + this.initializerIndex(id) and result = this.getDeclAndInit(id) or - result = this.getUpdate(updateIndex(id)) + result = this.getUpdate(this.updateIndex(id)) or - id = initializersNo() + updatesNo() and result = this.getCondition() + id = this.initializersNo() + this.updatesNo() and result = this.getCondition() or - id = initializersNo() + updatesNo() + 1 and result = this.getBody() + id = this.initializersNo() + this.updatesNo() + 1 and result = this.getBody() } private TranslatedElement getDeclAndInit(int index) { @@ -636,11 +636,11 @@ class TranslatedForStmt extends TranslatedLoop { private int updatesNo() { result = count(stmt.getAnUpdate()) } - private predicate initializerIndex(int index) { index in [0 .. initializersNo() - 1] } + private predicate initializerIndex(int index) { index in [0 .. this.initializersNo() - 1] } private int updateIndex(int index) { - result in [0 .. updatesNo() - 1] and - index = initializersNo() + result + result in [0 .. this.updatesNo() - 1] and + index = this.initializersNo() + result } override Instruction getFirstInstruction() { @@ -652,11 +652,11 @@ class TranslatedForStmt extends TranslatedLoop { override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | child = this.getDeclAndInit(index) and - index < initializersNo() - 1 and + index < this.initializersNo() - 1 and result = this.getDeclAndInit(index + 1).getFirstInstruction() ) or - child = this.getDeclAndInit(initializersNo() - 1) and + child = this.getDeclAndInit(this.initializersNo() - 1) and result = this.getFirstConditionInstruction() or ( @@ -671,7 +671,7 @@ class TranslatedForStmt extends TranslatedLoop { result = this.getUpdate(index + 1).getFirstInstruction() ) or - child = this.getUpdate(updatesNo() - 1) and + child = this.getUpdate(this.updatesNo() - 1) and result = this.getFirstConditionInstruction() } } @@ -693,7 +693,7 @@ abstract class TranslatedSpecificJump extends TranslatedStmt { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and - result = getTargetInstruction() + result = this.getTargetInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { none() } @@ -832,7 +832,7 @@ class TranslatedSwitchStmt extends TranslatedStmt { not exists(stmt.getDefaultCase()) and tag = SwitchBranchTag() and kind instanceof DefaultEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } private EdgeKind getCaseEdge(CaseStmt caseStmt) { @@ -862,19 +862,21 @@ class TranslatedEnumeratorForeach extends TranslatedLoop { override ForeachStmt stmt; override TranslatedElement getChild(int id) { - id = 0 and result = getTempEnumDecl() + id = 0 and result = this.getTempEnumDecl() or - id = 1 and result = getTry() + id = 1 and result = this.getTry() } - override Instruction getFirstInstruction() { result = getTempEnumDecl().getFirstInstruction() } + override Instruction getFirstInstruction() { + result = this.getTempEnumDecl().getFirstInstruction() + } override Instruction getChildSuccessor(TranslatedElement child) { - child = getTempEnumDecl() and - result = getTry().getFirstInstruction() + child = this.getTempEnumDecl() and + result = this.getTry().getFirstInstruction() or - child = getTry() and - result = getParent().getChildSuccessor(this) + child = this.getTry() and + result = this.getParent().getChildSuccessor(this) } private TranslatedElement getTry() { result = ForeachElements::getTry(stmt) } @@ -909,9 +911,9 @@ class TranslatedFixedStmt extends TranslatedStmt { override FixedStmt stmt; override TranslatedElement getChild(int id) { - result = getDecl(id) + result = this.getDecl(id) or - id = noDecls() and result = this.getBody() + id = this.noDecls() and result = this.getBody() } override Instruction getFirstInstruction() { result = this.getDecl(0).getFirstInstruction() } @@ -947,24 +949,26 @@ class TranslatedLockStmt extends TranslatedStmt { override LockStmt stmt; override TranslatedElement getChild(int id) { - id = 0 and result = getLockedVarDecl() + id = 0 and result = this.getLockedVarDecl() or - id = 1 and result = getLockWasTakenDecl() + id = 1 and result = this.getLockWasTakenDecl() or - id = 2 and result = getTry() + id = 2 and result = this.getTry() } - override Instruction getFirstInstruction() { result = getLockedVarDecl().getFirstInstruction() } + override Instruction getFirstInstruction() { + result = this.getLockedVarDecl().getFirstInstruction() + } override Instruction getChildSuccessor(TranslatedElement child) { - child = getLockedVarDecl() and - result = getLockWasTakenDecl().getFirstInstruction() + child = this.getLockedVarDecl() and + result = this.getLockWasTakenDecl().getFirstInstruction() or - child = getLockWasTakenDecl() and - result = getTry().getFirstInstruction() + child = this.getLockWasTakenDecl() and + result = this.getTry().getFirstInstruction() or - child = getTry() and - result = getParent().getChildSuccessor(this) + child = this.getTry() and + result = this.getParent().getChildSuccessor(this) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) { @@ -1017,13 +1021,13 @@ class TranslatedUsingBlockStmt extends TranslatedStmt { override UsingBlockStmt stmt; override TranslatedElement getChild(int id) { - result = getDecl(id) + result = this.getDecl(id) or - id = getNumberOfDecls() and result = this.getBody() + id = this.getNumberOfDecls() and result = this.getBody() } override Instruction getFirstInstruction() { - if getNumberOfDecls() > 0 + if this.getNumberOfDecls() > 0 then result = this.getDecl(0).getFirstInstruction() else result = this.getBody().getFirstInstruction() } @@ -1060,7 +1064,7 @@ class TranslatedUsingBlockStmt extends TranslatedStmt { class TranslatedUsingDeclStmt extends TranslatedStmt { override UsingDeclStmt stmt; - override TranslatedElement getChild(int id) { result = getDecl(id) } + override TranslatedElement getChild(int id) { result = this.getDecl(id) } override Instruction getFirstInstruction() { result = this.getDecl(0).getFirstInstruction() } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll index 4b86f9a7cec..bb8630a5e0c 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll @@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock { final string toString() { result = getFirstInstruction(this).toString() } /** Gets the source location of the first non-`Phi` instruction in this block. */ - final Language::Location getLocation() { result = getFirstInstruction().getLocation() } + final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() } /** * INTERNAL: Do not use. @@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock { ) and this = rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = getEnclosingFunction() and + funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and // Ensure that the block containing `EnterFunction` always comes first. if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction @@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock { * Get the `Phi` instructions that appear at the start of this block. */ final PhiInstruction getAPhiInstruction() { - Construction::getPhiInstructionBlockStart(result) = getFirstInstruction() + Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction() } /** * Gets an instruction in this block. This includes `Phi` instructions. */ final Instruction getAnInstruction() { - result = getInstruction(_) or - result = getAPhiInstruction() + result = this.getInstruction(_) or + result = this.getAPhiInstruction() } /** @@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock { /** * Gets the last instruction in this block. */ - final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) } + final Instruction getLastInstruction() { + result = this.getInstruction(this.getInstructionCount() - 1) + } /** * Gets the number of non-`Phi` instructions in this block. @@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase { * Block `A` dominates block `B` if any control flow path from the entry block of the function to * block `B` must pass through block `A`. A block always dominates itself. */ - final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block } + final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block } /** * Gets a block on the dominance frontier of this block. @@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock dominanceFrontier() { - dominates(result.getAPredecessor()) and - not strictlyDominates(result) + this.dominates(result.getAPredecessor()) and + not this.strictlyDominates(result) } /** @@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase { * Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the * function must pass through block `A`. A block always post-dominates itself. */ - final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block } + final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block } /** * Gets a block on the post-dominance frontier of this block. @@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock postPominanceFrontier() { - postDominates(result.getASuccessor()) and - not strictlyPostDominates(result) + this.postDominates(result.getASuccessor()) and + not this.strictlyPostDominates(result) } /** * Holds if this block is reachable from the entry block of its function. */ final predicate isReachableFromFunctionEntry() { - this = getEnclosingIRFunction().getEntryBlock() or - getAPredecessor().isReachableFromFunctionEntry() + this = this.getEnclosingIRFunction().getEntryBlock() or + this.getAPredecessor().isReachableFromFunctionEntry() } } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll index 6f471d8a7e8..88a973fc5a8 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll @@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction { } /** Gets a textual representation of this element. */ - final string toString() { result = getOpcode().toString() + ": " + getAST().toString() } + final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() } /** * Gets a string showing the result, opcode, and operands of the instruction, equivalent to what @@ -50,7 +50,8 @@ class Instruction extends Construction::TStageInstruction { * `mu0_28(int) = Store r0_26, r0_27` */ final string getDumpString() { - result = getResultString() + " = " + getOperationString() + " " + getOperandsString() + result = + this.getResultString() + " = " + this.getOperationString() + " " + this.getOperandsString() } private predicate shouldGenerateDumpStrings() { @@ -66,10 +67,13 @@ class Instruction extends Construction::TStageInstruction { * VariableAddress[x] */ final string getOperationString() { - shouldGenerateDumpStrings() and - if exists(getImmediateString()) - then result = getOperationPrefix() + getOpcode().toString() + "[" + getImmediateString() + "]" - else result = getOperationPrefix() + getOpcode().toString() + this.shouldGenerateDumpStrings() and + if exists(this.getImmediateString()) + then + result = + this.getOperationPrefix() + this.getOpcode().toString() + "[" + this.getImmediateString() + + "]" + else result = this.getOperationPrefix() + this.getOpcode().toString() } /** @@ -78,17 +82,17 @@ class Instruction extends Construction::TStageInstruction { string getImmediateString() { none() } private string getOperationPrefix() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and if this instanceof SideEffectInstruction then result = "^" else result = "" } private string getResultPrefix() { - shouldGenerateDumpStrings() and - if getResultIRType() instanceof IRVoidType + this.shouldGenerateDumpStrings() and + if this.getResultIRType() instanceof IRVoidType then result = "v" else - if hasMemoryResult() - then if isResultModeled() then result = "m" else result = "mu" + if this.hasMemoryResult() + then if this.isResultModeled() then result = "m" else result = "mu" else result = "r" } @@ -97,7 +101,7 @@ class Instruction extends Construction::TStageInstruction { * used by debugging and printing code only. */ int getDisplayIndexInBlock() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and exists(IRBlock block | this = block.getInstruction(result) or @@ -111,12 +115,12 @@ class Instruction extends Construction::TStageInstruction { } private int getLineRank() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and this = rank[result](Instruction instr | instr = - getAnInstructionAtLine(getEnclosingIRFunction(), getLocation().getFile(), - getLocation().getStartLine()) + getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), + this.getLocation().getStartLine()) | instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() ) @@ -130,8 +134,9 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1` */ string getResultId() { - shouldGenerateDumpStrings() and - result = getResultPrefix() + getAST().getLocation().getStartLine() + "_" + getLineRank() + this.shouldGenerateDumpStrings() and + result = + this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank() } /** @@ -142,8 +147,8 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1(int*)` */ final string getResultString() { - shouldGenerateDumpStrings() and - result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")" + this.shouldGenerateDumpStrings() and + result = this.getResultId() + "(" + this.getResultLanguageType().getDumpString() + ")" } /** @@ -153,10 +158,10 @@ class Instruction extends Construction::TStageInstruction { * Example: `func:r3_4, this:r3_5` */ string getOperandsString() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and result = concat(Operand operand | - operand = getAnOperand() + operand = this.getAnOperand() | operand.getDumpString(), ", " order by operand.getDumpSortOrder() ) @@ -190,7 +195,7 @@ class Instruction extends Construction::TStageInstruction { * Gets the function that contains this instruction. */ final Language::Function getEnclosingFunction() { - result = getEnclosingIRFunction().getFunction() + result = this.getEnclosingIRFunction().getFunction() } /** @@ -208,7 +213,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the location of the source code for this instruction. */ - final Language::Location getLocation() { result = getAST().getLocation() } + final Language::Location getLocation() { result = this.getAST().getLocation() } /** * Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a @@ -243,7 +248,7 @@ class Instruction extends Construction::TStageInstruction { * a result, its result type will be `IRVoidType`. */ cached - final IRType getResultIRType() { result = getResultLanguageType().getIRType() } + final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() } /** * Gets the type of the result produced by this instruction. If the @@ -254,7 +259,7 @@ class Instruction extends Construction::TStageInstruction { */ final Language::Type getResultType() { exists(Language::LanguageType resultType | - resultType = getResultLanguageType() and + resultType = this.getResultLanguageType() and ( resultType.hasUnspecifiedType(result, _) or @@ -283,7 +288,7 @@ class Instruction extends Construction::TStageInstruction { * result of the `Load` instruction is a prvalue of type `int`, representing * the integer value loaded from variable `x`. */ - final predicate isGLValue() { getResultLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getResultLanguageType().hasType(_, true) } /** * Gets the size of the result produced by this instruction, in bytes. If the @@ -292,7 +297,7 @@ class Instruction extends Construction::TStageInstruction { * If `this.isGLValue()` holds for this instruction, the value of * `getResultSize()` will always be the size of a pointer. */ - final int getResultSize() { result = getResultLanguageType().getByteSize() } + final int getResultSize() { result = this.getResultLanguageType().getByteSize() } /** * Gets the opcode that specifies the operation performed by this instruction. @@ -314,14 +319,16 @@ class Instruction extends Construction::TStageInstruction { /** * Holds if this instruction produces a memory result. */ - final predicate hasMemoryResult() { exists(getResultMemoryAccess()) } + final predicate hasMemoryResult() { exists(this.getResultMemoryAccess()) } /** * Gets the kind of memory access performed by this instruction's result. * Holds only for instructions with a memory result. */ pragma[inline] - final MemoryAccessKind getResultMemoryAccess() { result = getOpcode().getWriteMemoryAccess() } + final MemoryAccessKind getResultMemoryAccess() { + result = this.getOpcode().getWriteMemoryAccess() + } /** * Holds if the memory access performed by this instruction's result will not always write to @@ -332,7 +339,7 @@ class Instruction extends Construction::TStageInstruction { * (for example, the global side effects of a function call). */ pragma[inline] - final predicate hasResultMayMemoryAccess() { getOpcode().hasMayWriteMemoryAccess() } + final predicate hasResultMayMemoryAccess() { this.getOpcode().hasMayWriteMemoryAccess() } /** * Gets the operand that holds the memory address to which this instruction stores its @@ -340,7 +347,7 @@ class Instruction extends Construction::TStageInstruction { * is `r1`. */ final AddressOperand getResultAddressOperand() { - getResultMemoryAccess().usesAddressOperand() and + this.getResultMemoryAccess().usesAddressOperand() and result.getUse() = this } @@ -349,7 +356,7 @@ class Instruction extends Construction::TStageInstruction { * result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()` * is the instruction that defines `r1`. */ - final Instruction getResultAddress() { result = getResultAddressOperand().getDef() } + final Instruction getResultAddress() { result = this.getResultAddressOperand().getDef() } /** * Holds if the result of this instruction is precisely modeled in SSA. Always @@ -368,7 +375,7 @@ class Instruction extends Construction::TStageInstruction { */ final predicate isResultModeled() { // Register results are always in SSA form. - not hasMemoryResult() or + not this.hasMemoryResult() or Construction::hasModeledMemoryResult(this) } @@ -412,7 +419,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct successors of this instruction. */ - final Instruction getASuccessor() { result = getSuccessor(_) } + final Instruction getASuccessor() { result = this.getSuccessor(_) } /** * Gets a predecessor of this instruction such that the predecessor reaches @@ -423,7 +430,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct predecessors of this instruction. */ - final Instruction getAPredecessor() { result = getPredecessor(_) } + final Instruction getAPredecessor() { result = this.getPredecessor(_) } } /** @@ -543,7 +550,7 @@ class IndexedInstruction extends Instruction { * at this instruction. This instruction has no predecessors. */ class EnterFunctionInstruction extends Instruction { - EnterFunctionInstruction() { getOpcode() instanceof Opcode::EnterFunction } + EnterFunctionInstruction() { this.getOpcode() instanceof Opcode::EnterFunction } } /** @@ -554,7 +561,7 @@ class EnterFunctionInstruction extends Instruction { * struct, or union, see `FieldAddressInstruction`. */ class VariableAddressInstruction extends VariableInstruction { - VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress } + VariableAddressInstruction() { this.getOpcode() instanceof Opcode::VariableAddress } } /** @@ -566,7 +573,7 @@ class VariableAddressInstruction extends VariableInstruction { * The result has an `IRFunctionAddress` type. */ class FunctionAddressInstruction extends FunctionInstruction { - FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress } + FunctionAddressInstruction() { this.getOpcode() instanceof Opcode::FunctionAddress } } /** @@ -577,7 +584,7 @@ class FunctionAddressInstruction extends FunctionInstruction { * initializes that parameter. */ class InitializeParameterInstruction extends VariableInstruction { - InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter } + InitializeParameterInstruction() { this.getOpcode() instanceof Opcode::InitializeParameter } /** * Gets the parameter initialized by this instruction. @@ -603,7 +610,7 @@ class InitializeParameterInstruction extends VariableInstruction { * initialized elsewhere, would not otherwise have a definition in this function. */ class InitializeNonLocalInstruction extends Instruction { - InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal } + InitializeNonLocalInstruction() { this.getOpcode() instanceof Opcode::InitializeNonLocal } } /** @@ -611,7 +618,7 @@ class InitializeNonLocalInstruction extends Instruction { * with the value of that memory on entry to the function. */ class InitializeIndirectionInstruction extends VariableInstruction { - InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + InitializeIndirectionInstruction() { this.getOpcode() instanceof Opcode::InitializeIndirection } /** * Gets the parameter initialized by this instruction. @@ -635,24 +642,24 @@ class InitializeIndirectionInstruction extends VariableInstruction { * An instruction that initializes the `this` pointer parameter of the enclosing function. */ class InitializeThisInstruction extends Instruction { - InitializeThisInstruction() { getOpcode() instanceof Opcode::InitializeThis } + InitializeThisInstruction() { this.getOpcode() instanceof Opcode::InitializeThis } } /** * An instruction that computes the address of a non-static field of an object. */ class FieldAddressInstruction extends FieldInstruction { - FieldAddressInstruction() { getOpcode() instanceof Opcode::FieldAddress } + FieldAddressInstruction() { this.getOpcode() instanceof Opcode::FieldAddress } /** * Gets the operand that provides the address of the object containing the field. */ - final UnaryOperand getObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the object containing the field. */ - final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() } + final Instruction getObjectAddress() { result = this.getObjectAddressOperand().getDef() } } /** @@ -661,17 +668,19 @@ class FieldAddressInstruction extends FieldInstruction { * This instruction is used for element access to C# arrays. */ class ElementsAddressInstruction extends UnaryInstruction { - ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress } + ElementsAddressInstruction() { this.getOpcode() instanceof Opcode::ElementsAddress } /** * Gets the operand that provides the address of the array object. */ - final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getArrayObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the array object. */ - final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() } + final Instruction getArrayObjectAddress() { + result = this.getArrayObjectAddressOperand().getDef() + } } /** @@ -685,7 +694,7 @@ class ElementsAddressInstruction extends UnaryInstruction { * taken may want to ignore any function that contains an `ErrorInstruction`. */ class ErrorInstruction extends Instruction { - ErrorInstruction() { getOpcode() instanceof Opcode::Error } + ErrorInstruction() { this.getOpcode() instanceof Opcode::Error } } /** @@ -695,7 +704,7 @@ class ErrorInstruction extends Instruction { * an initializer, or whose initializer only partially initializes the variable. */ class UninitializedInstruction extends VariableInstruction { - UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized } + UninitializedInstruction() { this.getOpcode() instanceof Opcode::Uninitialized } /** * Gets the variable that is uninitialized. @@ -710,7 +719,7 @@ class UninitializedInstruction extends VariableInstruction { * least one instruction, even when the AST has no semantic effect. */ class NoOpInstruction extends Instruction { - NoOpInstruction() { getOpcode() instanceof Opcode::NoOp } + NoOpInstruction() { this.getOpcode() instanceof Opcode::NoOp } } /** @@ -732,32 +741,32 @@ class NoOpInstruction extends Instruction { * `void`-returning function. */ class ReturnInstruction extends Instruction { - ReturnInstruction() { getOpcode() instanceof ReturnOpcode } + ReturnInstruction() { this.getOpcode() instanceof ReturnOpcode } } /** * An instruction that returns control to the caller of the function, without returning a value. */ class ReturnVoidInstruction extends ReturnInstruction { - ReturnVoidInstruction() { getOpcode() instanceof Opcode::ReturnVoid } + ReturnVoidInstruction() { this.getOpcode() instanceof Opcode::ReturnVoid } } /** * An instruction that returns control to the caller of the function, including a return value. */ class ReturnValueInstruction extends ReturnInstruction { - ReturnValueInstruction() { getOpcode() instanceof Opcode::ReturnValue } + ReturnValueInstruction() { this.getOpcode() instanceof Opcode::ReturnValue } /** * Gets the operand that provides the value being returned by the function. */ - final LoadOperand getReturnValueOperand() { result = getAnOperand() } + final LoadOperand getReturnValueOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value being returned by the function, if an * exact definition is available. */ - final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } + final Instruction getReturnValue() { result = this.getReturnValueOperand().getDef() } } /** @@ -770,28 +779,28 @@ class ReturnValueInstruction extends ReturnInstruction { * that the caller initialized the memory pointed to by the parameter before the call. */ class ReturnIndirectionInstruction extends VariableInstruction { - ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + ReturnIndirectionInstruction() { this.getOpcode() instanceof Opcode::ReturnIndirection } /** * Gets the operand that provides the value of the pointed-to memory. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the pointed-to memory, if an exact * definition is available. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** * Gets the operand that provides the address of the pointed-to memory. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the pointed-to memory. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } /** * Gets the parameter for which this instruction reads the final pointed-to value within the @@ -826,7 +835,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * - `StoreInstruction` - Copies a register operand to a memory result. */ class CopyInstruction extends Instruction { - CopyInstruction() { getOpcode() instanceof CopyOpcode } + CopyInstruction() { this.getOpcode() instanceof CopyOpcode } /** * Gets the operand that provides the input value of the copy. @@ -837,16 +846,16 @@ class CopyInstruction extends Instruction { * Gets the instruction whose result provides the input value of the copy, if an exact definition * is available. */ - final Instruction getSourceValue() { result = getSourceValueOperand().getDef() } + final Instruction getSourceValue() { result = this.getSourceValueOperand().getDef() } } /** * An instruction that returns a register result containing a copy of its register operand. */ class CopyValueInstruction extends CopyInstruction, UnaryInstruction { - CopyValueInstruction() { getOpcode() instanceof Opcode::CopyValue } + CopyValueInstruction() { this.getOpcode() instanceof Opcode::CopyValue } - final override UnaryOperand getSourceValueOperand() { result = getAnOperand() } + final override UnaryOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -863,47 +872,49 @@ private string getAddressOperandDescription(AddressOperand operand) { * An instruction that returns a register result containing a copy of its memory operand. */ class LoadInstruction extends CopyInstruction { - LoadInstruction() { getOpcode() instanceof Opcode::Load } + LoadInstruction() { this.getOpcode() instanceof Opcode::Load } final override string getImmediateString() { - result = getAddressOperandDescription(getSourceAddressOperand()) + result = getAddressOperandDescription(this.getSourceAddressOperand()) } /** * Gets the operand that provides the address of the value being loaded. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the value being loaded. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } - final override LoadOperand getSourceValueOperand() { result = getAnOperand() } + final override LoadOperand getSourceValueOperand() { result = this.getAnOperand() } } /** * An instruction that returns a memory result containing a copy of its register operand. */ class StoreInstruction extends CopyInstruction { - StoreInstruction() { getOpcode() instanceof Opcode::Store } + StoreInstruction() { this.getOpcode() instanceof Opcode::Store } final override string getImmediateString() { - result = getAddressOperandDescription(getDestinationAddressOperand()) + result = getAddressOperandDescription(this.getDestinationAddressOperand()) } /** * Gets the operand that provides the address of the location to which the value will be stored. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the location to which the value will * be stored, if an exact definition is available. */ - final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + final Instruction getDestinationAddress() { + result = this.getDestinationAddressOperand().getDef() + } - final override StoreValueOperand getSourceValueOperand() { result = getAnOperand() } + final override StoreValueOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -911,27 +922,27 @@ class StoreInstruction extends CopyInstruction { * operand. */ class ConditionalBranchInstruction extends Instruction { - ConditionalBranchInstruction() { getOpcode() instanceof Opcode::ConditionalBranch } + ConditionalBranchInstruction() { this.getOpcode() instanceof Opcode::ConditionalBranch } /** * Gets the operand that provides the Boolean condition controlling the branch. */ - final ConditionOperand getConditionOperand() { result = getAnOperand() } + final ConditionOperand getConditionOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the Boolean condition controlling the branch. */ - final Instruction getCondition() { result = getConditionOperand().getDef() } + final Instruction getCondition() { result = this.getConditionOperand().getDef() } /** * Gets the instruction to which control will flow if the condition is true. */ - final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) } + final Instruction getTrueSuccessor() { result = this.getSuccessor(EdgeKind::trueEdge()) } /** * Gets the instruction to which control will flow if the condition is false. */ - final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) } + final Instruction getFalseSuccessor() { result = this.getSuccessor(EdgeKind::falseEdge()) } } /** @@ -943,14 +954,14 @@ class ConditionalBranchInstruction extends Instruction { * successors. */ class ExitFunctionInstruction extends Instruction { - ExitFunctionInstruction() { getOpcode() instanceof Opcode::ExitFunction } + ExitFunctionInstruction() { this.getOpcode() instanceof Opcode::ExitFunction } } /** * An instruction whose result is a constant value. */ class ConstantInstruction extends ConstantValueInstruction { - ConstantInstruction() { getOpcode() instanceof Opcode::Constant } + ConstantInstruction() { this.getOpcode() instanceof Opcode::Constant } } /** @@ -959,7 +970,7 @@ class ConstantInstruction extends ConstantValueInstruction { class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { exists(IRType resultType | - resultType = getResultIRType() and + resultType = this.getResultIRType() and (resultType instanceof IRIntegerType or resultType instanceof IRBooleanType) ) } @@ -969,7 +980,7 @@ class IntegerConstantInstruction extends ConstantInstruction { * An instruction whose result is a constant value of floating-point type. */ class FloatConstantInstruction extends ConstantInstruction { - FloatConstantInstruction() { getResultIRType() instanceof IRFloatingPointType } + FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType } } /** @@ -978,7 +989,9 @@ class FloatConstantInstruction extends ConstantInstruction { class StringConstantInstruction extends VariableInstruction { override IRStringLiteral var; - final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } + final override string getImmediateString() { + result = Language::getStringLiteralText(this.getValue()) + } /** * Gets the string literal whose address is returned by this instruction. @@ -990,37 +1003,37 @@ class StringConstantInstruction extends VariableInstruction { * An instruction whose result is computed from two operands. */ class BinaryInstruction extends Instruction { - BinaryInstruction() { getOpcode() instanceof BinaryOpcode } + BinaryInstruction() { this.getOpcode() instanceof BinaryOpcode } /** * Gets the left operand of this binary instruction. */ - final LeftOperand getLeftOperand() { result = getAnOperand() } + final LeftOperand getLeftOperand() { result = this.getAnOperand() } /** * Gets the right operand of this binary instruction. */ - final RightOperand getRightOperand() { result = getAnOperand() } + final RightOperand getRightOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the left operand of this binary * instruction. */ - final Instruction getLeft() { result = getLeftOperand().getDef() } + final Instruction getLeft() { result = this.getLeftOperand().getDef() } /** * Gets the instruction whose result provides the value of the right operand of this binary * instruction. */ - final Instruction getRight() { result = getRightOperand().getDef() } + final Instruction getRight() { result = this.getRightOperand().getDef() } /** * Holds if this instruction's operands are `op1` and `op2`, in either order. */ final predicate hasOperands(Operand op1, Operand op2) { - op1 = getLeftOperand() and op2 = getRightOperand() + op1 = this.getLeftOperand() and op2 = this.getRightOperand() or - op1 = getRightOperand() and op2 = getLeftOperand() + op1 = this.getRightOperand() and op2 = this.getLeftOperand() } } @@ -1028,7 +1041,7 @@ class BinaryInstruction extends Instruction { * An instruction that computes the result of an arithmetic operation. */ class ArithmeticInstruction extends Instruction { - ArithmeticInstruction() { getOpcode() instanceof ArithmeticOpcode } + ArithmeticInstruction() { this.getOpcode() instanceof ArithmeticOpcode } } /** @@ -1050,7 +1063,7 @@ class UnaryArithmeticInstruction extends ArithmeticInstruction, UnaryInstruction * performed according to IEEE-754. */ class AddInstruction extends BinaryArithmeticInstruction { - AddInstruction() { getOpcode() instanceof Opcode::Add } + AddInstruction() { this.getOpcode() instanceof Opcode::Add } } /** @@ -1061,7 +1074,7 @@ class AddInstruction extends BinaryArithmeticInstruction { * according to IEEE-754. */ class SubInstruction extends BinaryArithmeticInstruction { - SubInstruction() { getOpcode() instanceof Opcode::Sub } + SubInstruction() { this.getOpcode() instanceof Opcode::Sub } } /** @@ -1072,7 +1085,7 @@ class SubInstruction extends BinaryArithmeticInstruction { * performed according to IEEE-754. */ class MulInstruction extends BinaryArithmeticInstruction { - MulInstruction() { getOpcode() instanceof Opcode::Mul } + MulInstruction() { this.getOpcode() instanceof Opcode::Mul } } /** @@ -1083,7 +1096,7 @@ class MulInstruction extends BinaryArithmeticInstruction { * to IEEE-754. */ class DivInstruction extends BinaryArithmeticInstruction { - DivInstruction() { getOpcode() instanceof Opcode::Div } + DivInstruction() { this.getOpcode() instanceof Opcode::Div } } /** @@ -1093,7 +1106,7 @@ class DivInstruction extends BinaryArithmeticInstruction { * division by zero or integer overflow is undefined. */ class RemInstruction extends BinaryArithmeticInstruction { - RemInstruction() { getOpcode() instanceof Opcode::Rem } + RemInstruction() { this.getOpcode() instanceof Opcode::Rem } } /** @@ -1104,14 +1117,14 @@ class RemInstruction extends BinaryArithmeticInstruction { * is performed according to IEEE-754. */ class NegateInstruction extends UnaryArithmeticInstruction { - NegateInstruction() { getOpcode() instanceof Opcode::Negate } + NegateInstruction() { this.getOpcode() instanceof Opcode::Negate } } /** * An instruction that computes the result of a bitwise operation. */ class BitwiseInstruction extends Instruction { - BitwiseInstruction() { getOpcode() instanceof BitwiseOpcode } + BitwiseInstruction() { this.getOpcode() instanceof BitwiseOpcode } } /** @@ -1130,7 +1143,7 @@ class UnaryBitwiseInstruction extends BitwiseInstruction, UnaryInstruction { } * Both operands must have the same integer type, which will also be the result type. */ class BitAndInstruction extends BinaryBitwiseInstruction { - BitAndInstruction() { getOpcode() instanceof Opcode::BitAnd } + BitAndInstruction() { this.getOpcode() instanceof Opcode::BitAnd } } /** @@ -1139,7 +1152,7 @@ class BitAndInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitOrInstruction extends BinaryBitwiseInstruction { - BitOrInstruction() { getOpcode() instanceof Opcode::BitOr } + BitOrInstruction() { this.getOpcode() instanceof Opcode::BitOr } } /** @@ -1148,7 +1161,7 @@ class BitOrInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitXorInstruction extends BinaryBitwiseInstruction { - BitXorInstruction() { getOpcode() instanceof Opcode::BitXor } + BitXorInstruction() { this.getOpcode() instanceof Opcode::BitXor } } /** @@ -1159,7 +1172,7 @@ class BitXorInstruction extends BinaryBitwiseInstruction { * rightmost bits are zero-filled. */ class ShiftLeftInstruction extends BinaryBitwiseInstruction { - ShiftLeftInstruction() { getOpcode() instanceof Opcode::ShiftLeft } + ShiftLeftInstruction() { this.getOpcode() instanceof Opcode::ShiftLeft } } /** @@ -1172,7 +1185,7 @@ class ShiftLeftInstruction extends BinaryBitwiseInstruction { * of the left operand. */ class ShiftRightInstruction extends BinaryBitwiseInstruction { - ShiftRightInstruction() { getOpcode() instanceof Opcode::ShiftRight } + ShiftRightInstruction() { this.getOpcode() instanceof Opcode::ShiftRight } } /** @@ -1183,7 +1196,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { int elementSize; PointerArithmeticInstruction() { - getOpcode() instanceof PointerArithmeticOpcode and + this.getOpcode() instanceof PointerArithmeticOpcode and elementSize = Raw::getInstructionElementSize(this) } @@ -1206,7 +1219,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { * An instruction that adds or subtracts an integer offset from a pointer. */ class PointerOffsetInstruction extends PointerArithmeticInstruction { - PointerOffsetInstruction() { getOpcode() instanceof PointerOffsetOpcode } + PointerOffsetInstruction() { this.getOpcode() instanceof PointerOffsetOpcode } } /** @@ -1217,7 +1230,7 @@ class PointerOffsetInstruction extends PointerArithmeticInstruction { * overflow is undefined. */ class PointerAddInstruction extends PointerOffsetInstruction { - PointerAddInstruction() { getOpcode() instanceof Opcode::PointerAdd } + PointerAddInstruction() { this.getOpcode() instanceof Opcode::PointerAdd } } /** @@ -1228,7 +1241,7 @@ class PointerAddInstruction extends PointerOffsetInstruction { * pointer underflow is undefined. */ class PointerSubInstruction extends PointerOffsetInstruction { - PointerSubInstruction() { getOpcode() instanceof Opcode::PointerSub } + PointerSubInstruction() { this.getOpcode() instanceof Opcode::PointerSub } } /** @@ -1241,31 +1254,31 @@ class PointerSubInstruction extends PointerOffsetInstruction { * undefined. */ class PointerDiffInstruction extends PointerArithmeticInstruction { - PointerDiffInstruction() { getOpcode() instanceof Opcode::PointerDiff } + PointerDiffInstruction() { this.getOpcode() instanceof Opcode::PointerDiff } } /** * An instruction whose result is computed from a single operand. */ class UnaryInstruction extends Instruction { - UnaryInstruction() { getOpcode() instanceof UnaryOpcode } + UnaryInstruction() { this.getOpcode() instanceof UnaryOpcode } /** * Gets the sole operand of this instruction. */ - final UnaryOperand getUnaryOperand() { result = getAnOperand() } + final UnaryOperand getUnaryOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the sole operand of this instruction. */ - final Instruction getUnary() { result = getUnaryOperand().getDef() } + final Instruction getUnary() { result = this.getUnaryOperand().getDef() } } /** * An instruction that converts the value of its operand to a value of a different type. */ class ConvertInstruction extends UnaryInstruction { - ConvertInstruction() { getOpcode() instanceof Opcode::Convert } + ConvertInstruction() { this.getOpcode() instanceof Opcode::Convert } } /** @@ -1279,7 +1292,7 @@ class ConvertInstruction extends UnaryInstruction { * `as` expression. */ class CheckedConvertOrNullInstruction extends UnaryInstruction { - CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull } + CheckedConvertOrNullInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrNull } } /** @@ -1293,7 +1306,7 @@ class CheckedConvertOrNullInstruction extends UnaryInstruction { * expression. */ class CheckedConvertOrThrowInstruction extends UnaryInstruction { - CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow } + CheckedConvertOrThrowInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrThrow } } /** @@ -1306,7 +1319,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction { * the most-derived object. */ class CompleteObjectAddressInstruction extends UnaryInstruction { - CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress } + CompleteObjectAddressInstruction() { this.getOpcode() instanceof Opcode::CompleteObjectAddress } } /** @@ -1351,7 +1364,7 @@ class InheritanceConversionInstruction extends UnaryInstruction { * An instruction that converts from the address of a derived class to the address of a base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } + ConvertToBaseInstruction() { this.getOpcode() instanceof ConvertToBaseOpcode } } /** @@ -1361,7 +1374,9 @@ class ConvertToBaseInstruction extends InheritanceConversionInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } + ConvertToNonVirtualBaseInstruction() { + this.getOpcode() instanceof Opcode::ConvertToNonVirtualBase + } } /** @@ -1371,7 +1386,7 @@ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } + ConvertToVirtualBaseInstruction() { this.getOpcode() instanceof Opcode::ConvertToVirtualBase } } /** @@ -1381,7 +1396,7 @@ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { - ConvertToDerivedInstruction() { getOpcode() instanceof Opcode::ConvertToDerived } + ConvertToDerivedInstruction() { this.getOpcode() instanceof Opcode::ConvertToDerived } } /** @@ -1390,7 +1405,7 @@ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { * The operand must have an integer type, which will also be the result type. */ class BitComplementInstruction extends UnaryBitwiseInstruction { - BitComplementInstruction() { getOpcode() instanceof Opcode::BitComplement } + BitComplementInstruction() { this.getOpcode() instanceof Opcode::BitComplement } } /** @@ -1399,14 +1414,14 @@ class BitComplementInstruction extends UnaryBitwiseInstruction { * The operand must have a Boolean type, which will also be the result type. */ class LogicalNotInstruction extends UnaryInstruction { - LogicalNotInstruction() { getOpcode() instanceof Opcode::LogicalNot } + LogicalNotInstruction() { this.getOpcode() instanceof Opcode::LogicalNot } } /** * An instruction that compares two numeric operands. */ class CompareInstruction extends BinaryInstruction { - CompareInstruction() { getOpcode() instanceof CompareOpcode } + CompareInstruction() { this.getOpcode() instanceof CompareOpcode } } /** @@ -1417,7 +1432,7 @@ class CompareInstruction extends BinaryInstruction { * unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareEQInstruction extends CompareInstruction { - CompareEQInstruction() { getOpcode() instanceof Opcode::CompareEQ } + CompareEQInstruction() { this.getOpcode() instanceof Opcode::CompareEQ } } /** @@ -1428,14 +1443,14 @@ class CompareEQInstruction extends CompareInstruction { * `left == right`. Floating-point comparison is performed according to IEEE-754. */ class CompareNEInstruction extends CompareInstruction { - CompareNEInstruction() { getOpcode() instanceof Opcode::CompareNE } + CompareNEInstruction() { this.getOpcode() instanceof Opcode::CompareNE } } /** * An instruction that does a relative comparison of two values, such as `<` or `>=`. */ class RelationalInstruction extends CompareInstruction { - RelationalInstruction() { getOpcode() instanceof RelationalOpcode } + RelationalInstruction() { this.getOpcode() instanceof RelationalOpcode } /** * Gets the operand on the "greater" (or "greater-or-equal") side @@ -1467,11 +1482,11 @@ class RelationalInstruction extends CompareInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLTInstruction extends RelationalInstruction { - CompareLTInstruction() { getOpcode() instanceof Opcode::CompareLT } + CompareLTInstruction() { this.getOpcode() instanceof Opcode::CompareLT } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { any() } } @@ -1484,11 +1499,11 @@ class CompareLTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGTInstruction extends RelationalInstruction { - CompareGTInstruction() { getOpcode() instanceof Opcode::CompareGT } + CompareGTInstruction() { this.getOpcode() instanceof Opcode::CompareGT } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { any() } } @@ -1502,11 +1517,11 @@ class CompareGTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLEInstruction extends RelationalInstruction { - CompareLEInstruction() { getOpcode() instanceof Opcode::CompareLE } + CompareLEInstruction() { this.getOpcode() instanceof Opcode::CompareLE } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { none() } } @@ -1520,11 +1535,11 @@ class CompareLEInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGEInstruction extends RelationalInstruction { - CompareGEInstruction() { getOpcode() instanceof Opcode::CompareGE } + CompareGEInstruction() { this.getOpcode() instanceof Opcode::CompareGE } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { none() } } @@ -1543,78 +1558,78 @@ class CompareGEInstruction extends RelationalInstruction { * of any case edge. */ class SwitchInstruction extends Instruction { - SwitchInstruction() { getOpcode() instanceof Opcode::Switch } + SwitchInstruction() { this.getOpcode() instanceof Opcode::Switch } /** Gets the operand that provides the integer value controlling the switch. */ - final ConditionOperand getExpressionOperand() { result = getAnOperand() } + final ConditionOperand getExpressionOperand() { result = this.getAnOperand() } /** Gets the instruction whose result provides the integer value controlling the switch. */ - final Instruction getExpression() { result = getExpressionOperand().getDef() } + final Instruction getExpression() { result = this.getExpressionOperand().getDef() } /** Gets the successor instructions along the case edges of the switch. */ - final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) } + final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = this.getSuccessor(edge)) } /** Gets the successor instruction along the default edge of the switch, if any. */ - final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) } + final Instruction getDefaultSuccessor() { result = this.getSuccessor(EdgeKind::defaultEdge()) } } /** * An instruction that calls a function. */ class CallInstruction extends Instruction { - CallInstruction() { getOpcode() instanceof Opcode::Call } + CallInstruction() { this.getOpcode() instanceof Opcode::Call } final override string getImmediateString() { - result = getStaticCallTarget().toString() + result = this.getStaticCallTarget().toString() or - not exists(getStaticCallTarget()) and result = "?" + not exists(this.getStaticCallTarget()) and result = "?" } /** * Gets the operand the specifies the target function of the call. */ - final CallTargetOperand getCallTargetOperand() { result = getAnOperand() } + final CallTargetOperand getCallTargetOperand() { result = this.getAnOperand() } /** * Gets the `Instruction` that computes the target function of the call. This is usually a * `FunctionAddress` instruction, but can also be an arbitrary instruction that produces a * function pointer. */ - final Instruction getCallTarget() { result = getCallTargetOperand().getDef() } + final Instruction getCallTarget() { result = this.getCallTargetOperand().getDef() } /** * Gets all of the argument operands of the call, including the `this` pointer, if any. */ - final ArgumentOperand getAnArgumentOperand() { result = getAnOperand() } + final ArgumentOperand getAnArgumentOperand() { result = this.getAnOperand() } /** * Gets the `Function` that the call targets, if this is statically known. */ final Language::Function getStaticCallTarget() { - result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() + result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() } /** * Gets all of the arguments of the call, including the `this` pointer, if any. */ - final Instruction getAnArgument() { result = getAnArgumentOperand().getDef() } + final Instruction getAnArgument() { result = this.getAnArgumentOperand().getDef() } /** * Gets the `this` pointer argument operand of the call, if any. */ - final ThisArgumentOperand getThisArgumentOperand() { result = getAnOperand() } + final ThisArgumentOperand getThisArgumentOperand() { result = this.getAnOperand() } /** * Gets the `this` pointer argument of the call, if any. */ - final Instruction getThisArgument() { result = getThisArgumentOperand().getDef() } + final Instruction getThisArgument() { result = this.getThisArgumentOperand().getDef() } /** * Gets the argument operand at the specified index. */ pragma[noinline] final PositionalArgumentOperand getPositionalArgumentOperand(int index) { - result = getAnOperand() and + result = this.getAnOperand() and result.getIndex() = index } @@ -1623,7 +1638,7 @@ class CallInstruction extends Instruction { */ pragma[noinline] final Instruction getPositionalArgument(int index) { - result = getPositionalArgumentOperand(index).getDef() + result = this.getPositionalArgumentOperand(index).getDef() } /** @@ -1631,16 +1646,16 @@ class CallInstruction extends Instruction { */ pragma[noinline] final ArgumentOperand getArgumentOperand(int index) { - index >= 0 and result = getPositionalArgumentOperand(index) + index >= 0 and result = this.getPositionalArgumentOperand(index) or - index = -1 and result = getThisArgumentOperand() + index = -1 and result = this.getThisArgumentOperand() } /** * Gets the argument at the specified index, or `this` if `index` is `-1`. */ pragma[noinline] - final Instruction getArgument(int index) { result = getArgumentOperand(index).getDef() } + final Instruction getArgument(int index) { result = this.getArgumentOperand(index).getDef() } /** * Gets the number of arguments of the call, including the `this` pointer, if any. @@ -1665,7 +1680,7 @@ class CallInstruction extends Instruction { * An instruction representing a side effect of a function call. */ class SideEffectInstruction extends Instruction { - SideEffectInstruction() { getOpcode() instanceof SideEffectOpcode } + SideEffectInstruction() { this.getOpcode() instanceof SideEffectOpcode } /** * Gets the instruction whose execution causes this side effect. @@ -1680,7 +1695,7 @@ class SideEffectInstruction extends Instruction { * accessed by that call. */ class CallSideEffectInstruction extends SideEffectInstruction { - CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect } + CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } } /** @@ -1691,7 +1706,7 @@ class CallSideEffectInstruction extends SideEffectInstruction { * call target cannot write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { - CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } + CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } } /** @@ -1699,33 +1714,33 @@ class CallReadSideEffectInstruction extends SideEffectInstruction { * specific parameter. */ class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + ReadSideEffectInstruction() { this.getOpcode() instanceof ReadSideEffectOpcode } /** Gets the operand for the value that will be read from this instruction, if known. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** Gets the value that will be read from this instruction, if known. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** Gets the operand for the address from which this instruction may read. */ - final AddressOperand getArgumentOperand() { result = getAnOperand() } + final AddressOperand getArgumentOperand() { result = this.getAnOperand() } /** Gets the address from which this instruction may read. */ - final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } + final Instruction getArgumentDef() { result = this.getArgumentOperand().getDef() } } /** * An instruction representing the read of an indirect parameter within a function call. */ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { - IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } + IndirectReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::IndirectReadSideEffect } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } + BufferReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::BufferReadSideEffect } } /** @@ -1733,18 +1748,18 @@ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferReadSideEffect + this.getOpcode() instanceof Opcode::SizedBufferReadSideEffect } /** * Gets the operand that holds the number of bytes read from the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes read from the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1752,17 +1767,17 @@ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } + WriteSideEffectInstruction() { this.getOpcode() instanceof WriteSideEffectOpcode } /** * Get the operand that holds the address of the memory to be written. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the memory to be written. */ - Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + Instruction getDestinationAddress() { result = this.getDestinationAddressOperand().getDef() } } /** @@ -1770,7 +1785,7 @@ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstructi */ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMustWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMustWriteSideEffect } } @@ -1780,7 +1795,7 @@ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction */ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { BufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::BufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::BufferMustWriteSideEffect } } @@ -1790,18 +1805,18 @@ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1812,7 +1827,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi */ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMayWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMayWriteSideEffect } } @@ -1822,7 +1837,9 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { * Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten. */ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { - BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect } + BufferMayWriteSideEffectInstruction() { + this.getOpcode() instanceof Opcode::BufferMayWriteSideEffect + } } /** @@ -1832,18 +1849,18 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1852,80 +1869,80 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio */ class InitializeDynamicAllocationInstruction extends SideEffectInstruction { InitializeDynamicAllocationInstruction() { - getOpcode() instanceof Opcode::InitializeDynamicAllocation + this.getOpcode() instanceof Opcode::InitializeDynamicAllocation } /** * Gets the operand that represents the address of the allocation this instruction is initializing. */ - final AddressOperand getAllocationAddressOperand() { result = getAnOperand() } + final AddressOperand getAllocationAddressOperand() { result = this.getAnOperand() } /** * Gets the address for the allocation this instruction is initializing. */ - final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() } + final Instruction getAllocationAddress() { result = this.getAllocationAddressOperand().getDef() } } /** * An instruction representing a GNU or MSVC inline assembly statement. */ class InlineAsmInstruction extends Instruction { - InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm } + InlineAsmInstruction() { this.getOpcode() instanceof Opcode::InlineAsm } } /** * An instruction that throws an exception. */ class ThrowInstruction extends Instruction { - ThrowInstruction() { getOpcode() instanceof ThrowOpcode } + ThrowInstruction() { this.getOpcode() instanceof ThrowOpcode } } /** * An instruction that throws a new exception. */ class ThrowValueInstruction extends ThrowInstruction { - ThrowValueInstruction() { getOpcode() instanceof Opcode::ThrowValue } + ThrowValueInstruction() { this.getOpcode() instanceof Opcode::ThrowValue } /** * Gets the address operand of the exception thrown by this instruction. */ - final AddressOperand getExceptionAddressOperand() { result = getAnOperand() } + final AddressOperand getExceptionAddressOperand() { result = this.getAnOperand() } /** * Gets the address of the exception thrown by this instruction. */ - final Instruction getExceptionAddress() { result = getExceptionAddressOperand().getDef() } + final Instruction getExceptionAddress() { result = this.getExceptionAddressOperand().getDef() } /** * Gets the operand for the exception thrown by this instruction. */ - final LoadOperand getExceptionOperand() { result = getAnOperand() } + final LoadOperand getExceptionOperand() { result = this.getAnOperand() } /** * Gets the exception thrown by this instruction. */ - final Instruction getException() { result = getExceptionOperand().getDef() } + final Instruction getException() { result = this.getExceptionOperand().getDef() } } /** * An instruction that re-throws the current exception. */ class ReThrowInstruction extends ThrowInstruction { - ReThrowInstruction() { getOpcode() instanceof Opcode::ReThrow } + ReThrowInstruction() { this.getOpcode() instanceof Opcode::ReThrow } } /** * An instruction that exits the current function by propagating an exception. */ class UnwindInstruction extends Instruction { - UnwindInstruction() { getOpcode() instanceof Opcode::Unwind } + UnwindInstruction() { this.getOpcode() instanceof Opcode::Unwind } } /** * An instruction that starts a `catch` handler. */ class CatchInstruction extends Instruction { - CatchInstruction() { getOpcode() instanceof CatchOpcode } + CatchInstruction() { this.getOpcode() instanceof CatchOpcode } } /** @@ -1935,7 +1952,7 @@ class CatchByTypeInstruction extends CatchInstruction { Language::LanguageType exceptionType; CatchByTypeInstruction() { - getOpcode() instanceof Opcode::CatchByType and + this.getOpcode() instanceof Opcode::CatchByType and exceptionType = Raw::getInstructionExceptionType(this) } @@ -1951,21 +1968,21 @@ class CatchByTypeInstruction extends CatchInstruction { * An instruction that catches any exception. */ class CatchAnyInstruction extends CatchInstruction { - CatchAnyInstruction() { getOpcode() instanceof Opcode::CatchAny } + CatchAnyInstruction() { this.getOpcode() instanceof Opcode::CatchAny } } /** * An instruction that initializes all escaped memory. */ class AliasedDefinitionInstruction extends Instruction { - AliasedDefinitionInstruction() { getOpcode() instanceof Opcode::AliasedDefinition } + AliasedDefinitionInstruction() { this.getOpcode() instanceof Opcode::AliasedDefinition } } /** * An instruction that consumes all escaped memory on exit from the function. */ class AliasedUseInstruction extends Instruction { - AliasedUseInstruction() { getOpcode() instanceof Opcode::AliasedUse } + AliasedUseInstruction() { this.getOpcode() instanceof Opcode::AliasedUse } } /** @@ -1979,7 +1996,7 @@ class AliasedUseInstruction extends Instruction { * runtime. */ class PhiInstruction extends Instruction { - PhiInstruction() { getOpcode() instanceof Opcode::Phi } + PhiInstruction() { this.getOpcode() instanceof Opcode::Phi } /** * Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block. @@ -2047,29 +2064,29 @@ class PhiInstruction extends Instruction { * https://link.springer.com/content/pdf/10.1007%2F3-540-61053-7_66.pdf. */ class ChiInstruction extends Instruction { - ChiInstruction() { getOpcode() instanceof Opcode::Chi } + ChiInstruction() { this.getOpcode() instanceof Opcode::Chi } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final ChiTotalOperand getTotalOperand() { result = getAnOperand() } + final ChiTotalOperand getTotalOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final Instruction getTotal() { result = getTotalOperand().getDef() } + final Instruction getTotal() { result = this.getTotalOperand().getDef() } /** * Gets the operand that represents the new value written by the memory write. */ - final ChiPartialOperand getPartialOperand() { result = getAnOperand() } + final ChiPartialOperand getPartialOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the new value written by the memory write. */ - final Instruction getPartial() { result = getPartialOperand().getDef() } + final Instruction getPartial() { result = this.getPartialOperand().getDef() } /** * Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand. @@ -2093,7 +2110,7 @@ class ChiInstruction extends Instruction { * or `Switch` instruction where that particular edge is infeasible. */ class UnreachedInstruction extends Instruction { - UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached } + UnreachedInstruction() { this.getOpcode() instanceof Opcode::Unreached } } /** @@ -2106,7 +2123,7 @@ class BuiltInOperationInstruction extends Instruction { Language::BuiltInOperation operation; BuiltInOperationInstruction() { - getOpcode() instanceof BuiltInOperationOpcode and + this.getOpcode() instanceof BuiltInOperationOpcode and operation = Raw::getInstructionBuiltInOperation(this) } @@ -2122,9 +2139,9 @@ class BuiltInOperationInstruction extends Instruction { * actual operation is specified by the `getBuiltInOperation()` predicate. */ class BuiltInInstruction extends BuiltInOperationInstruction { - BuiltInInstruction() { getOpcode() instanceof Opcode::BuiltIn } + BuiltInInstruction() { this.getOpcode() instanceof Opcode::BuiltIn } - final override string getImmediateString() { result = getBuiltInOperation().toString() } + final override string getImmediateString() { result = this.getBuiltInOperation().toString() } } /** @@ -2135,7 +2152,7 @@ class BuiltInInstruction extends BuiltInOperationInstruction { * to the `...` parameter. */ class VarArgsStartInstruction extends UnaryInstruction { - VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart } + VarArgsStartInstruction() { this.getOpcode() instanceof Opcode::VarArgsStart } } /** @@ -2145,7 +2162,7 @@ class VarArgsStartInstruction extends UnaryInstruction { * a result. */ class VarArgsEndInstruction extends UnaryInstruction { - VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd } + VarArgsEndInstruction() { this.getOpcode() instanceof Opcode::VarArgsEnd } } /** @@ -2155,7 +2172,7 @@ class VarArgsEndInstruction extends UnaryInstruction { * argument. */ class VarArgInstruction extends UnaryInstruction { - VarArgInstruction() { getOpcode() instanceof Opcode::VarArg } + VarArgInstruction() { this.getOpcode() instanceof Opcode::VarArg } } /** @@ -2166,7 +2183,7 @@ class VarArgInstruction extends UnaryInstruction { * argument of the `...` parameter. */ class NextVarArgInstruction extends UnaryInstruction { - NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg } + NextVarArgInstruction() { this.getOpcode() instanceof Opcode::NextVarArg } } /** @@ -2180,5 +2197,5 @@ class NextVarArgInstruction extends UnaryInstruction { * The result is the address of the newly allocated object. */ class NewObjInstruction extends Instruction { - NewObjInstruction() { getOpcode() instanceof Opcode::NewObj } + NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj } } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll index d7cf89ca9aa..85d217bd361 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll @@ -46,12 +46,12 @@ class Operand extends TStageOperand { /** * Gets the location of the source code for this operand. */ - final Language::Location getLocation() { result = getUse().getLocation() } + final Language::Location getLocation() { result = this.getUse().getLocation() } /** * Gets the function that contains this operand. */ - final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() } + final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() } /** * Gets the `Instruction` that consumes this operand. @@ -74,7 +74,7 @@ class Operand extends TStageOperand { */ final Instruction getDef() { result = this.getAnyDef() and - getDefinitionOverlap() instanceof MustExactlyOverlap + this.getDefinitionOverlap() instanceof MustExactlyOverlap } /** @@ -82,7 +82,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` that consumes this operand. */ - deprecated final Instruction getUseInstruction() { result = getUse() } + deprecated final Instruction getUseInstruction() { result = this.getUse() } /** * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this @@ -91,7 +91,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` whose result is the value of the operand. */ - deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() } + deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } /** * Gets the overlap relationship between the operand's definition and its use. @@ -101,7 +101,9 @@ class Operand extends TStageOperand { /** * Holds if the result of the definition instruction does not exactly overlap this use. */ - final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap } + final predicate isDefinitionInexact() { + not this.getDefinitionOverlap() instanceof MustExactlyOverlap + } /** * Gets a prefix to use when dumping the operand in an operand list. @@ -121,7 +123,7 @@ class Operand extends TStageOperand { * For example: `this:r3_5` */ final string getDumpString() { - result = getDumpLabel() + getInexactSpecifier() + getDefinitionId() + result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId() } /** @@ -129,9 +131,9 @@ class Operand extends TStageOperand { * definition is not modeled in SSA. */ private string getDefinitionId() { - result = getAnyDef().getResultId() + result = this.getAnyDef().getResultId() or - not exists(getAnyDef()) and result = "m?" + not exists(this.getAnyDef()) and result = "m?" } /** @@ -140,7 +142,7 @@ class Operand extends TStageOperand { * the empty string. */ private string getInexactSpecifier() { - if isDefinitionInexact() then result = "~" else result = "" + if this.isDefinitionInexact() then result = "~" else result = "" } /** @@ -155,7 +157,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() } + Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() } /** * Gets the language-neutral type of the value consumed by this operand. This is usually the same @@ -164,7 +166,7 @@ class Operand extends TStageOperand { * from the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final IRType getIRType() { result = getLanguageType().getIRType() } + final IRType getIRType() { result = this.getLanguageType().getIRType() } /** * Gets the type of the value consumed by this operand. This is usually the same as the @@ -173,7 +175,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final Language::Type getType() { getLanguageType().hasType(result, _) } + final Language::Type getType() { this.getLanguageType().hasType(result, _) } /** * Holds if the value consumed by this operand is a glvalue. If this @@ -182,13 +184,13 @@ class Operand extends TStageOperand { * not hold, the value of the operand represents a value whose type is * given by `getType()`. */ - final predicate isGLValue() { getLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getLanguageType().hasType(_, true) } /** * Gets the size of the value consumed by this operand, in bytes. If the operand does not have * a known constant size, this predicate does not hold. */ - final int getSize() { result = getLanguageType().getByteSize() } + final int getSize() { result = this.getLanguageType().getByteSize() } } /** @@ -205,7 +207,7 @@ class MemoryOperand extends Operand { /** * Gets the kind of memory access performed by the operand. */ - MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() } + MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() } /** * Holds if the memory access performed by this operand will not always read from every bit in the @@ -215,7 +217,7 @@ class MemoryOperand extends Operand { * conservative estimate of the memory that might actually be accessed at runtime (for example, * the global side effects of a function call). */ - predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() } + predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() } /** * Returns the operand that holds the memory address from which the current operand loads its @@ -223,8 +225,8 @@ class MemoryOperand extends Operand { * is `r1`. */ final AddressOperand getAddressOperand() { - getMemoryAccess().usesAddressOperand() and - result.getUse() = getUse() + this.getMemoryAccess().usesAddressOperand() and + result.getUse() = this.getUse() } } @@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe result = unique(Instruction defInstr | hasDefinition(defInstr, _)) } - final override Overlap getDefinitionOverlap() { hasDefinition(_, result) } + final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) } pragma[noinline] private predicate hasDefinition(Instruction defInstr, Overlap overlap) { @@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand { final override Overlap getDefinitionOverlap() { result = overlap } - final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() } - - final override string getDumpLabel() { - result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" + final override int getDumpSortOrder() { + result = 11 + this.getPredecessorBlock().getDisplayIndex() } - final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() } + final override string getDumpLabel() { + result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":" + } + + final override string getDumpId() { + result = this.getPredecessorBlock().getDisplayIndex().toString() + } /** * Gets the predecessor block from which this value comes. diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll index e0bf271dcc7..b0eb5ec98cb 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll @@ -36,7 +36,7 @@ module AliasModels { * Holds if this is the input value of the parameter with index `index`. * DEPRECATED: Use `isParameter(index)` instead. */ - deprecated final predicate isInParameter(ParameterIndex index) { isParameter(index) } + deprecated final predicate isInParameter(ParameterIndex index) { this.isParameter(index) } /** * Holds if this is the input value pointed to by a pointer parameter to a function, or the input @@ -63,7 +63,7 @@ module AliasModels { * DEPRECATED: Use `isParameterDeref(index)` instead. */ deprecated final predicate isInParameterPointer(ParameterIndex index) { - isParameterDeref(index) + this.isParameterDeref(index) } /** @@ -86,7 +86,7 @@ module AliasModels { * function. * DEPRECATED: Use `isQualifierObject()` instead. */ - deprecated final predicate isInQualifier() { isQualifierObject() } + deprecated final predicate isInQualifier() { this.isQualifierObject() } /** * Holds if this is the input value of the `this` pointer of an instance member function. @@ -184,7 +184,7 @@ module AliasModels { * DEPRECATED: Use `isParameterDeref(index)` instead. */ deprecated final predicate isOutParameterPointer(ParameterIndex index) { - isParameterDeref(index) + this.isParameterDeref(index) } /** @@ -207,7 +207,7 @@ module AliasModels { * function. * DEPRECATED: Use `isQualifierObject()` instead. */ - deprecated final predicate isOutQualifier() { isQualifierObject() } + deprecated final predicate isOutQualifier() { this.isQualifierObject() } /** * Holds if this is the value returned by a function. @@ -232,7 +232,7 @@ module AliasModels { * Holds if this is the value returned by a function. * DEPRECATED: Use `isReturnValue()` instead. */ - deprecated final predicate isOutReturnValue() { isReturnValue() } + deprecated final predicate isOutReturnValue() { this.isReturnValue() } /** * Holds if this is the output value pointed to by the return value of a function, if the function @@ -260,7 +260,7 @@ module AliasModels { * function returns a reference. * DEPRECATED: Use `isReturnValueDeref()` instead. */ - deprecated final predicate isOutReturnPointer() { isReturnValueDeref() } + deprecated final predicate isOutReturnPointer() { this.isReturnValueDeref() } /** * Holds if `i >= 0` and `isParameterDeref(i)` holds for this is the value, or diff --git a/csharp/ql/src/experimental/ir/internal/IRGuards.qll b/csharp/ql/src/experimental/ir/internal/IRGuards.qll index d01dcbed1e1..40780a3920e 100644 --- a/csharp/ql/src/experimental/ir/internal/IRGuards.qll +++ b/csharp/ql/src/experimental/ir/internal/IRGuards.qll @@ -147,7 +147,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { exists(boolean testIsTrue | - comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) + this.comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) ) } @@ -161,7 +161,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { exists(boolean testIsTrue | - comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) + this.comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) ) } } @@ -326,9 +326,9 @@ class IRGuardCondition extends Instruction { cached predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) { pred.getASuccessor() = succ and - controls(pred, testIsTrue) + this.controls(pred, testIsTrue) or - hasBranchEdge(succ, testIsTrue) and + this.hasBranchEdge(succ, testIsTrue) and branch.getCondition() = this and branch.getBlock() = pred } diff --git a/csharp/ql/test/library-tests/assignables/AssignableDefinition.ql b/csharp/ql/test/library-tests/assignables/AssignableDefinition.ql index 6f24ecaa0e9..ad5facdab45 100644 --- a/csharp/ql/test/library-tests/assignables/AssignableDefinition.ql +++ b/csharp/ql/test/library-tests/assignables/AssignableDefinition.ql @@ -6,14 +6,14 @@ newtype TTargetAccessOption = class TargetAccessOption extends TTargetAccessOption { string toString() { - result = som().toString() + result = this.som().toString() or - exists(non()) and result = "<none>" + exists(this.non()) and result = "<none>" } Location getLocation() { - result = som().getLocation() or - result = non().getLocation() + result = this.som().getLocation() or + result = this.non().getLocation() } private AssignableAccess som() { this = TTargetAccessSome(result) } @@ -31,14 +31,14 @@ newtype TSourceOption = class SourceOption extends TSourceOption { string toString() { - result = som().toString() + result = this.som().toString() or - exists(non()) and result = "<none>" + exists(this.non()) and result = "<none>" } Location getLocation() { - result = som().getLocation() or - result = non().getLocation() + result = this.som().getLocation() or + result = this.non().getLocation() } private Expr som() { this = TSourceSome(result) } diff --git a/csharp/ql/test/library-tests/cil/consistency/Handles.ql b/csharp/ql/test/library-tests/cil/consistency/Handles.ql index a64ea94eb98..e67e4b29416 100644 --- a/csharp/ql/test/library-tests/cil/consistency/Handles.ql +++ b/csharp/ql/test/library-tests/cil/consistency/Handles.ql @@ -5,7 +5,7 @@ import dotnet class MetadataEntity extends DotNet::NamedElement, @metadata_entity { int getHandle() { metadata_handle(this, _, result) } - predicate hasHandle() { exists(getHandle()) } + predicate hasHandle() { exists(this.getHandle()) } Assembly getAssembly() { metadata_handle(this, result, _) } } From 57cb3007598d082865da1079910c98a4c068c020 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Thu, 14 Oct 2021 11:34:22 +0200 Subject: [PATCH 277/361] C++/C#/Java/JavaScript/Python: Remove singleton set literals. --- .../cpp/models/implementations/Allocation.qll | 2 +- .../csharp/frameworks/EntityFramework.qll | 2 +- .../csharp/security/dataflow/XSSSinks.qll | 2 +- .../lib/semmle/code/java/frameworks/jOOQ.qll | 8 +------ .../code/java/security/InformationLeak.qll | 4 +--- .../library-tests/frameworks/stream/test.ql | 5 +---- java/ql/test/library-tests/optional/test.ql | 6 +---- .../security/CWE-079/semmle/tests/XSS.ql | 2 +- .../semmle/javascript/frameworks/Angular2.qll | 2 +- .../frameworks/ComposedFunctions.qll | 2 +- .../semmle/javascript/frameworks/MooTools.qll | 2 +- .../security/performance/ReDoSUtil.qll | 4 ++-- .../testUtilities/ConsistencyChecking.qll | 2 +- .../lib/semmle/python/frameworks/Aiohttp.qll | 2 +- .../semmle/python/frameworks/Cryptodome.qll | 22 +++++++++---------- .../lib/semmle/python/frameworks/Stdlib.qll | 2 +- .../lib/semmle/python/frameworks/Tornado.qll | 2 +- .../lib/semmle/python/frameworks/Werkzeug.qll | 2 +- .../ql/lib/semmle/python/frameworks/Yarl.qll | 2 +- .../python/security/performance/ReDoSUtil.qll | 4 ++-- .../test/experimental/meta/ConceptsTest.qll | 4 ++-- 21 files changed, 34 insertions(+), 49 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll index 25dae1c2fd1..b91eff2b3d9 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll @@ -56,7 +56,7 @@ private class MallocAllocationFunction extends AllocationFunction { ]) and sizeArg = 1 or - hasGlobalName(["HeapAlloc"]) and // HeapAlloc(heap, flags, size) + hasGlobalName("HeapAlloc") and // HeapAlloc(heap, flags, size) sizeArg = 2 or hasGlobalName([ diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll index 36882d3b12e..5f63d7ab268 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll @@ -239,7 +239,7 @@ module EntityFramework { private class SystemDataEntityDbSetSqlQuerySinkModelCsv extends SinkModelCsv { override predicate row(string row) { row = - ["System.Data.Entity;DbSet;false;SqlQuery;(System.String,System.Object[]);;Argument[0];sql"] + "System.Data.Entity;DbSet;false;SqlQuery;(System.String,System.Object[]);;Argument[0];sql" } } diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSSinks.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSSinks.qll index 4be005be4de..d6e25710c91 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSSinks.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSSinks.qll @@ -251,7 +251,7 @@ private class HttpResponseBaseSink extends Sink { */ private class StringContentSinkModelCsv extends SinkModelCsv { override predicate row(string row) { - row = ["System.Net.Http;StringContent;false;StringContent;;;Argument[0];xss"] + row = "System.Net.Http;StringContent;false;StringContent;;;Argument[0];xss" } } diff --git a/java/ql/lib/semmle/code/java/frameworks/jOOQ.qll b/java/ql/lib/semmle/code/java/frameworks/jOOQ.qll index c95c9f4c90f..8a6ee13ec57 100644 --- a/java/ql/lib/semmle/code/java/frameworks/jOOQ.qll +++ b/java/ql/lib/semmle/code/java/frameworks/jOOQ.qll @@ -24,11 +24,5 @@ predicate jOOQSqlMethod(Method m) { } private class SqlSinkCsv extends SinkModelCsv { - override predicate row(string row) { - row = - [ - //"package;type;overrides;name;signature;ext;spec;kind" - "org.jooq;PlainSQL;false;;;Annotated;Argument[0];sql" - ] - } + override predicate row(string row) { row = "org.jooq;PlainSQL;false;;;Annotated;Argument[0];sql" } } diff --git a/java/ql/lib/semmle/code/java/security/InformationLeak.qll b/java/ql/lib/semmle/code/java/security/InformationLeak.qll index f68ddd5b121..3ea674521a0 100644 --- a/java/ql/lib/semmle/code/java/security/InformationLeak.qll +++ b/java/ql/lib/semmle/code/java/security/InformationLeak.qll @@ -9,9 +9,7 @@ import semmle.code.java.security.XSS private class DefaultInformationLeakSinkModel extends SinkModelCsv { override predicate row(string row) { row = - [ - "javax.servlet.http;HttpServletResponse;false;sendError;(int,String);;Argument[1];information-leak" - ] + "javax.servlet.http;HttpServletResponse;false;sendError;(int,String);;Argument[1];information-leak" } } diff --git a/java/ql/test/library-tests/frameworks/stream/test.ql b/java/ql/test/library-tests/frameworks/stream/test.ql index ff94106f985..b9baef32869 100644 --- a/java/ql/test/library-tests/frameworks/stream/test.ql +++ b/java/ql/test/library-tests/frameworks/stream/test.ql @@ -4,9 +4,6 @@ import TestUtilities.InlineFlowTest class SummaryModelTest extends SummaryModelCsv { override predicate row(string row) { row = - [ - //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", - "generatedtest;Test;false;getElementSpliterator;(Spliterator);;Element of Argument[0];ReturnValue;value" - ] + "generatedtest;Test;false;getElementSpliterator;(Spliterator);;Element of Argument[0];ReturnValue;value" } } diff --git a/java/ql/test/library-tests/optional/test.ql b/java/ql/test/library-tests/optional/test.ql index 1edfda2487a..a5a61097dde 100644 --- a/java/ql/test/library-tests/optional/test.ql +++ b/java/ql/test/library-tests/optional/test.ql @@ -3,10 +3,6 @@ import TestUtilities.InlineFlowTest class SummaryModelTest extends SummaryModelCsv { override predicate row(string row) { - row = - [ - //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", - "generatedtest;Test;false;getStreamElement;;;Element of Argument[0];ReturnValue;value" - ] + row = "generatedtest;Test;false;getStreamElement;;;Element of Argument[0];ReturnValue;value" } } diff --git a/java/ql/test/query-tests/security/CWE-079/semmle/tests/XSS.ql b/java/ql/test/query-tests/security/CWE-079/semmle/tests/XSS.ql index 1cd3e59fc6b..6bfde865e85 100644 --- a/java/ql/test/query-tests/security/CWE-079/semmle/tests/XSS.ql +++ b/java/ql/test/query-tests/security/CWE-079/semmle/tests/XSS.ql @@ -20,7 +20,7 @@ class XSSConfig extends TaintTracking::Configuration { class XssTest extends InlineExpectationsTest { XssTest() { this = "XssTest" } - override string getARelevantTag() { result = ["xss"] } + override string getARelevantTag() { result = "xss" } override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "xss" and diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index 4041a7e7413..6a2e0132678 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -152,7 +152,7 @@ module Angular2 { /** A value that is about to be promoted to a trusted script value. */ private class AngularCodeInjectionSink extends CodeInjection::Sink { AngularCodeInjectionSink() { - this = domSanitizer().getAMethodCall(["bypassSecurityTrustScript"]).getArgument(0) + this = domSanitizer().getAMethodCall("bypassSecurityTrustScript").getArgument(0) } } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll b/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll index 6887758b064..1fd4e49db5a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll @@ -82,7 +82,7 @@ module FunctionCompositionCall { /** A call whose arguments are functions `f,g,h` which are composed into `f(g(h(...))` */ private class RightToLeft extends WithArrayOverloading { RightToLeft() { - this = DataFlow::moduleImport(["compose-function"]).getACall() + this = DataFlow::moduleImport("compose-function").getACall() or this = DataFlow::moduleMember(["redux", "ramda", "@reduxjs/toolkit", "recompose"], "compose") diff --git a/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll b/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll index 46a813d5c08..c1b4811e889 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll @@ -35,7 +35,7 @@ module MooTools { predicate interpretsNodeAsHtml(DataFlow::Node node) { exists(Element e | node = e.getAnElementPropertyValue("html") or - node = e.getAMethodCall(["appendHtml"]).getArgument(0) + node = e.getAMethodCall("appendHtml").getArgument(0) ) } } diff --git a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll index 12b7559615d..2cd324ed8f7 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll @@ -477,7 +477,7 @@ private module CharacterClasses { result = ["0", "9"] or cc.getValue() = "s" and - result = [" "] + result = " " or cc.getValue() = "w" and result = ["a", "Z", "_", "0", "9"] @@ -490,7 +490,7 @@ private module CharacterClasses { result = "9" or cc.getValue() = "s" and - result = [" "] + result = " " or cc.getValue() = "w" and result = "a" diff --git a/javascript/ql/test/testUtilities/ConsistencyChecking.qll b/javascript/ql/test/testUtilities/ConsistencyChecking.qll index cd02a998649..f63eb933ff6 100644 --- a/javascript/ql/test/testUtilities/ConsistencyChecking.qll +++ b/javascript/ql/test/testUtilities/ConsistencyChecking.qll @@ -62,7 +62,7 @@ private class AssertionComment extends LineComment { /** * Holds if a consistency issue is expected at this location. */ - predicate expectConsistencyError() { getText().matches(["%[INCONSISTENCY]%"]) } + predicate expectConsistencyError() { getText().matches("%[INCONSISTENCY]%") } } private DataFlow::Node getASink() { exists(DataFlow::Configuration cfg | cfg.hasFlow(_, result)) } diff --git a/python/ql/lib/semmle/python/frameworks/Aiohttp.qll b/python/ql/lib/semmle/python/frameworks/Aiohttp.qll index 46bcf3e554c..748f6c92d39 100644 --- a/python/ql/lib/semmle/python/frameworks/Aiohttp.qll +++ b/python/ql/lib/semmle/python/frameworks/Aiohttp.qll @@ -424,7 +424,7 @@ module AiohttpWebModel { override string getAttributeName() { none() } - override string getMethodName() { result in ["read_nowait"] } + override string getMethodName() { result = "read_nowait" } override string getAsyncMethodName() { result in [ diff --git a/python/ql/lib/semmle/python/frameworks/Cryptodome.qll b/python/ql/lib/semmle/python/frameworks/Cryptodome.qll index 4d108196148..54b5b9437a3 100644 --- a/python/ql/lib/semmle/python/frameworks/Cryptodome.qll +++ b/python/ql/lib/semmle/python/frameworks/Cryptodome.qll @@ -116,7 +116,7 @@ private module CryptodomeModel { ] and this = API::moduleImport(["Crypto", "Cryptodome"]) - .getMember(["Cipher"]) + .getMember("Cipher") .getMember(cipherName) .getMember("new") .getReturn() @@ -135,21 +135,21 @@ private module CryptodomeModel { or // for the following methods, method signatures can be found in // https://pycryptodome.readthedocs.io/en/latest/src/cipher/modern.html - methodName in ["update"] and + methodName = "update" and result in [this.getArg(0), this.getArgByName("data")] or // although `mac_tag` is used as the parameter name in the spec above, some implementations use `received_mac_tag`, for an example, see // https://github.com/Legrandin/pycryptodome/blob/5dace638b70ac35bb5d9b565f3e75f7869c9d851/lib/Crypto/Cipher/ChaCha20_Poly1305.py#L207 - methodName in ["verify"] and + methodName = "verify" and result in [this.getArg(0), this.getArgByName(["mac_tag", "received_mac_tag"])] or - methodName in ["hexverify"] and + methodName = "hexverify" and result in [this.getArg(0), this.getArgByName("mac_tag_hex")] or - methodName in ["encrypt_and_digest"] and + methodName = "encrypt_and_digest" and result in [this.getArg(0), this.getArgByName("plaintext")] or - methodName in ["decrypt_and_verify"] and + methodName = "decrypt_and_verify" and result in [ this.getArg(0), this.getArgByName("ciphertext"), this.getArg(1), this.getArgByName("mac_tag") @@ -169,7 +169,7 @@ private module CryptodomeModel { methodName in ["sign", "verify"] and this = API::moduleImport(["Crypto", "Cryptodome"]) - .getMember(["Signature"]) + .getMember("Signature") .getMember(signatureName) .getMember("new") .getReturn() @@ -185,11 +185,11 @@ private module CryptodomeModel { methodName = "sign" and result in [this.getArg(0), this.getArgByName("msg_hash")] // Cryptodome.Hash instance or - methodName in ["verify"] and + methodName = "verify" and ( - result in [this.getArg(0), this.getArgByName(["msg_hash"])] // Cryptodome.Hash instance + result in [this.getArg(0), this.getArgByName("msg_hash")] // Cryptodome.Hash instance or - result in [this.getArg(1), this.getArgByName(["signature"])] + result in [this.getArg(1), this.getArgByName("signature")] ) } } @@ -204,7 +204,7 @@ private module CryptodomeModel { CryptodomeGenericHashOperation() { exists(API::Node hashModule | hashModule = - API::moduleImport(["Crypto", "Cryptodome"]).getMember(["Hash"]).getMember(hashName) + API::moduleImport(["Crypto", "Cryptodome"]).getMember("Hash").getMember(hashName) | this = hashModule.getMember("new").getACall() or diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 86c2f0ff557..118c71ecad1 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1277,7 +1277,7 @@ private module StdlibPrivate { /** * Gets a name of an attribute of a `pathlib.Path` object that is also a `pathlib.Path` object. */ - private string pathlibPathAttribute() { result in ["parent"] } + private string pathlibPathAttribute() { result = "parent" } /** * Gets a name of a method of a `pathlib.Path` object that returns a `pathlib.Path` object. diff --git a/python/ql/lib/semmle/python/frameworks/Tornado.qll b/python/ql/lib/semmle/python/frameworks/Tornado.qll index ba4898facc8..91ae3ac2575 100644 --- a/python/ql/lib/semmle/python/frameworks/Tornado.qll +++ b/python/ql/lib/semmle/python/frameworks/Tornado.qll @@ -318,7 +318,7 @@ private module Tornado { ] } - override string getMethodName() { result in ["full_url"] } + override string getMethodName() { result = "full_url" } override string getAsyncMethodName() { none() } } diff --git a/python/ql/lib/semmle/python/frameworks/Werkzeug.qll b/python/ql/lib/semmle/python/frameworks/Werkzeug.qll index 039481f8522..e9e3f257871 100644 --- a/python/ql/lib/semmle/python/frameworks/Werkzeug.qll +++ b/python/ql/lib/semmle/python/frameworks/Werkzeug.qll @@ -58,7 +58,7 @@ module Werkzeug { override string getAttributeName() { none() } - override string getMethodName() { result in ["getlist"] } + override string getMethodName() { result = "getlist" } override string getAsyncMethodName() { none() } } diff --git a/python/ql/lib/semmle/python/frameworks/Yarl.qll b/python/ql/lib/semmle/python/frameworks/Yarl.qll index 00b0911471b..5ea78c1ac8e 100644 --- a/python/ql/lib/semmle/python/frameworks/Yarl.qll +++ b/python/ql/lib/semmle/python/frameworks/Yarl.qll @@ -68,7 +68,7 @@ module Yarl { ] } - override string getMethodName() { result in ["human_repr"] } + override string getMethodName() { result = "human_repr" } override string getAsyncMethodName() { none() } } diff --git a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll index 12b7559615d..2cd324ed8f7 100644 --- a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll +++ b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll @@ -477,7 +477,7 @@ private module CharacterClasses { result = ["0", "9"] or cc.getValue() = "s" and - result = [" "] + result = " " or cc.getValue() = "w" and result = ["a", "Z", "_", "0", "9"] @@ -490,7 +490,7 @@ private module CharacterClasses { result = "9" or cc.getValue() = "s" and - result = [" "] + result = " " or cc.getValue() = "w" and result = "a" diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index de53f053eb9..3ba52ddabde 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -96,7 +96,7 @@ class EncodingTest extends InlineExpectationsTest { class LoggingTest extends InlineExpectationsTest { LoggingTest() { this = "LoggingTest" } - override string getARelevantTag() { result in ["loggingInput"] } + override string getARelevantTag() { result = "loggingInput" } override predicate hasActualResult(Location location, string element, string tag, string value) { exists(location.getFile().getRelativePath()) and @@ -181,7 +181,7 @@ class EscapingTest extends InlineExpectationsTest { class HttpServerRouteSetupTest extends InlineExpectationsTest { HttpServerRouteSetupTest() { this = "HttpServerRouteSetupTest" } - override string getARelevantTag() { result in ["routeSetup"] } + override string getARelevantTag() { result = "routeSetup" } override predicate hasActualResult(Location location, string element, string tag, string value) { exists(location.getFile().getRelativePath()) and From f5420333e25e7d2ad5dc1f4b411311a066dbaa10 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 14 Oct 2021 11:49:02 +0200 Subject: [PATCH 278/361] Sync shared files --- cpp/ql/lib/semmle/code/cpp/XML.qll | 12 +- .../dataflow/internal/DataFlowImplCommon.qll | 4 +- .../tainttracking1/TaintTrackingImpl.qll | 12 +- .../tainttracking2/TaintTrackingImpl.qll | 12 +- .../dataflow/internal/DataFlowImplCommon.qll | 4 +- .../tainttracking1/TaintTrackingImpl.qll | 12 +- .../tainttracking2/TaintTrackingImpl.qll | 12 +- .../tainttracking3/TaintTrackingImpl.qll | 12 +- .../ir/implementation/aliased_ssa/IRBlock.qll | 30 +- .../aliased_ssa/Instruction.qll | 451 +++++++++--------- .../ir/implementation/aliased_ssa/Operand.qll | 56 ++- .../cpp/ir/implementation/raw/IRBlock.qll | 30 +- .../cpp/ir/implementation/raw/Instruction.qll | 451 +++++++++--------- .../cpp/ir/implementation/raw/Operand.qll | 56 ++- .../implementation/unaliased_ssa/IRBlock.qll | 30 +- .../unaliased_ssa/Instruction.qll | 451 +++++++++--------- .../implementation/unaliased_ssa/Operand.qll | 56 ++- .../csharp/dataflow/internal/DataFlowImpl.qll | 16 +- .../dataflow/internal/DataFlowImpl2.qll | 16 +- .../dataflow/internal/DataFlowImpl3.qll | 16 +- .../dataflow/internal/DataFlowImpl4.qll | 16 +- .../dataflow/internal/DataFlowImpl5.qll | 16 +- .../dataflow/internal/DataFlowImplCommon.qll | 4 +- .../rangeanalysis/SsaReadPositionCommon.qll | 6 +- .../tainttracking1/TaintTrackingImpl.qll | 12 +- .../tainttracking2/TaintTrackingImpl.qll | 12 +- java/ql/lib/semmle/code/xml/XML.qll | 12 +- javascript/ql/lib/semmle/javascript/XML.qll | 12 +- .../new/internal/DataFlowImplCommon.qll | 4 +- .../tainttracking1/TaintTrackingImpl.qll | 12 +- .../tainttracking2/TaintTrackingImpl.qll | 12 +- .../tainttracking3/TaintTrackingImpl.qll | 12 +- .../tainttracking4/TaintTrackingImpl.qll | 12 +- python/ql/lib/semmle/python/xml/XML.qll | 12 +- 34 files changed, 990 insertions(+), 903 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/XML.qll b/cpp/ql/lib/semmle/code/cpp/XML.qll index 4c762f4bf65..76f3b3cb022 100755 --- a/cpp/ql/lib/semmle/code/cpp/XML.qll +++ b/cpp/ql/lib/semmle/code/cpp/XML.qll @@ -108,7 +108,7 @@ class XMLParent extends @xmlparent { } /** Gets the text value contained in this XML parent. */ - string getTextValue() { result = allCharactersString() } + string getTextValue() { result = this.allCharactersString() } /** Gets a printable representation of this XML parent. */ string toString() { result = this.getName() } @@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File { XMLFile() { xmlEncoding(this, _) } /** Gets a printable representation of this XML file. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } /** Gets the name of this XML file. */ override string getName() { result = File.super.getAbsolutePath() } @@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File { * * Gets the path of this XML file. */ - deprecated string getPath() { result = getAbsolutePath() } + deprecated string getPath() { result = this.getAbsolutePath() } /** * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. * * Gets the path of the folder that contains this XML file. */ - deprecated string getFolder() { result = getParentContainer().getAbsolutePath() } + deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() } /** Gets the encoding of this XML file. */ string getEncoding() { xmlEncoding(this, result) } @@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd { */ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { /** Holds if this XML element has the given `name`. */ - predicate hasName(string name) { name = getName() } + predicate hasName(string name) { name = this.getName() } /** Gets the name of this XML element. */ override string getName() { xmlElements(this, result, _, _, _) } @@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } /** Gets a printable representation of this XML element. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } } /** 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 f43a550af57..494780d2e1b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -937,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { } override predicate relevantFor(DataFlowCallable callable) { - recordDataFlowCallSite(getCall(), callable) + recordDataFlowCallSite(this.getCall(), callable) } override predicate matchesCall(DataFlowCall call) { call = this.getCall() } @@ -1257,7 +1257,7 @@ abstract class AccessPathFront extends TAccessPathFront { TypedContent getHead() { this = TFrontHead(result) } - predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) } + predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } 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 f43a550af57..494780d2e1b 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 @@ -937,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { } override predicate relevantFor(DataFlowCallable callable) { - recordDataFlowCallSite(getCall(), callable) + recordDataFlowCallSite(this.getCall(), callable) } override predicate matchesCall(DataFlowCall call) { call = this.getCall() } @@ -1257,7 +1257,7 @@ abstract class AccessPathFront extends TAccessPathFront { TypedContent getHead() { this = TFrontHead(result) } - predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) } + predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll index 4b86f9a7cec..bb8630a5e0c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll @@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock { final string toString() { result = getFirstInstruction(this).toString() } /** Gets the source location of the first non-`Phi` instruction in this block. */ - final Language::Location getLocation() { result = getFirstInstruction().getLocation() } + final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() } /** * INTERNAL: Do not use. @@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock { ) and this = rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = getEnclosingFunction() and + funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and // Ensure that the block containing `EnterFunction` always comes first. if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction @@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock { * Get the `Phi` instructions that appear at the start of this block. */ final PhiInstruction getAPhiInstruction() { - Construction::getPhiInstructionBlockStart(result) = getFirstInstruction() + Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction() } /** * Gets an instruction in this block. This includes `Phi` instructions. */ final Instruction getAnInstruction() { - result = getInstruction(_) or - result = getAPhiInstruction() + result = this.getInstruction(_) or + result = this.getAPhiInstruction() } /** @@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock { /** * Gets the last instruction in this block. */ - final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) } + final Instruction getLastInstruction() { + result = this.getInstruction(this.getInstructionCount() - 1) + } /** * Gets the number of non-`Phi` instructions in this block. @@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase { * Block `A` dominates block `B` if any control flow path from the entry block of the function to * block `B` must pass through block `A`. A block always dominates itself. */ - final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block } + final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block } /** * Gets a block on the dominance frontier of this block. @@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock dominanceFrontier() { - dominates(result.getAPredecessor()) and - not strictlyDominates(result) + this.dominates(result.getAPredecessor()) and + not this.strictlyDominates(result) } /** @@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase { * Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the * function must pass through block `A`. A block always post-dominates itself. */ - final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block } + final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block } /** * Gets a block on the post-dominance frontier of this block. @@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock postPominanceFrontier() { - postDominates(result.getASuccessor()) and - not strictlyPostDominates(result) + this.postDominates(result.getASuccessor()) and + not this.strictlyPostDominates(result) } /** * Holds if this block is reachable from the entry block of its function. */ final predicate isReachableFromFunctionEntry() { - this = getEnclosingIRFunction().getEntryBlock() or - getAPredecessor().isReachableFromFunctionEntry() + this = this.getEnclosingIRFunction().getEntryBlock() or + this.getAPredecessor().isReachableFromFunctionEntry() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 6f471d8a7e8..88a973fc5a8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction { } /** Gets a textual representation of this element. */ - final string toString() { result = getOpcode().toString() + ": " + getAST().toString() } + final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() } /** * Gets a string showing the result, opcode, and operands of the instruction, equivalent to what @@ -50,7 +50,8 @@ class Instruction extends Construction::TStageInstruction { * `mu0_28(int) = Store r0_26, r0_27` */ final string getDumpString() { - result = getResultString() + " = " + getOperationString() + " " + getOperandsString() + result = + this.getResultString() + " = " + this.getOperationString() + " " + this.getOperandsString() } private predicate shouldGenerateDumpStrings() { @@ -66,10 +67,13 @@ class Instruction extends Construction::TStageInstruction { * VariableAddress[x] */ final string getOperationString() { - shouldGenerateDumpStrings() and - if exists(getImmediateString()) - then result = getOperationPrefix() + getOpcode().toString() + "[" + getImmediateString() + "]" - else result = getOperationPrefix() + getOpcode().toString() + this.shouldGenerateDumpStrings() and + if exists(this.getImmediateString()) + then + result = + this.getOperationPrefix() + this.getOpcode().toString() + "[" + this.getImmediateString() + + "]" + else result = this.getOperationPrefix() + this.getOpcode().toString() } /** @@ -78,17 +82,17 @@ class Instruction extends Construction::TStageInstruction { string getImmediateString() { none() } private string getOperationPrefix() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and if this instanceof SideEffectInstruction then result = "^" else result = "" } private string getResultPrefix() { - shouldGenerateDumpStrings() and - if getResultIRType() instanceof IRVoidType + this.shouldGenerateDumpStrings() and + if this.getResultIRType() instanceof IRVoidType then result = "v" else - if hasMemoryResult() - then if isResultModeled() then result = "m" else result = "mu" + if this.hasMemoryResult() + then if this.isResultModeled() then result = "m" else result = "mu" else result = "r" } @@ -97,7 +101,7 @@ class Instruction extends Construction::TStageInstruction { * used by debugging and printing code only. */ int getDisplayIndexInBlock() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and exists(IRBlock block | this = block.getInstruction(result) or @@ -111,12 +115,12 @@ class Instruction extends Construction::TStageInstruction { } private int getLineRank() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and this = rank[result](Instruction instr | instr = - getAnInstructionAtLine(getEnclosingIRFunction(), getLocation().getFile(), - getLocation().getStartLine()) + getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), + this.getLocation().getStartLine()) | instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() ) @@ -130,8 +134,9 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1` */ string getResultId() { - shouldGenerateDumpStrings() and - result = getResultPrefix() + getAST().getLocation().getStartLine() + "_" + getLineRank() + this.shouldGenerateDumpStrings() and + result = + this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank() } /** @@ -142,8 +147,8 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1(int*)` */ final string getResultString() { - shouldGenerateDumpStrings() and - result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")" + this.shouldGenerateDumpStrings() and + result = this.getResultId() + "(" + this.getResultLanguageType().getDumpString() + ")" } /** @@ -153,10 +158,10 @@ class Instruction extends Construction::TStageInstruction { * Example: `func:r3_4, this:r3_5` */ string getOperandsString() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and result = concat(Operand operand | - operand = getAnOperand() + operand = this.getAnOperand() | operand.getDumpString(), ", " order by operand.getDumpSortOrder() ) @@ -190,7 +195,7 @@ class Instruction extends Construction::TStageInstruction { * Gets the function that contains this instruction. */ final Language::Function getEnclosingFunction() { - result = getEnclosingIRFunction().getFunction() + result = this.getEnclosingIRFunction().getFunction() } /** @@ -208,7 +213,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the location of the source code for this instruction. */ - final Language::Location getLocation() { result = getAST().getLocation() } + final Language::Location getLocation() { result = this.getAST().getLocation() } /** * Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a @@ -243,7 +248,7 @@ class Instruction extends Construction::TStageInstruction { * a result, its result type will be `IRVoidType`. */ cached - final IRType getResultIRType() { result = getResultLanguageType().getIRType() } + final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() } /** * Gets the type of the result produced by this instruction. If the @@ -254,7 +259,7 @@ class Instruction extends Construction::TStageInstruction { */ final Language::Type getResultType() { exists(Language::LanguageType resultType | - resultType = getResultLanguageType() and + resultType = this.getResultLanguageType() and ( resultType.hasUnspecifiedType(result, _) or @@ -283,7 +288,7 @@ class Instruction extends Construction::TStageInstruction { * result of the `Load` instruction is a prvalue of type `int`, representing * the integer value loaded from variable `x`. */ - final predicate isGLValue() { getResultLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getResultLanguageType().hasType(_, true) } /** * Gets the size of the result produced by this instruction, in bytes. If the @@ -292,7 +297,7 @@ class Instruction extends Construction::TStageInstruction { * If `this.isGLValue()` holds for this instruction, the value of * `getResultSize()` will always be the size of a pointer. */ - final int getResultSize() { result = getResultLanguageType().getByteSize() } + final int getResultSize() { result = this.getResultLanguageType().getByteSize() } /** * Gets the opcode that specifies the operation performed by this instruction. @@ -314,14 +319,16 @@ class Instruction extends Construction::TStageInstruction { /** * Holds if this instruction produces a memory result. */ - final predicate hasMemoryResult() { exists(getResultMemoryAccess()) } + final predicate hasMemoryResult() { exists(this.getResultMemoryAccess()) } /** * Gets the kind of memory access performed by this instruction's result. * Holds only for instructions with a memory result. */ pragma[inline] - final MemoryAccessKind getResultMemoryAccess() { result = getOpcode().getWriteMemoryAccess() } + final MemoryAccessKind getResultMemoryAccess() { + result = this.getOpcode().getWriteMemoryAccess() + } /** * Holds if the memory access performed by this instruction's result will not always write to @@ -332,7 +339,7 @@ class Instruction extends Construction::TStageInstruction { * (for example, the global side effects of a function call). */ pragma[inline] - final predicate hasResultMayMemoryAccess() { getOpcode().hasMayWriteMemoryAccess() } + final predicate hasResultMayMemoryAccess() { this.getOpcode().hasMayWriteMemoryAccess() } /** * Gets the operand that holds the memory address to which this instruction stores its @@ -340,7 +347,7 @@ class Instruction extends Construction::TStageInstruction { * is `r1`. */ final AddressOperand getResultAddressOperand() { - getResultMemoryAccess().usesAddressOperand() and + this.getResultMemoryAccess().usesAddressOperand() and result.getUse() = this } @@ -349,7 +356,7 @@ class Instruction extends Construction::TStageInstruction { * result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()` * is the instruction that defines `r1`. */ - final Instruction getResultAddress() { result = getResultAddressOperand().getDef() } + final Instruction getResultAddress() { result = this.getResultAddressOperand().getDef() } /** * Holds if the result of this instruction is precisely modeled in SSA. Always @@ -368,7 +375,7 @@ class Instruction extends Construction::TStageInstruction { */ final predicate isResultModeled() { // Register results are always in SSA form. - not hasMemoryResult() or + not this.hasMemoryResult() or Construction::hasModeledMemoryResult(this) } @@ -412,7 +419,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct successors of this instruction. */ - final Instruction getASuccessor() { result = getSuccessor(_) } + final Instruction getASuccessor() { result = this.getSuccessor(_) } /** * Gets a predecessor of this instruction such that the predecessor reaches @@ -423,7 +430,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct predecessors of this instruction. */ - final Instruction getAPredecessor() { result = getPredecessor(_) } + final Instruction getAPredecessor() { result = this.getPredecessor(_) } } /** @@ -543,7 +550,7 @@ class IndexedInstruction extends Instruction { * at this instruction. This instruction has no predecessors. */ class EnterFunctionInstruction extends Instruction { - EnterFunctionInstruction() { getOpcode() instanceof Opcode::EnterFunction } + EnterFunctionInstruction() { this.getOpcode() instanceof Opcode::EnterFunction } } /** @@ -554,7 +561,7 @@ class EnterFunctionInstruction extends Instruction { * struct, or union, see `FieldAddressInstruction`. */ class VariableAddressInstruction extends VariableInstruction { - VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress } + VariableAddressInstruction() { this.getOpcode() instanceof Opcode::VariableAddress } } /** @@ -566,7 +573,7 @@ class VariableAddressInstruction extends VariableInstruction { * The result has an `IRFunctionAddress` type. */ class FunctionAddressInstruction extends FunctionInstruction { - FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress } + FunctionAddressInstruction() { this.getOpcode() instanceof Opcode::FunctionAddress } } /** @@ -577,7 +584,7 @@ class FunctionAddressInstruction extends FunctionInstruction { * initializes that parameter. */ class InitializeParameterInstruction extends VariableInstruction { - InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter } + InitializeParameterInstruction() { this.getOpcode() instanceof Opcode::InitializeParameter } /** * Gets the parameter initialized by this instruction. @@ -603,7 +610,7 @@ class InitializeParameterInstruction extends VariableInstruction { * initialized elsewhere, would not otherwise have a definition in this function. */ class InitializeNonLocalInstruction extends Instruction { - InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal } + InitializeNonLocalInstruction() { this.getOpcode() instanceof Opcode::InitializeNonLocal } } /** @@ -611,7 +618,7 @@ class InitializeNonLocalInstruction extends Instruction { * with the value of that memory on entry to the function. */ class InitializeIndirectionInstruction extends VariableInstruction { - InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + InitializeIndirectionInstruction() { this.getOpcode() instanceof Opcode::InitializeIndirection } /** * Gets the parameter initialized by this instruction. @@ -635,24 +642,24 @@ class InitializeIndirectionInstruction extends VariableInstruction { * An instruction that initializes the `this` pointer parameter of the enclosing function. */ class InitializeThisInstruction extends Instruction { - InitializeThisInstruction() { getOpcode() instanceof Opcode::InitializeThis } + InitializeThisInstruction() { this.getOpcode() instanceof Opcode::InitializeThis } } /** * An instruction that computes the address of a non-static field of an object. */ class FieldAddressInstruction extends FieldInstruction { - FieldAddressInstruction() { getOpcode() instanceof Opcode::FieldAddress } + FieldAddressInstruction() { this.getOpcode() instanceof Opcode::FieldAddress } /** * Gets the operand that provides the address of the object containing the field. */ - final UnaryOperand getObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the object containing the field. */ - final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() } + final Instruction getObjectAddress() { result = this.getObjectAddressOperand().getDef() } } /** @@ -661,17 +668,19 @@ class FieldAddressInstruction extends FieldInstruction { * This instruction is used for element access to C# arrays. */ class ElementsAddressInstruction extends UnaryInstruction { - ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress } + ElementsAddressInstruction() { this.getOpcode() instanceof Opcode::ElementsAddress } /** * Gets the operand that provides the address of the array object. */ - final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getArrayObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the array object. */ - final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() } + final Instruction getArrayObjectAddress() { + result = this.getArrayObjectAddressOperand().getDef() + } } /** @@ -685,7 +694,7 @@ class ElementsAddressInstruction extends UnaryInstruction { * taken may want to ignore any function that contains an `ErrorInstruction`. */ class ErrorInstruction extends Instruction { - ErrorInstruction() { getOpcode() instanceof Opcode::Error } + ErrorInstruction() { this.getOpcode() instanceof Opcode::Error } } /** @@ -695,7 +704,7 @@ class ErrorInstruction extends Instruction { * an initializer, or whose initializer only partially initializes the variable. */ class UninitializedInstruction extends VariableInstruction { - UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized } + UninitializedInstruction() { this.getOpcode() instanceof Opcode::Uninitialized } /** * Gets the variable that is uninitialized. @@ -710,7 +719,7 @@ class UninitializedInstruction extends VariableInstruction { * least one instruction, even when the AST has no semantic effect. */ class NoOpInstruction extends Instruction { - NoOpInstruction() { getOpcode() instanceof Opcode::NoOp } + NoOpInstruction() { this.getOpcode() instanceof Opcode::NoOp } } /** @@ -732,32 +741,32 @@ class NoOpInstruction extends Instruction { * `void`-returning function. */ class ReturnInstruction extends Instruction { - ReturnInstruction() { getOpcode() instanceof ReturnOpcode } + ReturnInstruction() { this.getOpcode() instanceof ReturnOpcode } } /** * An instruction that returns control to the caller of the function, without returning a value. */ class ReturnVoidInstruction extends ReturnInstruction { - ReturnVoidInstruction() { getOpcode() instanceof Opcode::ReturnVoid } + ReturnVoidInstruction() { this.getOpcode() instanceof Opcode::ReturnVoid } } /** * An instruction that returns control to the caller of the function, including a return value. */ class ReturnValueInstruction extends ReturnInstruction { - ReturnValueInstruction() { getOpcode() instanceof Opcode::ReturnValue } + ReturnValueInstruction() { this.getOpcode() instanceof Opcode::ReturnValue } /** * Gets the operand that provides the value being returned by the function. */ - final LoadOperand getReturnValueOperand() { result = getAnOperand() } + final LoadOperand getReturnValueOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value being returned by the function, if an * exact definition is available. */ - final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } + final Instruction getReturnValue() { result = this.getReturnValueOperand().getDef() } } /** @@ -770,28 +779,28 @@ class ReturnValueInstruction extends ReturnInstruction { * that the caller initialized the memory pointed to by the parameter before the call. */ class ReturnIndirectionInstruction extends VariableInstruction { - ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + ReturnIndirectionInstruction() { this.getOpcode() instanceof Opcode::ReturnIndirection } /** * Gets the operand that provides the value of the pointed-to memory. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the pointed-to memory, if an exact * definition is available. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** * Gets the operand that provides the address of the pointed-to memory. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the pointed-to memory. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } /** * Gets the parameter for which this instruction reads the final pointed-to value within the @@ -826,7 +835,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * - `StoreInstruction` - Copies a register operand to a memory result. */ class CopyInstruction extends Instruction { - CopyInstruction() { getOpcode() instanceof CopyOpcode } + CopyInstruction() { this.getOpcode() instanceof CopyOpcode } /** * Gets the operand that provides the input value of the copy. @@ -837,16 +846,16 @@ class CopyInstruction extends Instruction { * Gets the instruction whose result provides the input value of the copy, if an exact definition * is available. */ - final Instruction getSourceValue() { result = getSourceValueOperand().getDef() } + final Instruction getSourceValue() { result = this.getSourceValueOperand().getDef() } } /** * An instruction that returns a register result containing a copy of its register operand. */ class CopyValueInstruction extends CopyInstruction, UnaryInstruction { - CopyValueInstruction() { getOpcode() instanceof Opcode::CopyValue } + CopyValueInstruction() { this.getOpcode() instanceof Opcode::CopyValue } - final override UnaryOperand getSourceValueOperand() { result = getAnOperand() } + final override UnaryOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -863,47 +872,49 @@ private string getAddressOperandDescription(AddressOperand operand) { * An instruction that returns a register result containing a copy of its memory operand. */ class LoadInstruction extends CopyInstruction { - LoadInstruction() { getOpcode() instanceof Opcode::Load } + LoadInstruction() { this.getOpcode() instanceof Opcode::Load } final override string getImmediateString() { - result = getAddressOperandDescription(getSourceAddressOperand()) + result = getAddressOperandDescription(this.getSourceAddressOperand()) } /** * Gets the operand that provides the address of the value being loaded. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the value being loaded. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } - final override LoadOperand getSourceValueOperand() { result = getAnOperand() } + final override LoadOperand getSourceValueOperand() { result = this.getAnOperand() } } /** * An instruction that returns a memory result containing a copy of its register operand. */ class StoreInstruction extends CopyInstruction { - StoreInstruction() { getOpcode() instanceof Opcode::Store } + StoreInstruction() { this.getOpcode() instanceof Opcode::Store } final override string getImmediateString() { - result = getAddressOperandDescription(getDestinationAddressOperand()) + result = getAddressOperandDescription(this.getDestinationAddressOperand()) } /** * Gets the operand that provides the address of the location to which the value will be stored. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the location to which the value will * be stored, if an exact definition is available. */ - final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + final Instruction getDestinationAddress() { + result = this.getDestinationAddressOperand().getDef() + } - final override StoreValueOperand getSourceValueOperand() { result = getAnOperand() } + final override StoreValueOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -911,27 +922,27 @@ class StoreInstruction extends CopyInstruction { * operand. */ class ConditionalBranchInstruction extends Instruction { - ConditionalBranchInstruction() { getOpcode() instanceof Opcode::ConditionalBranch } + ConditionalBranchInstruction() { this.getOpcode() instanceof Opcode::ConditionalBranch } /** * Gets the operand that provides the Boolean condition controlling the branch. */ - final ConditionOperand getConditionOperand() { result = getAnOperand() } + final ConditionOperand getConditionOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the Boolean condition controlling the branch. */ - final Instruction getCondition() { result = getConditionOperand().getDef() } + final Instruction getCondition() { result = this.getConditionOperand().getDef() } /** * Gets the instruction to which control will flow if the condition is true. */ - final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) } + final Instruction getTrueSuccessor() { result = this.getSuccessor(EdgeKind::trueEdge()) } /** * Gets the instruction to which control will flow if the condition is false. */ - final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) } + final Instruction getFalseSuccessor() { result = this.getSuccessor(EdgeKind::falseEdge()) } } /** @@ -943,14 +954,14 @@ class ConditionalBranchInstruction extends Instruction { * successors. */ class ExitFunctionInstruction extends Instruction { - ExitFunctionInstruction() { getOpcode() instanceof Opcode::ExitFunction } + ExitFunctionInstruction() { this.getOpcode() instanceof Opcode::ExitFunction } } /** * An instruction whose result is a constant value. */ class ConstantInstruction extends ConstantValueInstruction { - ConstantInstruction() { getOpcode() instanceof Opcode::Constant } + ConstantInstruction() { this.getOpcode() instanceof Opcode::Constant } } /** @@ -959,7 +970,7 @@ class ConstantInstruction extends ConstantValueInstruction { class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { exists(IRType resultType | - resultType = getResultIRType() and + resultType = this.getResultIRType() and (resultType instanceof IRIntegerType or resultType instanceof IRBooleanType) ) } @@ -969,7 +980,7 @@ class IntegerConstantInstruction extends ConstantInstruction { * An instruction whose result is a constant value of floating-point type. */ class FloatConstantInstruction extends ConstantInstruction { - FloatConstantInstruction() { getResultIRType() instanceof IRFloatingPointType } + FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType } } /** @@ -978,7 +989,9 @@ class FloatConstantInstruction extends ConstantInstruction { class StringConstantInstruction extends VariableInstruction { override IRStringLiteral var; - final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } + final override string getImmediateString() { + result = Language::getStringLiteralText(this.getValue()) + } /** * Gets the string literal whose address is returned by this instruction. @@ -990,37 +1003,37 @@ class StringConstantInstruction extends VariableInstruction { * An instruction whose result is computed from two operands. */ class BinaryInstruction extends Instruction { - BinaryInstruction() { getOpcode() instanceof BinaryOpcode } + BinaryInstruction() { this.getOpcode() instanceof BinaryOpcode } /** * Gets the left operand of this binary instruction. */ - final LeftOperand getLeftOperand() { result = getAnOperand() } + final LeftOperand getLeftOperand() { result = this.getAnOperand() } /** * Gets the right operand of this binary instruction. */ - final RightOperand getRightOperand() { result = getAnOperand() } + final RightOperand getRightOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the left operand of this binary * instruction. */ - final Instruction getLeft() { result = getLeftOperand().getDef() } + final Instruction getLeft() { result = this.getLeftOperand().getDef() } /** * Gets the instruction whose result provides the value of the right operand of this binary * instruction. */ - final Instruction getRight() { result = getRightOperand().getDef() } + final Instruction getRight() { result = this.getRightOperand().getDef() } /** * Holds if this instruction's operands are `op1` and `op2`, in either order. */ final predicate hasOperands(Operand op1, Operand op2) { - op1 = getLeftOperand() and op2 = getRightOperand() + op1 = this.getLeftOperand() and op2 = this.getRightOperand() or - op1 = getRightOperand() and op2 = getLeftOperand() + op1 = this.getRightOperand() and op2 = this.getLeftOperand() } } @@ -1028,7 +1041,7 @@ class BinaryInstruction extends Instruction { * An instruction that computes the result of an arithmetic operation. */ class ArithmeticInstruction extends Instruction { - ArithmeticInstruction() { getOpcode() instanceof ArithmeticOpcode } + ArithmeticInstruction() { this.getOpcode() instanceof ArithmeticOpcode } } /** @@ -1050,7 +1063,7 @@ class UnaryArithmeticInstruction extends ArithmeticInstruction, UnaryInstruction * performed according to IEEE-754. */ class AddInstruction extends BinaryArithmeticInstruction { - AddInstruction() { getOpcode() instanceof Opcode::Add } + AddInstruction() { this.getOpcode() instanceof Opcode::Add } } /** @@ -1061,7 +1074,7 @@ class AddInstruction extends BinaryArithmeticInstruction { * according to IEEE-754. */ class SubInstruction extends BinaryArithmeticInstruction { - SubInstruction() { getOpcode() instanceof Opcode::Sub } + SubInstruction() { this.getOpcode() instanceof Opcode::Sub } } /** @@ -1072,7 +1085,7 @@ class SubInstruction extends BinaryArithmeticInstruction { * performed according to IEEE-754. */ class MulInstruction extends BinaryArithmeticInstruction { - MulInstruction() { getOpcode() instanceof Opcode::Mul } + MulInstruction() { this.getOpcode() instanceof Opcode::Mul } } /** @@ -1083,7 +1096,7 @@ class MulInstruction extends BinaryArithmeticInstruction { * to IEEE-754. */ class DivInstruction extends BinaryArithmeticInstruction { - DivInstruction() { getOpcode() instanceof Opcode::Div } + DivInstruction() { this.getOpcode() instanceof Opcode::Div } } /** @@ -1093,7 +1106,7 @@ class DivInstruction extends BinaryArithmeticInstruction { * division by zero or integer overflow is undefined. */ class RemInstruction extends BinaryArithmeticInstruction { - RemInstruction() { getOpcode() instanceof Opcode::Rem } + RemInstruction() { this.getOpcode() instanceof Opcode::Rem } } /** @@ -1104,14 +1117,14 @@ class RemInstruction extends BinaryArithmeticInstruction { * is performed according to IEEE-754. */ class NegateInstruction extends UnaryArithmeticInstruction { - NegateInstruction() { getOpcode() instanceof Opcode::Negate } + NegateInstruction() { this.getOpcode() instanceof Opcode::Negate } } /** * An instruction that computes the result of a bitwise operation. */ class BitwiseInstruction extends Instruction { - BitwiseInstruction() { getOpcode() instanceof BitwiseOpcode } + BitwiseInstruction() { this.getOpcode() instanceof BitwiseOpcode } } /** @@ -1130,7 +1143,7 @@ class UnaryBitwiseInstruction extends BitwiseInstruction, UnaryInstruction { } * Both operands must have the same integer type, which will also be the result type. */ class BitAndInstruction extends BinaryBitwiseInstruction { - BitAndInstruction() { getOpcode() instanceof Opcode::BitAnd } + BitAndInstruction() { this.getOpcode() instanceof Opcode::BitAnd } } /** @@ -1139,7 +1152,7 @@ class BitAndInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitOrInstruction extends BinaryBitwiseInstruction { - BitOrInstruction() { getOpcode() instanceof Opcode::BitOr } + BitOrInstruction() { this.getOpcode() instanceof Opcode::BitOr } } /** @@ -1148,7 +1161,7 @@ class BitOrInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitXorInstruction extends BinaryBitwiseInstruction { - BitXorInstruction() { getOpcode() instanceof Opcode::BitXor } + BitXorInstruction() { this.getOpcode() instanceof Opcode::BitXor } } /** @@ -1159,7 +1172,7 @@ class BitXorInstruction extends BinaryBitwiseInstruction { * rightmost bits are zero-filled. */ class ShiftLeftInstruction extends BinaryBitwiseInstruction { - ShiftLeftInstruction() { getOpcode() instanceof Opcode::ShiftLeft } + ShiftLeftInstruction() { this.getOpcode() instanceof Opcode::ShiftLeft } } /** @@ -1172,7 +1185,7 @@ class ShiftLeftInstruction extends BinaryBitwiseInstruction { * of the left operand. */ class ShiftRightInstruction extends BinaryBitwiseInstruction { - ShiftRightInstruction() { getOpcode() instanceof Opcode::ShiftRight } + ShiftRightInstruction() { this.getOpcode() instanceof Opcode::ShiftRight } } /** @@ -1183,7 +1196,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { int elementSize; PointerArithmeticInstruction() { - getOpcode() instanceof PointerArithmeticOpcode and + this.getOpcode() instanceof PointerArithmeticOpcode and elementSize = Raw::getInstructionElementSize(this) } @@ -1206,7 +1219,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { * An instruction that adds or subtracts an integer offset from a pointer. */ class PointerOffsetInstruction extends PointerArithmeticInstruction { - PointerOffsetInstruction() { getOpcode() instanceof PointerOffsetOpcode } + PointerOffsetInstruction() { this.getOpcode() instanceof PointerOffsetOpcode } } /** @@ -1217,7 +1230,7 @@ class PointerOffsetInstruction extends PointerArithmeticInstruction { * overflow is undefined. */ class PointerAddInstruction extends PointerOffsetInstruction { - PointerAddInstruction() { getOpcode() instanceof Opcode::PointerAdd } + PointerAddInstruction() { this.getOpcode() instanceof Opcode::PointerAdd } } /** @@ -1228,7 +1241,7 @@ class PointerAddInstruction extends PointerOffsetInstruction { * pointer underflow is undefined. */ class PointerSubInstruction extends PointerOffsetInstruction { - PointerSubInstruction() { getOpcode() instanceof Opcode::PointerSub } + PointerSubInstruction() { this.getOpcode() instanceof Opcode::PointerSub } } /** @@ -1241,31 +1254,31 @@ class PointerSubInstruction extends PointerOffsetInstruction { * undefined. */ class PointerDiffInstruction extends PointerArithmeticInstruction { - PointerDiffInstruction() { getOpcode() instanceof Opcode::PointerDiff } + PointerDiffInstruction() { this.getOpcode() instanceof Opcode::PointerDiff } } /** * An instruction whose result is computed from a single operand. */ class UnaryInstruction extends Instruction { - UnaryInstruction() { getOpcode() instanceof UnaryOpcode } + UnaryInstruction() { this.getOpcode() instanceof UnaryOpcode } /** * Gets the sole operand of this instruction. */ - final UnaryOperand getUnaryOperand() { result = getAnOperand() } + final UnaryOperand getUnaryOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the sole operand of this instruction. */ - final Instruction getUnary() { result = getUnaryOperand().getDef() } + final Instruction getUnary() { result = this.getUnaryOperand().getDef() } } /** * An instruction that converts the value of its operand to a value of a different type. */ class ConvertInstruction extends UnaryInstruction { - ConvertInstruction() { getOpcode() instanceof Opcode::Convert } + ConvertInstruction() { this.getOpcode() instanceof Opcode::Convert } } /** @@ -1279,7 +1292,7 @@ class ConvertInstruction extends UnaryInstruction { * `as` expression. */ class CheckedConvertOrNullInstruction extends UnaryInstruction { - CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull } + CheckedConvertOrNullInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrNull } } /** @@ -1293,7 +1306,7 @@ class CheckedConvertOrNullInstruction extends UnaryInstruction { * expression. */ class CheckedConvertOrThrowInstruction extends UnaryInstruction { - CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow } + CheckedConvertOrThrowInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrThrow } } /** @@ -1306,7 +1319,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction { * the most-derived object. */ class CompleteObjectAddressInstruction extends UnaryInstruction { - CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress } + CompleteObjectAddressInstruction() { this.getOpcode() instanceof Opcode::CompleteObjectAddress } } /** @@ -1351,7 +1364,7 @@ class InheritanceConversionInstruction extends UnaryInstruction { * An instruction that converts from the address of a derived class to the address of a base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } + ConvertToBaseInstruction() { this.getOpcode() instanceof ConvertToBaseOpcode } } /** @@ -1361,7 +1374,9 @@ class ConvertToBaseInstruction extends InheritanceConversionInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } + ConvertToNonVirtualBaseInstruction() { + this.getOpcode() instanceof Opcode::ConvertToNonVirtualBase + } } /** @@ -1371,7 +1386,7 @@ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } + ConvertToVirtualBaseInstruction() { this.getOpcode() instanceof Opcode::ConvertToVirtualBase } } /** @@ -1381,7 +1396,7 @@ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { - ConvertToDerivedInstruction() { getOpcode() instanceof Opcode::ConvertToDerived } + ConvertToDerivedInstruction() { this.getOpcode() instanceof Opcode::ConvertToDerived } } /** @@ -1390,7 +1405,7 @@ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { * The operand must have an integer type, which will also be the result type. */ class BitComplementInstruction extends UnaryBitwiseInstruction { - BitComplementInstruction() { getOpcode() instanceof Opcode::BitComplement } + BitComplementInstruction() { this.getOpcode() instanceof Opcode::BitComplement } } /** @@ -1399,14 +1414,14 @@ class BitComplementInstruction extends UnaryBitwiseInstruction { * The operand must have a Boolean type, which will also be the result type. */ class LogicalNotInstruction extends UnaryInstruction { - LogicalNotInstruction() { getOpcode() instanceof Opcode::LogicalNot } + LogicalNotInstruction() { this.getOpcode() instanceof Opcode::LogicalNot } } /** * An instruction that compares two numeric operands. */ class CompareInstruction extends BinaryInstruction { - CompareInstruction() { getOpcode() instanceof CompareOpcode } + CompareInstruction() { this.getOpcode() instanceof CompareOpcode } } /** @@ -1417,7 +1432,7 @@ class CompareInstruction extends BinaryInstruction { * unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareEQInstruction extends CompareInstruction { - CompareEQInstruction() { getOpcode() instanceof Opcode::CompareEQ } + CompareEQInstruction() { this.getOpcode() instanceof Opcode::CompareEQ } } /** @@ -1428,14 +1443,14 @@ class CompareEQInstruction extends CompareInstruction { * `left == right`. Floating-point comparison is performed according to IEEE-754. */ class CompareNEInstruction extends CompareInstruction { - CompareNEInstruction() { getOpcode() instanceof Opcode::CompareNE } + CompareNEInstruction() { this.getOpcode() instanceof Opcode::CompareNE } } /** * An instruction that does a relative comparison of two values, such as `<` or `>=`. */ class RelationalInstruction extends CompareInstruction { - RelationalInstruction() { getOpcode() instanceof RelationalOpcode } + RelationalInstruction() { this.getOpcode() instanceof RelationalOpcode } /** * Gets the operand on the "greater" (or "greater-or-equal") side @@ -1467,11 +1482,11 @@ class RelationalInstruction extends CompareInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLTInstruction extends RelationalInstruction { - CompareLTInstruction() { getOpcode() instanceof Opcode::CompareLT } + CompareLTInstruction() { this.getOpcode() instanceof Opcode::CompareLT } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { any() } } @@ -1484,11 +1499,11 @@ class CompareLTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGTInstruction extends RelationalInstruction { - CompareGTInstruction() { getOpcode() instanceof Opcode::CompareGT } + CompareGTInstruction() { this.getOpcode() instanceof Opcode::CompareGT } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { any() } } @@ -1502,11 +1517,11 @@ class CompareGTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLEInstruction extends RelationalInstruction { - CompareLEInstruction() { getOpcode() instanceof Opcode::CompareLE } + CompareLEInstruction() { this.getOpcode() instanceof Opcode::CompareLE } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { none() } } @@ -1520,11 +1535,11 @@ class CompareLEInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGEInstruction extends RelationalInstruction { - CompareGEInstruction() { getOpcode() instanceof Opcode::CompareGE } + CompareGEInstruction() { this.getOpcode() instanceof Opcode::CompareGE } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { none() } } @@ -1543,78 +1558,78 @@ class CompareGEInstruction extends RelationalInstruction { * of any case edge. */ class SwitchInstruction extends Instruction { - SwitchInstruction() { getOpcode() instanceof Opcode::Switch } + SwitchInstruction() { this.getOpcode() instanceof Opcode::Switch } /** Gets the operand that provides the integer value controlling the switch. */ - final ConditionOperand getExpressionOperand() { result = getAnOperand() } + final ConditionOperand getExpressionOperand() { result = this.getAnOperand() } /** Gets the instruction whose result provides the integer value controlling the switch. */ - final Instruction getExpression() { result = getExpressionOperand().getDef() } + final Instruction getExpression() { result = this.getExpressionOperand().getDef() } /** Gets the successor instructions along the case edges of the switch. */ - final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) } + final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = this.getSuccessor(edge)) } /** Gets the successor instruction along the default edge of the switch, if any. */ - final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) } + final Instruction getDefaultSuccessor() { result = this.getSuccessor(EdgeKind::defaultEdge()) } } /** * An instruction that calls a function. */ class CallInstruction extends Instruction { - CallInstruction() { getOpcode() instanceof Opcode::Call } + CallInstruction() { this.getOpcode() instanceof Opcode::Call } final override string getImmediateString() { - result = getStaticCallTarget().toString() + result = this.getStaticCallTarget().toString() or - not exists(getStaticCallTarget()) and result = "?" + not exists(this.getStaticCallTarget()) and result = "?" } /** * Gets the operand the specifies the target function of the call. */ - final CallTargetOperand getCallTargetOperand() { result = getAnOperand() } + final CallTargetOperand getCallTargetOperand() { result = this.getAnOperand() } /** * Gets the `Instruction` that computes the target function of the call. This is usually a * `FunctionAddress` instruction, but can also be an arbitrary instruction that produces a * function pointer. */ - final Instruction getCallTarget() { result = getCallTargetOperand().getDef() } + final Instruction getCallTarget() { result = this.getCallTargetOperand().getDef() } /** * Gets all of the argument operands of the call, including the `this` pointer, if any. */ - final ArgumentOperand getAnArgumentOperand() { result = getAnOperand() } + final ArgumentOperand getAnArgumentOperand() { result = this.getAnOperand() } /** * Gets the `Function` that the call targets, if this is statically known. */ final Language::Function getStaticCallTarget() { - result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() + result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() } /** * Gets all of the arguments of the call, including the `this` pointer, if any. */ - final Instruction getAnArgument() { result = getAnArgumentOperand().getDef() } + final Instruction getAnArgument() { result = this.getAnArgumentOperand().getDef() } /** * Gets the `this` pointer argument operand of the call, if any. */ - final ThisArgumentOperand getThisArgumentOperand() { result = getAnOperand() } + final ThisArgumentOperand getThisArgumentOperand() { result = this.getAnOperand() } /** * Gets the `this` pointer argument of the call, if any. */ - final Instruction getThisArgument() { result = getThisArgumentOperand().getDef() } + final Instruction getThisArgument() { result = this.getThisArgumentOperand().getDef() } /** * Gets the argument operand at the specified index. */ pragma[noinline] final PositionalArgumentOperand getPositionalArgumentOperand(int index) { - result = getAnOperand() and + result = this.getAnOperand() and result.getIndex() = index } @@ -1623,7 +1638,7 @@ class CallInstruction extends Instruction { */ pragma[noinline] final Instruction getPositionalArgument(int index) { - result = getPositionalArgumentOperand(index).getDef() + result = this.getPositionalArgumentOperand(index).getDef() } /** @@ -1631,16 +1646,16 @@ class CallInstruction extends Instruction { */ pragma[noinline] final ArgumentOperand getArgumentOperand(int index) { - index >= 0 and result = getPositionalArgumentOperand(index) + index >= 0 and result = this.getPositionalArgumentOperand(index) or - index = -1 and result = getThisArgumentOperand() + index = -1 and result = this.getThisArgumentOperand() } /** * Gets the argument at the specified index, or `this` if `index` is `-1`. */ pragma[noinline] - final Instruction getArgument(int index) { result = getArgumentOperand(index).getDef() } + final Instruction getArgument(int index) { result = this.getArgumentOperand(index).getDef() } /** * Gets the number of arguments of the call, including the `this` pointer, if any. @@ -1665,7 +1680,7 @@ class CallInstruction extends Instruction { * An instruction representing a side effect of a function call. */ class SideEffectInstruction extends Instruction { - SideEffectInstruction() { getOpcode() instanceof SideEffectOpcode } + SideEffectInstruction() { this.getOpcode() instanceof SideEffectOpcode } /** * Gets the instruction whose execution causes this side effect. @@ -1680,7 +1695,7 @@ class SideEffectInstruction extends Instruction { * accessed by that call. */ class CallSideEffectInstruction extends SideEffectInstruction { - CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect } + CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } } /** @@ -1691,7 +1706,7 @@ class CallSideEffectInstruction extends SideEffectInstruction { * call target cannot write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { - CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } + CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } } /** @@ -1699,33 +1714,33 @@ class CallReadSideEffectInstruction extends SideEffectInstruction { * specific parameter. */ class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + ReadSideEffectInstruction() { this.getOpcode() instanceof ReadSideEffectOpcode } /** Gets the operand for the value that will be read from this instruction, if known. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** Gets the value that will be read from this instruction, if known. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** Gets the operand for the address from which this instruction may read. */ - final AddressOperand getArgumentOperand() { result = getAnOperand() } + final AddressOperand getArgumentOperand() { result = this.getAnOperand() } /** Gets the address from which this instruction may read. */ - final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } + final Instruction getArgumentDef() { result = this.getArgumentOperand().getDef() } } /** * An instruction representing the read of an indirect parameter within a function call. */ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { - IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } + IndirectReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::IndirectReadSideEffect } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } + BufferReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::BufferReadSideEffect } } /** @@ -1733,18 +1748,18 @@ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferReadSideEffect + this.getOpcode() instanceof Opcode::SizedBufferReadSideEffect } /** * Gets the operand that holds the number of bytes read from the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes read from the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1752,17 +1767,17 @@ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } + WriteSideEffectInstruction() { this.getOpcode() instanceof WriteSideEffectOpcode } /** * Get the operand that holds the address of the memory to be written. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the memory to be written. */ - Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + Instruction getDestinationAddress() { result = this.getDestinationAddressOperand().getDef() } } /** @@ -1770,7 +1785,7 @@ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstructi */ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMustWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMustWriteSideEffect } } @@ -1780,7 +1795,7 @@ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction */ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { BufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::BufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::BufferMustWriteSideEffect } } @@ -1790,18 +1805,18 @@ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1812,7 +1827,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi */ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMayWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMayWriteSideEffect } } @@ -1822,7 +1837,9 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { * Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten. */ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { - BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect } + BufferMayWriteSideEffectInstruction() { + this.getOpcode() instanceof Opcode::BufferMayWriteSideEffect + } } /** @@ -1832,18 +1849,18 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1852,80 +1869,80 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio */ class InitializeDynamicAllocationInstruction extends SideEffectInstruction { InitializeDynamicAllocationInstruction() { - getOpcode() instanceof Opcode::InitializeDynamicAllocation + this.getOpcode() instanceof Opcode::InitializeDynamicAllocation } /** * Gets the operand that represents the address of the allocation this instruction is initializing. */ - final AddressOperand getAllocationAddressOperand() { result = getAnOperand() } + final AddressOperand getAllocationAddressOperand() { result = this.getAnOperand() } /** * Gets the address for the allocation this instruction is initializing. */ - final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() } + final Instruction getAllocationAddress() { result = this.getAllocationAddressOperand().getDef() } } /** * An instruction representing a GNU or MSVC inline assembly statement. */ class InlineAsmInstruction extends Instruction { - InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm } + InlineAsmInstruction() { this.getOpcode() instanceof Opcode::InlineAsm } } /** * An instruction that throws an exception. */ class ThrowInstruction extends Instruction { - ThrowInstruction() { getOpcode() instanceof ThrowOpcode } + ThrowInstruction() { this.getOpcode() instanceof ThrowOpcode } } /** * An instruction that throws a new exception. */ class ThrowValueInstruction extends ThrowInstruction { - ThrowValueInstruction() { getOpcode() instanceof Opcode::ThrowValue } + ThrowValueInstruction() { this.getOpcode() instanceof Opcode::ThrowValue } /** * Gets the address operand of the exception thrown by this instruction. */ - final AddressOperand getExceptionAddressOperand() { result = getAnOperand() } + final AddressOperand getExceptionAddressOperand() { result = this.getAnOperand() } /** * Gets the address of the exception thrown by this instruction. */ - final Instruction getExceptionAddress() { result = getExceptionAddressOperand().getDef() } + final Instruction getExceptionAddress() { result = this.getExceptionAddressOperand().getDef() } /** * Gets the operand for the exception thrown by this instruction. */ - final LoadOperand getExceptionOperand() { result = getAnOperand() } + final LoadOperand getExceptionOperand() { result = this.getAnOperand() } /** * Gets the exception thrown by this instruction. */ - final Instruction getException() { result = getExceptionOperand().getDef() } + final Instruction getException() { result = this.getExceptionOperand().getDef() } } /** * An instruction that re-throws the current exception. */ class ReThrowInstruction extends ThrowInstruction { - ReThrowInstruction() { getOpcode() instanceof Opcode::ReThrow } + ReThrowInstruction() { this.getOpcode() instanceof Opcode::ReThrow } } /** * An instruction that exits the current function by propagating an exception. */ class UnwindInstruction extends Instruction { - UnwindInstruction() { getOpcode() instanceof Opcode::Unwind } + UnwindInstruction() { this.getOpcode() instanceof Opcode::Unwind } } /** * An instruction that starts a `catch` handler. */ class CatchInstruction extends Instruction { - CatchInstruction() { getOpcode() instanceof CatchOpcode } + CatchInstruction() { this.getOpcode() instanceof CatchOpcode } } /** @@ -1935,7 +1952,7 @@ class CatchByTypeInstruction extends CatchInstruction { Language::LanguageType exceptionType; CatchByTypeInstruction() { - getOpcode() instanceof Opcode::CatchByType and + this.getOpcode() instanceof Opcode::CatchByType and exceptionType = Raw::getInstructionExceptionType(this) } @@ -1951,21 +1968,21 @@ class CatchByTypeInstruction extends CatchInstruction { * An instruction that catches any exception. */ class CatchAnyInstruction extends CatchInstruction { - CatchAnyInstruction() { getOpcode() instanceof Opcode::CatchAny } + CatchAnyInstruction() { this.getOpcode() instanceof Opcode::CatchAny } } /** * An instruction that initializes all escaped memory. */ class AliasedDefinitionInstruction extends Instruction { - AliasedDefinitionInstruction() { getOpcode() instanceof Opcode::AliasedDefinition } + AliasedDefinitionInstruction() { this.getOpcode() instanceof Opcode::AliasedDefinition } } /** * An instruction that consumes all escaped memory on exit from the function. */ class AliasedUseInstruction extends Instruction { - AliasedUseInstruction() { getOpcode() instanceof Opcode::AliasedUse } + AliasedUseInstruction() { this.getOpcode() instanceof Opcode::AliasedUse } } /** @@ -1979,7 +1996,7 @@ class AliasedUseInstruction extends Instruction { * runtime. */ class PhiInstruction extends Instruction { - PhiInstruction() { getOpcode() instanceof Opcode::Phi } + PhiInstruction() { this.getOpcode() instanceof Opcode::Phi } /** * Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block. @@ -2047,29 +2064,29 @@ class PhiInstruction extends Instruction { * https://link.springer.com/content/pdf/10.1007%2F3-540-61053-7_66.pdf. */ class ChiInstruction extends Instruction { - ChiInstruction() { getOpcode() instanceof Opcode::Chi } + ChiInstruction() { this.getOpcode() instanceof Opcode::Chi } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final ChiTotalOperand getTotalOperand() { result = getAnOperand() } + final ChiTotalOperand getTotalOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final Instruction getTotal() { result = getTotalOperand().getDef() } + final Instruction getTotal() { result = this.getTotalOperand().getDef() } /** * Gets the operand that represents the new value written by the memory write. */ - final ChiPartialOperand getPartialOperand() { result = getAnOperand() } + final ChiPartialOperand getPartialOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the new value written by the memory write. */ - final Instruction getPartial() { result = getPartialOperand().getDef() } + final Instruction getPartial() { result = this.getPartialOperand().getDef() } /** * Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand. @@ -2093,7 +2110,7 @@ class ChiInstruction extends Instruction { * or `Switch` instruction where that particular edge is infeasible. */ class UnreachedInstruction extends Instruction { - UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached } + UnreachedInstruction() { this.getOpcode() instanceof Opcode::Unreached } } /** @@ -2106,7 +2123,7 @@ class BuiltInOperationInstruction extends Instruction { Language::BuiltInOperation operation; BuiltInOperationInstruction() { - getOpcode() instanceof BuiltInOperationOpcode and + this.getOpcode() instanceof BuiltInOperationOpcode and operation = Raw::getInstructionBuiltInOperation(this) } @@ -2122,9 +2139,9 @@ class BuiltInOperationInstruction extends Instruction { * actual operation is specified by the `getBuiltInOperation()` predicate. */ class BuiltInInstruction extends BuiltInOperationInstruction { - BuiltInInstruction() { getOpcode() instanceof Opcode::BuiltIn } + BuiltInInstruction() { this.getOpcode() instanceof Opcode::BuiltIn } - final override string getImmediateString() { result = getBuiltInOperation().toString() } + final override string getImmediateString() { result = this.getBuiltInOperation().toString() } } /** @@ -2135,7 +2152,7 @@ class BuiltInInstruction extends BuiltInOperationInstruction { * to the `...` parameter. */ class VarArgsStartInstruction extends UnaryInstruction { - VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart } + VarArgsStartInstruction() { this.getOpcode() instanceof Opcode::VarArgsStart } } /** @@ -2145,7 +2162,7 @@ class VarArgsStartInstruction extends UnaryInstruction { * a result. */ class VarArgsEndInstruction extends UnaryInstruction { - VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd } + VarArgsEndInstruction() { this.getOpcode() instanceof Opcode::VarArgsEnd } } /** @@ -2155,7 +2172,7 @@ class VarArgsEndInstruction extends UnaryInstruction { * argument. */ class VarArgInstruction extends UnaryInstruction { - VarArgInstruction() { getOpcode() instanceof Opcode::VarArg } + VarArgInstruction() { this.getOpcode() instanceof Opcode::VarArg } } /** @@ -2166,7 +2183,7 @@ class VarArgInstruction extends UnaryInstruction { * argument of the `...` parameter. */ class NextVarArgInstruction extends UnaryInstruction { - NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg } + NextVarArgInstruction() { this.getOpcode() instanceof Opcode::NextVarArg } } /** @@ -2180,5 +2197,5 @@ class NextVarArgInstruction extends UnaryInstruction { * The result is the address of the newly allocated object. */ class NewObjInstruction extends Instruction { - NewObjInstruction() { getOpcode() instanceof Opcode::NewObj } + NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll index d7cf89ca9aa..85d217bd361 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -46,12 +46,12 @@ class Operand extends TStageOperand { /** * Gets the location of the source code for this operand. */ - final Language::Location getLocation() { result = getUse().getLocation() } + final Language::Location getLocation() { result = this.getUse().getLocation() } /** * Gets the function that contains this operand. */ - final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() } + final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() } /** * Gets the `Instruction` that consumes this operand. @@ -74,7 +74,7 @@ class Operand extends TStageOperand { */ final Instruction getDef() { result = this.getAnyDef() and - getDefinitionOverlap() instanceof MustExactlyOverlap + this.getDefinitionOverlap() instanceof MustExactlyOverlap } /** @@ -82,7 +82,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` that consumes this operand. */ - deprecated final Instruction getUseInstruction() { result = getUse() } + deprecated final Instruction getUseInstruction() { result = this.getUse() } /** * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this @@ -91,7 +91,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` whose result is the value of the operand. */ - deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() } + deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } /** * Gets the overlap relationship between the operand's definition and its use. @@ -101,7 +101,9 @@ class Operand extends TStageOperand { /** * Holds if the result of the definition instruction does not exactly overlap this use. */ - final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap } + final predicate isDefinitionInexact() { + not this.getDefinitionOverlap() instanceof MustExactlyOverlap + } /** * Gets a prefix to use when dumping the operand in an operand list. @@ -121,7 +123,7 @@ class Operand extends TStageOperand { * For example: `this:r3_5` */ final string getDumpString() { - result = getDumpLabel() + getInexactSpecifier() + getDefinitionId() + result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId() } /** @@ -129,9 +131,9 @@ class Operand extends TStageOperand { * definition is not modeled in SSA. */ private string getDefinitionId() { - result = getAnyDef().getResultId() + result = this.getAnyDef().getResultId() or - not exists(getAnyDef()) and result = "m?" + not exists(this.getAnyDef()) and result = "m?" } /** @@ -140,7 +142,7 @@ class Operand extends TStageOperand { * the empty string. */ private string getInexactSpecifier() { - if isDefinitionInexact() then result = "~" else result = "" + if this.isDefinitionInexact() then result = "~" else result = "" } /** @@ -155,7 +157,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() } + Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() } /** * Gets the language-neutral type of the value consumed by this operand. This is usually the same @@ -164,7 +166,7 @@ class Operand extends TStageOperand { * from the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final IRType getIRType() { result = getLanguageType().getIRType() } + final IRType getIRType() { result = this.getLanguageType().getIRType() } /** * Gets the type of the value consumed by this operand. This is usually the same as the @@ -173,7 +175,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final Language::Type getType() { getLanguageType().hasType(result, _) } + final Language::Type getType() { this.getLanguageType().hasType(result, _) } /** * Holds if the value consumed by this operand is a glvalue. If this @@ -182,13 +184,13 @@ class Operand extends TStageOperand { * not hold, the value of the operand represents a value whose type is * given by `getType()`. */ - final predicate isGLValue() { getLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getLanguageType().hasType(_, true) } /** * Gets the size of the value consumed by this operand, in bytes. If the operand does not have * a known constant size, this predicate does not hold. */ - final int getSize() { result = getLanguageType().getByteSize() } + final int getSize() { result = this.getLanguageType().getByteSize() } } /** @@ -205,7 +207,7 @@ class MemoryOperand extends Operand { /** * Gets the kind of memory access performed by the operand. */ - MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() } + MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() } /** * Holds if the memory access performed by this operand will not always read from every bit in the @@ -215,7 +217,7 @@ class MemoryOperand extends Operand { * conservative estimate of the memory that might actually be accessed at runtime (for example, * the global side effects of a function call). */ - predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() } + predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() } /** * Returns the operand that holds the memory address from which the current operand loads its @@ -223,8 +225,8 @@ class MemoryOperand extends Operand { * is `r1`. */ final AddressOperand getAddressOperand() { - getMemoryAccess().usesAddressOperand() and - result.getUse() = getUse() + this.getMemoryAccess().usesAddressOperand() and + result.getUse() = this.getUse() } } @@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe result = unique(Instruction defInstr | hasDefinition(defInstr, _)) } - final override Overlap getDefinitionOverlap() { hasDefinition(_, result) } + final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) } pragma[noinline] private predicate hasDefinition(Instruction defInstr, Overlap overlap) { @@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand { final override Overlap getDefinitionOverlap() { result = overlap } - final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() } - - final override string getDumpLabel() { - result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" + final override int getDumpSortOrder() { + result = 11 + this.getPredecessorBlock().getDisplayIndex() } - final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() } + final override string getDumpLabel() { + result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":" + } + + final override string getDumpId() { + result = this.getPredecessorBlock().getDisplayIndex().toString() + } /** * Gets the predecessor block from which this value comes. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll index 4b86f9a7cec..bb8630a5e0c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll @@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock { final string toString() { result = getFirstInstruction(this).toString() } /** Gets the source location of the first non-`Phi` instruction in this block. */ - final Language::Location getLocation() { result = getFirstInstruction().getLocation() } + final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() } /** * INTERNAL: Do not use. @@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock { ) and this = rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = getEnclosingFunction() and + funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and // Ensure that the block containing `EnterFunction` always comes first. if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction @@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock { * Get the `Phi` instructions that appear at the start of this block. */ final PhiInstruction getAPhiInstruction() { - Construction::getPhiInstructionBlockStart(result) = getFirstInstruction() + Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction() } /** * Gets an instruction in this block. This includes `Phi` instructions. */ final Instruction getAnInstruction() { - result = getInstruction(_) or - result = getAPhiInstruction() + result = this.getInstruction(_) or + result = this.getAPhiInstruction() } /** @@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock { /** * Gets the last instruction in this block. */ - final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) } + final Instruction getLastInstruction() { + result = this.getInstruction(this.getInstructionCount() - 1) + } /** * Gets the number of non-`Phi` instructions in this block. @@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase { * Block `A` dominates block `B` if any control flow path from the entry block of the function to * block `B` must pass through block `A`. A block always dominates itself. */ - final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block } + final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block } /** * Gets a block on the dominance frontier of this block. @@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock dominanceFrontier() { - dominates(result.getAPredecessor()) and - not strictlyDominates(result) + this.dominates(result.getAPredecessor()) and + not this.strictlyDominates(result) } /** @@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase { * Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the * function must pass through block `A`. A block always post-dominates itself. */ - final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block } + final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block } /** * Gets a block on the post-dominance frontier of this block. @@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock postPominanceFrontier() { - postDominates(result.getASuccessor()) and - not strictlyPostDominates(result) + this.postDominates(result.getASuccessor()) and + not this.strictlyPostDominates(result) } /** * Holds if this block is reachable from the entry block of its function. */ final predicate isReachableFromFunctionEntry() { - this = getEnclosingIRFunction().getEntryBlock() or - getAPredecessor().isReachableFromFunctionEntry() + this = this.getEnclosingIRFunction().getEntryBlock() or + this.getAPredecessor().isReachableFromFunctionEntry() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 6f471d8a7e8..88a973fc5a8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction { } /** Gets a textual representation of this element. */ - final string toString() { result = getOpcode().toString() + ": " + getAST().toString() } + final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() } /** * Gets a string showing the result, opcode, and operands of the instruction, equivalent to what @@ -50,7 +50,8 @@ class Instruction extends Construction::TStageInstruction { * `mu0_28(int) = Store r0_26, r0_27` */ final string getDumpString() { - result = getResultString() + " = " + getOperationString() + " " + getOperandsString() + result = + this.getResultString() + " = " + this.getOperationString() + " " + this.getOperandsString() } private predicate shouldGenerateDumpStrings() { @@ -66,10 +67,13 @@ class Instruction extends Construction::TStageInstruction { * VariableAddress[x] */ final string getOperationString() { - shouldGenerateDumpStrings() and - if exists(getImmediateString()) - then result = getOperationPrefix() + getOpcode().toString() + "[" + getImmediateString() + "]" - else result = getOperationPrefix() + getOpcode().toString() + this.shouldGenerateDumpStrings() and + if exists(this.getImmediateString()) + then + result = + this.getOperationPrefix() + this.getOpcode().toString() + "[" + this.getImmediateString() + + "]" + else result = this.getOperationPrefix() + this.getOpcode().toString() } /** @@ -78,17 +82,17 @@ class Instruction extends Construction::TStageInstruction { string getImmediateString() { none() } private string getOperationPrefix() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and if this instanceof SideEffectInstruction then result = "^" else result = "" } private string getResultPrefix() { - shouldGenerateDumpStrings() and - if getResultIRType() instanceof IRVoidType + this.shouldGenerateDumpStrings() and + if this.getResultIRType() instanceof IRVoidType then result = "v" else - if hasMemoryResult() - then if isResultModeled() then result = "m" else result = "mu" + if this.hasMemoryResult() + then if this.isResultModeled() then result = "m" else result = "mu" else result = "r" } @@ -97,7 +101,7 @@ class Instruction extends Construction::TStageInstruction { * used by debugging and printing code only. */ int getDisplayIndexInBlock() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and exists(IRBlock block | this = block.getInstruction(result) or @@ -111,12 +115,12 @@ class Instruction extends Construction::TStageInstruction { } private int getLineRank() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and this = rank[result](Instruction instr | instr = - getAnInstructionAtLine(getEnclosingIRFunction(), getLocation().getFile(), - getLocation().getStartLine()) + getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), + this.getLocation().getStartLine()) | instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() ) @@ -130,8 +134,9 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1` */ string getResultId() { - shouldGenerateDumpStrings() and - result = getResultPrefix() + getAST().getLocation().getStartLine() + "_" + getLineRank() + this.shouldGenerateDumpStrings() and + result = + this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank() } /** @@ -142,8 +147,8 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1(int*)` */ final string getResultString() { - shouldGenerateDumpStrings() and - result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")" + this.shouldGenerateDumpStrings() and + result = this.getResultId() + "(" + this.getResultLanguageType().getDumpString() + ")" } /** @@ -153,10 +158,10 @@ class Instruction extends Construction::TStageInstruction { * Example: `func:r3_4, this:r3_5` */ string getOperandsString() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and result = concat(Operand operand | - operand = getAnOperand() + operand = this.getAnOperand() | operand.getDumpString(), ", " order by operand.getDumpSortOrder() ) @@ -190,7 +195,7 @@ class Instruction extends Construction::TStageInstruction { * Gets the function that contains this instruction. */ final Language::Function getEnclosingFunction() { - result = getEnclosingIRFunction().getFunction() + result = this.getEnclosingIRFunction().getFunction() } /** @@ -208,7 +213,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the location of the source code for this instruction. */ - final Language::Location getLocation() { result = getAST().getLocation() } + final Language::Location getLocation() { result = this.getAST().getLocation() } /** * Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a @@ -243,7 +248,7 @@ class Instruction extends Construction::TStageInstruction { * a result, its result type will be `IRVoidType`. */ cached - final IRType getResultIRType() { result = getResultLanguageType().getIRType() } + final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() } /** * Gets the type of the result produced by this instruction. If the @@ -254,7 +259,7 @@ class Instruction extends Construction::TStageInstruction { */ final Language::Type getResultType() { exists(Language::LanguageType resultType | - resultType = getResultLanguageType() and + resultType = this.getResultLanguageType() and ( resultType.hasUnspecifiedType(result, _) or @@ -283,7 +288,7 @@ class Instruction extends Construction::TStageInstruction { * result of the `Load` instruction is a prvalue of type `int`, representing * the integer value loaded from variable `x`. */ - final predicate isGLValue() { getResultLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getResultLanguageType().hasType(_, true) } /** * Gets the size of the result produced by this instruction, in bytes. If the @@ -292,7 +297,7 @@ class Instruction extends Construction::TStageInstruction { * If `this.isGLValue()` holds for this instruction, the value of * `getResultSize()` will always be the size of a pointer. */ - final int getResultSize() { result = getResultLanguageType().getByteSize() } + final int getResultSize() { result = this.getResultLanguageType().getByteSize() } /** * Gets the opcode that specifies the operation performed by this instruction. @@ -314,14 +319,16 @@ class Instruction extends Construction::TStageInstruction { /** * Holds if this instruction produces a memory result. */ - final predicate hasMemoryResult() { exists(getResultMemoryAccess()) } + final predicate hasMemoryResult() { exists(this.getResultMemoryAccess()) } /** * Gets the kind of memory access performed by this instruction's result. * Holds only for instructions with a memory result. */ pragma[inline] - final MemoryAccessKind getResultMemoryAccess() { result = getOpcode().getWriteMemoryAccess() } + final MemoryAccessKind getResultMemoryAccess() { + result = this.getOpcode().getWriteMemoryAccess() + } /** * Holds if the memory access performed by this instruction's result will not always write to @@ -332,7 +339,7 @@ class Instruction extends Construction::TStageInstruction { * (for example, the global side effects of a function call). */ pragma[inline] - final predicate hasResultMayMemoryAccess() { getOpcode().hasMayWriteMemoryAccess() } + final predicate hasResultMayMemoryAccess() { this.getOpcode().hasMayWriteMemoryAccess() } /** * Gets the operand that holds the memory address to which this instruction stores its @@ -340,7 +347,7 @@ class Instruction extends Construction::TStageInstruction { * is `r1`. */ final AddressOperand getResultAddressOperand() { - getResultMemoryAccess().usesAddressOperand() and + this.getResultMemoryAccess().usesAddressOperand() and result.getUse() = this } @@ -349,7 +356,7 @@ class Instruction extends Construction::TStageInstruction { * result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()` * is the instruction that defines `r1`. */ - final Instruction getResultAddress() { result = getResultAddressOperand().getDef() } + final Instruction getResultAddress() { result = this.getResultAddressOperand().getDef() } /** * Holds if the result of this instruction is precisely modeled in SSA. Always @@ -368,7 +375,7 @@ class Instruction extends Construction::TStageInstruction { */ final predicate isResultModeled() { // Register results are always in SSA form. - not hasMemoryResult() or + not this.hasMemoryResult() or Construction::hasModeledMemoryResult(this) } @@ -412,7 +419,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct successors of this instruction. */ - final Instruction getASuccessor() { result = getSuccessor(_) } + final Instruction getASuccessor() { result = this.getSuccessor(_) } /** * Gets a predecessor of this instruction such that the predecessor reaches @@ -423,7 +430,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct predecessors of this instruction. */ - final Instruction getAPredecessor() { result = getPredecessor(_) } + final Instruction getAPredecessor() { result = this.getPredecessor(_) } } /** @@ -543,7 +550,7 @@ class IndexedInstruction extends Instruction { * at this instruction. This instruction has no predecessors. */ class EnterFunctionInstruction extends Instruction { - EnterFunctionInstruction() { getOpcode() instanceof Opcode::EnterFunction } + EnterFunctionInstruction() { this.getOpcode() instanceof Opcode::EnterFunction } } /** @@ -554,7 +561,7 @@ class EnterFunctionInstruction extends Instruction { * struct, or union, see `FieldAddressInstruction`. */ class VariableAddressInstruction extends VariableInstruction { - VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress } + VariableAddressInstruction() { this.getOpcode() instanceof Opcode::VariableAddress } } /** @@ -566,7 +573,7 @@ class VariableAddressInstruction extends VariableInstruction { * The result has an `IRFunctionAddress` type. */ class FunctionAddressInstruction extends FunctionInstruction { - FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress } + FunctionAddressInstruction() { this.getOpcode() instanceof Opcode::FunctionAddress } } /** @@ -577,7 +584,7 @@ class FunctionAddressInstruction extends FunctionInstruction { * initializes that parameter. */ class InitializeParameterInstruction extends VariableInstruction { - InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter } + InitializeParameterInstruction() { this.getOpcode() instanceof Opcode::InitializeParameter } /** * Gets the parameter initialized by this instruction. @@ -603,7 +610,7 @@ class InitializeParameterInstruction extends VariableInstruction { * initialized elsewhere, would not otherwise have a definition in this function. */ class InitializeNonLocalInstruction extends Instruction { - InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal } + InitializeNonLocalInstruction() { this.getOpcode() instanceof Opcode::InitializeNonLocal } } /** @@ -611,7 +618,7 @@ class InitializeNonLocalInstruction extends Instruction { * with the value of that memory on entry to the function. */ class InitializeIndirectionInstruction extends VariableInstruction { - InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + InitializeIndirectionInstruction() { this.getOpcode() instanceof Opcode::InitializeIndirection } /** * Gets the parameter initialized by this instruction. @@ -635,24 +642,24 @@ class InitializeIndirectionInstruction extends VariableInstruction { * An instruction that initializes the `this` pointer parameter of the enclosing function. */ class InitializeThisInstruction extends Instruction { - InitializeThisInstruction() { getOpcode() instanceof Opcode::InitializeThis } + InitializeThisInstruction() { this.getOpcode() instanceof Opcode::InitializeThis } } /** * An instruction that computes the address of a non-static field of an object. */ class FieldAddressInstruction extends FieldInstruction { - FieldAddressInstruction() { getOpcode() instanceof Opcode::FieldAddress } + FieldAddressInstruction() { this.getOpcode() instanceof Opcode::FieldAddress } /** * Gets the operand that provides the address of the object containing the field. */ - final UnaryOperand getObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the object containing the field. */ - final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() } + final Instruction getObjectAddress() { result = this.getObjectAddressOperand().getDef() } } /** @@ -661,17 +668,19 @@ class FieldAddressInstruction extends FieldInstruction { * This instruction is used for element access to C# arrays. */ class ElementsAddressInstruction extends UnaryInstruction { - ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress } + ElementsAddressInstruction() { this.getOpcode() instanceof Opcode::ElementsAddress } /** * Gets the operand that provides the address of the array object. */ - final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getArrayObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the array object. */ - final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() } + final Instruction getArrayObjectAddress() { + result = this.getArrayObjectAddressOperand().getDef() + } } /** @@ -685,7 +694,7 @@ class ElementsAddressInstruction extends UnaryInstruction { * taken may want to ignore any function that contains an `ErrorInstruction`. */ class ErrorInstruction extends Instruction { - ErrorInstruction() { getOpcode() instanceof Opcode::Error } + ErrorInstruction() { this.getOpcode() instanceof Opcode::Error } } /** @@ -695,7 +704,7 @@ class ErrorInstruction extends Instruction { * an initializer, or whose initializer only partially initializes the variable. */ class UninitializedInstruction extends VariableInstruction { - UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized } + UninitializedInstruction() { this.getOpcode() instanceof Opcode::Uninitialized } /** * Gets the variable that is uninitialized. @@ -710,7 +719,7 @@ class UninitializedInstruction extends VariableInstruction { * least one instruction, even when the AST has no semantic effect. */ class NoOpInstruction extends Instruction { - NoOpInstruction() { getOpcode() instanceof Opcode::NoOp } + NoOpInstruction() { this.getOpcode() instanceof Opcode::NoOp } } /** @@ -732,32 +741,32 @@ class NoOpInstruction extends Instruction { * `void`-returning function. */ class ReturnInstruction extends Instruction { - ReturnInstruction() { getOpcode() instanceof ReturnOpcode } + ReturnInstruction() { this.getOpcode() instanceof ReturnOpcode } } /** * An instruction that returns control to the caller of the function, without returning a value. */ class ReturnVoidInstruction extends ReturnInstruction { - ReturnVoidInstruction() { getOpcode() instanceof Opcode::ReturnVoid } + ReturnVoidInstruction() { this.getOpcode() instanceof Opcode::ReturnVoid } } /** * An instruction that returns control to the caller of the function, including a return value. */ class ReturnValueInstruction extends ReturnInstruction { - ReturnValueInstruction() { getOpcode() instanceof Opcode::ReturnValue } + ReturnValueInstruction() { this.getOpcode() instanceof Opcode::ReturnValue } /** * Gets the operand that provides the value being returned by the function. */ - final LoadOperand getReturnValueOperand() { result = getAnOperand() } + final LoadOperand getReturnValueOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value being returned by the function, if an * exact definition is available. */ - final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } + final Instruction getReturnValue() { result = this.getReturnValueOperand().getDef() } } /** @@ -770,28 +779,28 @@ class ReturnValueInstruction extends ReturnInstruction { * that the caller initialized the memory pointed to by the parameter before the call. */ class ReturnIndirectionInstruction extends VariableInstruction { - ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + ReturnIndirectionInstruction() { this.getOpcode() instanceof Opcode::ReturnIndirection } /** * Gets the operand that provides the value of the pointed-to memory. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the pointed-to memory, if an exact * definition is available. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** * Gets the operand that provides the address of the pointed-to memory. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the pointed-to memory. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } /** * Gets the parameter for which this instruction reads the final pointed-to value within the @@ -826,7 +835,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * - `StoreInstruction` - Copies a register operand to a memory result. */ class CopyInstruction extends Instruction { - CopyInstruction() { getOpcode() instanceof CopyOpcode } + CopyInstruction() { this.getOpcode() instanceof CopyOpcode } /** * Gets the operand that provides the input value of the copy. @@ -837,16 +846,16 @@ class CopyInstruction extends Instruction { * Gets the instruction whose result provides the input value of the copy, if an exact definition * is available. */ - final Instruction getSourceValue() { result = getSourceValueOperand().getDef() } + final Instruction getSourceValue() { result = this.getSourceValueOperand().getDef() } } /** * An instruction that returns a register result containing a copy of its register operand. */ class CopyValueInstruction extends CopyInstruction, UnaryInstruction { - CopyValueInstruction() { getOpcode() instanceof Opcode::CopyValue } + CopyValueInstruction() { this.getOpcode() instanceof Opcode::CopyValue } - final override UnaryOperand getSourceValueOperand() { result = getAnOperand() } + final override UnaryOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -863,47 +872,49 @@ private string getAddressOperandDescription(AddressOperand operand) { * An instruction that returns a register result containing a copy of its memory operand. */ class LoadInstruction extends CopyInstruction { - LoadInstruction() { getOpcode() instanceof Opcode::Load } + LoadInstruction() { this.getOpcode() instanceof Opcode::Load } final override string getImmediateString() { - result = getAddressOperandDescription(getSourceAddressOperand()) + result = getAddressOperandDescription(this.getSourceAddressOperand()) } /** * Gets the operand that provides the address of the value being loaded. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the value being loaded. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } - final override LoadOperand getSourceValueOperand() { result = getAnOperand() } + final override LoadOperand getSourceValueOperand() { result = this.getAnOperand() } } /** * An instruction that returns a memory result containing a copy of its register operand. */ class StoreInstruction extends CopyInstruction { - StoreInstruction() { getOpcode() instanceof Opcode::Store } + StoreInstruction() { this.getOpcode() instanceof Opcode::Store } final override string getImmediateString() { - result = getAddressOperandDescription(getDestinationAddressOperand()) + result = getAddressOperandDescription(this.getDestinationAddressOperand()) } /** * Gets the operand that provides the address of the location to which the value will be stored. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the location to which the value will * be stored, if an exact definition is available. */ - final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + final Instruction getDestinationAddress() { + result = this.getDestinationAddressOperand().getDef() + } - final override StoreValueOperand getSourceValueOperand() { result = getAnOperand() } + final override StoreValueOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -911,27 +922,27 @@ class StoreInstruction extends CopyInstruction { * operand. */ class ConditionalBranchInstruction extends Instruction { - ConditionalBranchInstruction() { getOpcode() instanceof Opcode::ConditionalBranch } + ConditionalBranchInstruction() { this.getOpcode() instanceof Opcode::ConditionalBranch } /** * Gets the operand that provides the Boolean condition controlling the branch. */ - final ConditionOperand getConditionOperand() { result = getAnOperand() } + final ConditionOperand getConditionOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the Boolean condition controlling the branch. */ - final Instruction getCondition() { result = getConditionOperand().getDef() } + final Instruction getCondition() { result = this.getConditionOperand().getDef() } /** * Gets the instruction to which control will flow if the condition is true. */ - final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) } + final Instruction getTrueSuccessor() { result = this.getSuccessor(EdgeKind::trueEdge()) } /** * Gets the instruction to which control will flow if the condition is false. */ - final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) } + final Instruction getFalseSuccessor() { result = this.getSuccessor(EdgeKind::falseEdge()) } } /** @@ -943,14 +954,14 @@ class ConditionalBranchInstruction extends Instruction { * successors. */ class ExitFunctionInstruction extends Instruction { - ExitFunctionInstruction() { getOpcode() instanceof Opcode::ExitFunction } + ExitFunctionInstruction() { this.getOpcode() instanceof Opcode::ExitFunction } } /** * An instruction whose result is a constant value. */ class ConstantInstruction extends ConstantValueInstruction { - ConstantInstruction() { getOpcode() instanceof Opcode::Constant } + ConstantInstruction() { this.getOpcode() instanceof Opcode::Constant } } /** @@ -959,7 +970,7 @@ class ConstantInstruction extends ConstantValueInstruction { class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { exists(IRType resultType | - resultType = getResultIRType() and + resultType = this.getResultIRType() and (resultType instanceof IRIntegerType or resultType instanceof IRBooleanType) ) } @@ -969,7 +980,7 @@ class IntegerConstantInstruction extends ConstantInstruction { * An instruction whose result is a constant value of floating-point type. */ class FloatConstantInstruction extends ConstantInstruction { - FloatConstantInstruction() { getResultIRType() instanceof IRFloatingPointType } + FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType } } /** @@ -978,7 +989,9 @@ class FloatConstantInstruction extends ConstantInstruction { class StringConstantInstruction extends VariableInstruction { override IRStringLiteral var; - final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } + final override string getImmediateString() { + result = Language::getStringLiteralText(this.getValue()) + } /** * Gets the string literal whose address is returned by this instruction. @@ -990,37 +1003,37 @@ class StringConstantInstruction extends VariableInstruction { * An instruction whose result is computed from two operands. */ class BinaryInstruction extends Instruction { - BinaryInstruction() { getOpcode() instanceof BinaryOpcode } + BinaryInstruction() { this.getOpcode() instanceof BinaryOpcode } /** * Gets the left operand of this binary instruction. */ - final LeftOperand getLeftOperand() { result = getAnOperand() } + final LeftOperand getLeftOperand() { result = this.getAnOperand() } /** * Gets the right operand of this binary instruction. */ - final RightOperand getRightOperand() { result = getAnOperand() } + final RightOperand getRightOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the left operand of this binary * instruction. */ - final Instruction getLeft() { result = getLeftOperand().getDef() } + final Instruction getLeft() { result = this.getLeftOperand().getDef() } /** * Gets the instruction whose result provides the value of the right operand of this binary * instruction. */ - final Instruction getRight() { result = getRightOperand().getDef() } + final Instruction getRight() { result = this.getRightOperand().getDef() } /** * Holds if this instruction's operands are `op1` and `op2`, in either order. */ final predicate hasOperands(Operand op1, Operand op2) { - op1 = getLeftOperand() and op2 = getRightOperand() + op1 = this.getLeftOperand() and op2 = this.getRightOperand() or - op1 = getRightOperand() and op2 = getLeftOperand() + op1 = this.getRightOperand() and op2 = this.getLeftOperand() } } @@ -1028,7 +1041,7 @@ class BinaryInstruction extends Instruction { * An instruction that computes the result of an arithmetic operation. */ class ArithmeticInstruction extends Instruction { - ArithmeticInstruction() { getOpcode() instanceof ArithmeticOpcode } + ArithmeticInstruction() { this.getOpcode() instanceof ArithmeticOpcode } } /** @@ -1050,7 +1063,7 @@ class UnaryArithmeticInstruction extends ArithmeticInstruction, UnaryInstruction * performed according to IEEE-754. */ class AddInstruction extends BinaryArithmeticInstruction { - AddInstruction() { getOpcode() instanceof Opcode::Add } + AddInstruction() { this.getOpcode() instanceof Opcode::Add } } /** @@ -1061,7 +1074,7 @@ class AddInstruction extends BinaryArithmeticInstruction { * according to IEEE-754. */ class SubInstruction extends BinaryArithmeticInstruction { - SubInstruction() { getOpcode() instanceof Opcode::Sub } + SubInstruction() { this.getOpcode() instanceof Opcode::Sub } } /** @@ -1072,7 +1085,7 @@ class SubInstruction extends BinaryArithmeticInstruction { * performed according to IEEE-754. */ class MulInstruction extends BinaryArithmeticInstruction { - MulInstruction() { getOpcode() instanceof Opcode::Mul } + MulInstruction() { this.getOpcode() instanceof Opcode::Mul } } /** @@ -1083,7 +1096,7 @@ class MulInstruction extends BinaryArithmeticInstruction { * to IEEE-754. */ class DivInstruction extends BinaryArithmeticInstruction { - DivInstruction() { getOpcode() instanceof Opcode::Div } + DivInstruction() { this.getOpcode() instanceof Opcode::Div } } /** @@ -1093,7 +1106,7 @@ class DivInstruction extends BinaryArithmeticInstruction { * division by zero or integer overflow is undefined. */ class RemInstruction extends BinaryArithmeticInstruction { - RemInstruction() { getOpcode() instanceof Opcode::Rem } + RemInstruction() { this.getOpcode() instanceof Opcode::Rem } } /** @@ -1104,14 +1117,14 @@ class RemInstruction extends BinaryArithmeticInstruction { * is performed according to IEEE-754. */ class NegateInstruction extends UnaryArithmeticInstruction { - NegateInstruction() { getOpcode() instanceof Opcode::Negate } + NegateInstruction() { this.getOpcode() instanceof Opcode::Negate } } /** * An instruction that computes the result of a bitwise operation. */ class BitwiseInstruction extends Instruction { - BitwiseInstruction() { getOpcode() instanceof BitwiseOpcode } + BitwiseInstruction() { this.getOpcode() instanceof BitwiseOpcode } } /** @@ -1130,7 +1143,7 @@ class UnaryBitwiseInstruction extends BitwiseInstruction, UnaryInstruction { } * Both operands must have the same integer type, which will also be the result type. */ class BitAndInstruction extends BinaryBitwiseInstruction { - BitAndInstruction() { getOpcode() instanceof Opcode::BitAnd } + BitAndInstruction() { this.getOpcode() instanceof Opcode::BitAnd } } /** @@ -1139,7 +1152,7 @@ class BitAndInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitOrInstruction extends BinaryBitwiseInstruction { - BitOrInstruction() { getOpcode() instanceof Opcode::BitOr } + BitOrInstruction() { this.getOpcode() instanceof Opcode::BitOr } } /** @@ -1148,7 +1161,7 @@ class BitOrInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitXorInstruction extends BinaryBitwiseInstruction { - BitXorInstruction() { getOpcode() instanceof Opcode::BitXor } + BitXorInstruction() { this.getOpcode() instanceof Opcode::BitXor } } /** @@ -1159,7 +1172,7 @@ class BitXorInstruction extends BinaryBitwiseInstruction { * rightmost bits are zero-filled. */ class ShiftLeftInstruction extends BinaryBitwiseInstruction { - ShiftLeftInstruction() { getOpcode() instanceof Opcode::ShiftLeft } + ShiftLeftInstruction() { this.getOpcode() instanceof Opcode::ShiftLeft } } /** @@ -1172,7 +1185,7 @@ class ShiftLeftInstruction extends BinaryBitwiseInstruction { * of the left operand. */ class ShiftRightInstruction extends BinaryBitwiseInstruction { - ShiftRightInstruction() { getOpcode() instanceof Opcode::ShiftRight } + ShiftRightInstruction() { this.getOpcode() instanceof Opcode::ShiftRight } } /** @@ -1183,7 +1196,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { int elementSize; PointerArithmeticInstruction() { - getOpcode() instanceof PointerArithmeticOpcode and + this.getOpcode() instanceof PointerArithmeticOpcode and elementSize = Raw::getInstructionElementSize(this) } @@ -1206,7 +1219,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { * An instruction that adds or subtracts an integer offset from a pointer. */ class PointerOffsetInstruction extends PointerArithmeticInstruction { - PointerOffsetInstruction() { getOpcode() instanceof PointerOffsetOpcode } + PointerOffsetInstruction() { this.getOpcode() instanceof PointerOffsetOpcode } } /** @@ -1217,7 +1230,7 @@ class PointerOffsetInstruction extends PointerArithmeticInstruction { * overflow is undefined. */ class PointerAddInstruction extends PointerOffsetInstruction { - PointerAddInstruction() { getOpcode() instanceof Opcode::PointerAdd } + PointerAddInstruction() { this.getOpcode() instanceof Opcode::PointerAdd } } /** @@ -1228,7 +1241,7 @@ class PointerAddInstruction extends PointerOffsetInstruction { * pointer underflow is undefined. */ class PointerSubInstruction extends PointerOffsetInstruction { - PointerSubInstruction() { getOpcode() instanceof Opcode::PointerSub } + PointerSubInstruction() { this.getOpcode() instanceof Opcode::PointerSub } } /** @@ -1241,31 +1254,31 @@ class PointerSubInstruction extends PointerOffsetInstruction { * undefined. */ class PointerDiffInstruction extends PointerArithmeticInstruction { - PointerDiffInstruction() { getOpcode() instanceof Opcode::PointerDiff } + PointerDiffInstruction() { this.getOpcode() instanceof Opcode::PointerDiff } } /** * An instruction whose result is computed from a single operand. */ class UnaryInstruction extends Instruction { - UnaryInstruction() { getOpcode() instanceof UnaryOpcode } + UnaryInstruction() { this.getOpcode() instanceof UnaryOpcode } /** * Gets the sole operand of this instruction. */ - final UnaryOperand getUnaryOperand() { result = getAnOperand() } + final UnaryOperand getUnaryOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the sole operand of this instruction. */ - final Instruction getUnary() { result = getUnaryOperand().getDef() } + final Instruction getUnary() { result = this.getUnaryOperand().getDef() } } /** * An instruction that converts the value of its operand to a value of a different type. */ class ConvertInstruction extends UnaryInstruction { - ConvertInstruction() { getOpcode() instanceof Opcode::Convert } + ConvertInstruction() { this.getOpcode() instanceof Opcode::Convert } } /** @@ -1279,7 +1292,7 @@ class ConvertInstruction extends UnaryInstruction { * `as` expression. */ class CheckedConvertOrNullInstruction extends UnaryInstruction { - CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull } + CheckedConvertOrNullInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrNull } } /** @@ -1293,7 +1306,7 @@ class CheckedConvertOrNullInstruction extends UnaryInstruction { * expression. */ class CheckedConvertOrThrowInstruction extends UnaryInstruction { - CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow } + CheckedConvertOrThrowInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrThrow } } /** @@ -1306,7 +1319,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction { * the most-derived object. */ class CompleteObjectAddressInstruction extends UnaryInstruction { - CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress } + CompleteObjectAddressInstruction() { this.getOpcode() instanceof Opcode::CompleteObjectAddress } } /** @@ -1351,7 +1364,7 @@ class InheritanceConversionInstruction extends UnaryInstruction { * An instruction that converts from the address of a derived class to the address of a base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } + ConvertToBaseInstruction() { this.getOpcode() instanceof ConvertToBaseOpcode } } /** @@ -1361,7 +1374,9 @@ class ConvertToBaseInstruction extends InheritanceConversionInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } + ConvertToNonVirtualBaseInstruction() { + this.getOpcode() instanceof Opcode::ConvertToNonVirtualBase + } } /** @@ -1371,7 +1386,7 @@ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } + ConvertToVirtualBaseInstruction() { this.getOpcode() instanceof Opcode::ConvertToVirtualBase } } /** @@ -1381,7 +1396,7 @@ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { - ConvertToDerivedInstruction() { getOpcode() instanceof Opcode::ConvertToDerived } + ConvertToDerivedInstruction() { this.getOpcode() instanceof Opcode::ConvertToDerived } } /** @@ -1390,7 +1405,7 @@ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { * The operand must have an integer type, which will also be the result type. */ class BitComplementInstruction extends UnaryBitwiseInstruction { - BitComplementInstruction() { getOpcode() instanceof Opcode::BitComplement } + BitComplementInstruction() { this.getOpcode() instanceof Opcode::BitComplement } } /** @@ -1399,14 +1414,14 @@ class BitComplementInstruction extends UnaryBitwiseInstruction { * The operand must have a Boolean type, which will also be the result type. */ class LogicalNotInstruction extends UnaryInstruction { - LogicalNotInstruction() { getOpcode() instanceof Opcode::LogicalNot } + LogicalNotInstruction() { this.getOpcode() instanceof Opcode::LogicalNot } } /** * An instruction that compares two numeric operands. */ class CompareInstruction extends BinaryInstruction { - CompareInstruction() { getOpcode() instanceof CompareOpcode } + CompareInstruction() { this.getOpcode() instanceof CompareOpcode } } /** @@ -1417,7 +1432,7 @@ class CompareInstruction extends BinaryInstruction { * unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareEQInstruction extends CompareInstruction { - CompareEQInstruction() { getOpcode() instanceof Opcode::CompareEQ } + CompareEQInstruction() { this.getOpcode() instanceof Opcode::CompareEQ } } /** @@ -1428,14 +1443,14 @@ class CompareEQInstruction extends CompareInstruction { * `left == right`. Floating-point comparison is performed according to IEEE-754. */ class CompareNEInstruction extends CompareInstruction { - CompareNEInstruction() { getOpcode() instanceof Opcode::CompareNE } + CompareNEInstruction() { this.getOpcode() instanceof Opcode::CompareNE } } /** * An instruction that does a relative comparison of two values, such as `<` or `>=`. */ class RelationalInstruction extends CompareInstruction { - RelationalInstruction() { getOpcode() instanceof RelationalOpcode } + RelationalInstruction() { this.getOpcode() instanceof RelationalOpcode } /** * Gets the operand on the "greater" (or "greater-or-equal") side @@ -1467,11 +1482,11 @@ class RelationalInstruction extends CompareInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLTInstruction extends RelationalInstruction { - CompareLTInstruction() { getOpcode() instanceof Opcode::CompareLT } + CompareLTInstruction() { this.getOpcode() instanceof Opcode::CompareLT } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { any() } } @@ -1484,11 +1499,11 @@ class CompareLTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGTInstruction extends RelationalInstruction { - CompareGTInstruction() { getOpcode() instanceof Opcode::CompareGT } + CompareGTInstruction() { this.getOpcode() instanceof Opcode::CompareGT } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { any() } } @@ -1502,11 +1517,11 @@ class CompareGTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLEInstruction extends RelationalInstruction { - CompareLEInstruction() { getOpcode() instanceof Opcode::CompareLE } + CompareLEInstruction() { this.getOpcode() instanceof Opcode::CompareLE } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { none() } } @@ -1520,11 +1535,11 @@ class CompareLEInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGEInstruction extends RelationalInstruction { - CompareGEInstruction() { getOpcode() instanceof Opcode::CompareGE } + CompareGEInstruction() { this.getOpcode() instanceof Opcode::CompareGE } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { none() } } @@ -1543,78 +1558,78 @@ class CompareGEInstruction extends RelationalInstruction { * of any case edge. */ class SwitchInstruction extends Instruction { - SwitchInstruction() { getOpcode() instanceof Opcode::Switch } + SwitchInstruction() { this.getOpcode() instanceof Opcode::Switch } /** Gets the operand that provides the integer value controlling the switch. */ - final ConditionOperand getExpressionOperand() { result = getAnOperand() } + final ConditionOperand getExpressionOperand() { result = this.getAnOperand() } /** Gets the instruction whose result provides the integer value controlling the switch. */ - final Instruction getExpression() { result = getExpressionOperand().getDef() } + final Instruction getExpression() { result = this.getExpressionOperand().getDef() } /** Gets the successor instructions along the case edges of the switch. */ - final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) } + final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = this.getSuccessor(edge)) } /** Gets the successor instruction along the default edge of the switch, if any. */ - final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) } + final Instruction getDefaultSuccessor() { result = this.getSuccessor(EdgeKind::defaultEdge()) } } /** * An instruction that calls a function. */ class CallInstruction extends Instruction { - CallInstruction() { getOpcode() instanceof Opcode::Call } + CallInstruction() { this.getOpcode() instanceof Opcode::Call } final override string getImmediateString() { - result = getStaticCallTarget().toString() + result = this.getStaticCallTarget().toString() or - not exists(getStaticCallTarget()) and result = "?" + not exists(this.getStaticCallTarget()) and result = "?" } /** * Gets the operand the specifies the target function of the call. */ - final CallTargetOperand getCallTargetOperand() { result = getAnOperand() } + final CallTargetOperand getCallTargetOperand() { result = this.getAnOperand() } /** * Gets the `Instruction` that computes the target function of the call. This is usually a * `FunctionAddress` instruction, but can also be an arbitrary instruction that produces a * function pointer. */ - final Instruction getCallTarget() { result = getCallTargetOperand().getDef() } + final Instruction getCallTarget() { result = this.getCallTargetOperand().getDef() } /** * Gets all of the argument operands of the call, including the `this` pointer, if any. */ - final ArgumentOperand getAnArgumentOperand() { result = getAnOperand() } + final ArgumentOperand getAnArgumentOperand() { result = this.getAnOperand() } /** * Gets the `Function` that the call targets, if this is statically known. */ final Language::Function getStaticCallTarget() { - result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() + result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() } /** * Gets all of the arguments of the call, including the `this` pointer, if any. */ - final Instruction getAnArgument() { result = getAnArgumentOperand().getDef() } + final Instruction getAnArgument() { result = this.getAnArgumentOperand().getDef() } /** * Gets the `this` pointer argument operand of the call, if any. */ - final ThisArgumentOperand getThisArgumentOperand() { result = getAnOperand() } + final ThisArgumentOperand getThisArgumentOperand() { result = this.getAnOperand() } /** * Gets the `this` pointer argument of the call, if any. */ - final Instruction getThisArgument() { result = getThisArgumentOperand().getDef() } + final Instruction getThisArgument() { result = this.getThisArgumentOperand().getDef() } /** * Gets the argument operand at the specified index. */ pragma[noinline] final PositionalArgumentOperand getPositionalArgumentOperand(int index) { - result = getAnOperand() and + result = this.getAnOperand() and result.getIndex() = index } @@ -1623,7 +1638,7 @@ class CallInstruction extends Instruction { */ pragma[noinline] final Instruction getPositionalArgument(int index) { - result = getPositionalArgumentOperand(index).getDef() + result = this.getPositionalArgumentOperand(index).getDef() } /** @@ -1631,16 +1646,16 @@ class CallInstruction extends Instruction { */ pragma[noinline] final ArgumentOperand getArgumentOperand(int index) { - index >= 0 and result = getPositionalArgumentOperand(index) + index >= 0 and result = this.getPositionalArgumentOperand(index) or - index = -1 and result = getThisArgumentOperand() + index = -1 and result = this.getThisArgumentOperand() } /** * Gets the argument at the specified index, or `this` if `index` is `-1`. */ pragma[noinline] - final Instruction getArgument(int index) { result = getArgumentOperand(index).getDef() } + final Instruction getArgument(int index) { result = this.getArgumentOperand(index).getDef() } /** * Gets the number of arguments of the call, including the `this` pointer, if any. @@ -1665,7 +1680,7 @@ class CallInstruction extends Instruction { * An instruction representing a side effect of a function call. */ class SideEffectInstruction extends Instruction { - SideEffectInstruction() { getOpcode() instanceof SideEffectOpcode } + SideEffectInstruction() { this.getOpcode() instanceof SideEffectOpcode } /** * Gets the instruction whose execution causes this side effect. @@ -1680,7 +1695,7 @@ class SideEffectInstruction extends Instruction { * accessed by that call. */ class CallSideEffectInstruction extends SideEffectInstruction { - CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect } + CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } } /** @@ -1691,7 +1706,7 @@ class CallSideEffectInstruction extends SideEffectInstruction { * call target cannot write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { - CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } + CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } } /** @@ -1699,33 +1714,33 @@ class CallReadSideEffectInstruction extends SideEffectInstruction { * specific parameter. */ class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + ReadSideEffectInstruction() { this.getOpcode() instanceof ReadSideEffectOpcode } /** Gets the operand for the value that will be read from this instruction, if known. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** Gets the value that will be read from this instruction, if known. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** Gets the operand for the address from which this instruction may read. */ - final AddressOperand getArgumentOperand() { result = getAnOperand() } + final AddressOperand getArgumentOperand() { result = this.getAnOperand() } /** Gets the address from which this instruction may read. */ - final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } + final Instruction getArgumentDef() { result = this.getArgumentOperand().getDef() } } /** * An instruction representing the read of an indirect parameter within a function call. */ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { - IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } + IndirectReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::IndirectReadSideEffect } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } + BufferReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::BufferReadSideEffect } } /** @@ -1733,18 +1748,18 @@ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferReadSideEffect + this.getOpcode() instanceof Opcode::SizedBufferReadSideEffect } /** * Gets the operand that holds the number of bytes read from the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes read from the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1752,17 +1767,17 @@ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } + WriteSideEffectInstruction() { this.getOpcode() instanceof WriteSideEffectOpcode } /** * Get the operand that holds the address of the memory to be written. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the memory to be written. */ - Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + Instruction getDestinationAddress() { result = this.getDestinationAddressOperand().getDef() } } /** @@ -1770,7 +1785,7 @@ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstructi */ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMustWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMustWriteSideEffect } } @@ -1780,7 +1795,7 @@ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction */ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { BufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::BufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::BufferMustWriteSideEffect } } @@ -1790,18 +1805,18 @@ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1812,7 +1827,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi */ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMayWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMayWriteSideEffect } } @@ -1822,7 +1837,9 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { * Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten. */ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { - BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect } + BufferMayWriteSideEffectInstruction() { + this.getOpcode() instanceof Opcode::BufferMayWriteSideEffect + } } /** @@ -1832,18 +1849,18 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1852,80 +1869,80 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio */ class InitializeDynamicAllocationInstruction extends SideEffectInstruction { InitializeDynamicAllocationInstruction() { - getOpcode() instanceof Opcode::InitializeDynamicAllocation + this.getOpcode() instanceof Opcode::InitializeDynamicAllocation } /** * Gets the operand that represents the address of the allocation this instruction is initializing. */ - final AddressOperand getAllocationAddressOperand() { result = getAnOperand() } + final AddressOperand getAllocationAddressOperand() { result = this.getAnOperand() } /** * Gets the address for the allocation this instruction is initializing. */ - final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() } + final Instruction getAllocationAddress() { result = this.getAllocationAddressOperand().getDef() } } /** * An instruction representing a GNU or MSVC inline assembly statement. */ class InlineAsmInstruction extends Instruction { - InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm } + InlineAsmInstruction() { this.getOpcode() instanceof Opcode::InlineAsm } } /** * An instruction that throws an exception. */ class ThrowInstruction extends Instruction { - ThrowInstruction() { getOpcode() instanceof ThrowOpcode } + ThrowInstruction() { this.getOpcode() instanceof ThrowOpcode } } /** * An instruction that throws a new exception. */ class ThrowValueInstruction extends ThrowInstruction { - ThrowValueInstruction() { getOpcode() instanceof Opcode::ThrowValue } + ThrowValueInstruction() { this.getOpcode() instanceof Opcode::ThrowValue } /** * Gets the address operand of the exception thrown by this instruction. */ - final AddressOperand getExceptionAddressOperand() { result = getAnOperand() } + final AddressOperand getExceptionAddressOperand() { result = this.getAnOperand() } /** * Gets the address of the exception thrown by this instruction. */ - final Instruction getExceptionAddress() { result = getExceptionAddressOperand().getDef() } + final Instruction getExceptionAddress() { result = this.getExceptionAddressOperand().getDef() } /** * Gets the operand for the exception thrown by this instruction. */ - final LoadOperand getExceptionOperand() { result = getAnOperand() } + final LoadOperand getExceptionOperand() { result = this.getAnOperand() } /** * Gets the exception thrown by this instruction. */ - final Instruction getException() { result = getExceptionOperand().getDef() } + final Instruction getException() { result = this.getExceptionOperand().getDef() } } /** * An instruction that re-throws the current exception. */ class ReThrowInstruction extends ThrowInstruction { - ReThrowInstruction() { getOpcode() instanceof Opcode::ReThrow } + ReThrowInstruction() { this.getOpcode() instanceof Opcode::ReThrow } } /** * An instruction that exits the current function by propagating an exception. */ class UnwindInstruction extends Instruction { - UnwindInstruction() { getOpcode() instanceof Opcode::Unwind } + UnwindInstruction() { this.getOpcode() instanceof Opcode::Unwind } } /** * An instruction that starts a `catch` handler. */ class CatchInstruction extends Instruction { - CatchInstruction() { getOpcode() instanceof CatchOpcode } + CatchInstruction() { this.getOpcode() instanceof CatchOpcode } } /** @@ -1935,7 +1952,7 @@ class CatchByTypeInstruction extends CatchInstruction { Language::LanguageType exceptionType; CatchByTypeInstruction() { - getOpcode() instanceof Opcode::CatchByType and + this.getOpcode() instanceof Opcode::CatchByType and exceptionType = Raw::getInstructionExceptionType(this) } @@ -1951,21 +1968,21 @@ class CatchByTypeInstruction extends CatchInstruction { * An instruction that catches any exception. */ class CatchAnyInstruction extends CatchInstruction { - CatchAnyInstruction() { getOpcode() instanceof Opcode::CatchAny } + CatchAnyInstruction() { this.getOpcode() instanceof Opcode::CatchAny } } /** * An instruction that initializes all escaped memory. */ class AliasedDefinitionInstruction extends Instruction { - AliasedDefinitionInstruction() { getOpcode() instanceof Opcode::AliasedDefinition } + AliasedDefinitionInstruction() { this.getOpcode() instanceof Opcode::AliasedDefinition } } /** * An instruction that consumes all escaped memory on exit from the function. */ class AliasedUseInstruction extends Instruction { - AliasedUseInstruction() { getOpcode() instanceof Opcode::AliasedUse } + AliasedUseInstruction() { this.getOpcode() instanceof Opcode::AliasedUse } } /** @@ -1979,7 +1996,7 @@ class AliasedUseInstruction extends Instruction { * runtime. */ class PhiInstruction extends Instruction { - PhiInstruction() { getOpcode() instanceof Opcode::Phi } + PhiInstruction() { this.getOpcode() instanceof Opcode::Phi } /** * Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block. @@ -2047,29 +2064,29 @@ class PhiInstruction extends Instruction { * https://link.springer.com/content/pdf/10.1007%2F3-540-61053-7_66.pdf. */ class ChiInstruction extends Instruction { - ChiInstruction() { getOpcode() instanceof Opcode::Chi } + ChiInstruction() { this.getOpcode() instanceof Opcode::Chi } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final ChiTotalOperand getTotalOperand() { result = getAnOperand() } + final ChiTotalOperand getTotalOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final Instruction getTotal() { result = getTotalOperand().getDef() } + final Instruction getTotal() { result = this.getTotalOperand().getDef() } /** * Gets the operand that represents the new value written by the memory write. */ - final ChiPartialOperand getPartialOperand() { result = getAnOperand() } + final ChiPartialOperand getPartialOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the new value written by the memory write. */ - final Instruction getPartial() { result = getPartialOperand().getDef() } + final Instruction getPartial() { result = this.getPartialOperand().getDef() } /** * Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand. @@ -2093,7 +2110,7 @@ class ChiInstruction extends Instruction { * or `Switch` instruction where that particular edge is infeasible. */ class UnreachedInstruction extends Instruction { - UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached } + UnreachedInstruction() { this.getOpcode() instanceof Opcode::Unreached } } /** @@ -2106,7 +2123,7 @@ class BuiltInOperationInstruction extends Instruction { Language::BuiltInOperation operation; BuiltInOperationInstruction() { - getOpcode() instanceof BuiltInOperationOpcode and + this.getOpcode() instanceof BuiltInOperationOpcode and operation = Raw::getInstructionBuiltInOperation(this) } @@ -2122,9 +2139,9 @@ class BuiltInOperationInstruction extends Instruction { * actual operation is specified by the `getBuiltInOperation()` predicate. */ class BuiltInInstruction extends BuiltInOperationInstruction { - BuiltInInstruction() { getOpcode() instanceof Opcode::BuiltIn } + BuiltInInstruction() { this.getOpcode() instanceof Opcode::BuiltIn } - final override string getImmediateString() { result = getBuiltInOperation().toString() } + final override string getImmediateString() { result = this.getBuiltInOperation().toString() } } /** @@ -2135,7 +2152,7 @@ class BuiltInInstruction extends BuiltInOperationInstruction { * to the `...` parameter. */ class VarArgsStartInstruction extends UnaryInstruction { - VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart } + VarArgsStartInstruction() { this.getOpcode() instanceof Opcode::VarArgsStart } } /** @@ -2145,7 +2162,7 @@ class VarArgsStartInstruction extends UnaryInstruction { * a result. */ class VarArgsEndInstruction extends UnaryInstruction { - VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd } + VarArgsEndInstruction() { this.getOpcode() instanceof Opcode::VarArgsEnd } } /** @@ -2155,7 +2172,7 @@ class VarArgsEndInstruction extends UnaryInstruction { * argument. */ class VarArgInstruction extends UnaryInstruction { - VarArgInstruction() { getOpcode() instanceof Opcode::VarArg } + VarArgInstruction() { this.getOpcode() instanceof Opcode::VarArg } } /** @@ -2166,7 +2183,7 @@ class VarArgInstruction extends UnaryInstruction { * argument of the `...` parameter. */ class NextVarArgInstruction extends UnaryInstruction { - NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg } + NextVarArgInstruction() { this.getOpcode() instanceof Opcode::NextVarArg } } /** @@ -2180,5 +2197,5 @@ class NextVarArgInstruction extends UnaryInstruction { * The result is the address of the newly allocated object. */ class NewObjInstruction extends Instruction { - NewObjInstruction() { getOpcode() instanceof Opcode::NewObj } + NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll index d7cf89ca9aa..85d217bd361 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -46,12 +46,12 @@ class Operand extends TStageOperand { /** * Gets the location of the source code for this operand. */ - final Language::Location getLocation() { result = getUse().getLocation() } + final Language::Location getLocation() { result = this.getUse().getLocation() } /** * Gets the function that contains this operand. */ - final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() } + final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() } /** * Gets the `Instruction` that consumes this operand. @@ -74,7 +74,7 @@ class Operand extends TStageOperand { */ final Instruction getDef() { result = this.getAnyDef() and - getDefinitionOverlap() instanceof MustExactlyOverlap + this.getDefinitionOverlap() instanceof MustExactlyOverlap } /** @@ -82,7 +82,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` that consumes this operand. */ - deprecated final Instruction getUseInstruction() { result = getUse() } + deprecated final Instruction getUseInstruction() { result = this.getUse() } /** * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this @@ -91,7 +91,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` whose result is the value of the operand. */ - deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() } + deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } /** * Gets the overlap relationship between the operand's definition and its use. @@ -101,7 +101,9 @@ class Operand extends TStageOperand { /** * Holds if the result of the definition instruction does not exactly overlap this use. */ - final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap } + final predicate isDefinitionInexact() { + not this.getDefinitionOverlap() instanceof MustExactlyOverlap + } /** * Gets a prefix to use when dumping the operand in an operand list. @@ -121,7 +123,7 @@ class Operand extends TStageOperand { * For example: `this:r3_5` */ final string getDumpString() { - result = getDumpLabel() + getInexactSpecifier() + getDefinitionId() + result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId() } /** @@ -129,9 +131,9 @@ class Operand extends TStageOperand { * definition is not modeled in SSA. */ private string getDefinitionId() { - result = getAnyDef().getResultId() + result = this.getAnyDef().getResultId() or - not exists(getAnyDef()) and result = "m?" + not exists(this.getAnyDef()) and result = "m?" } /** @@ -140,7 +142,7 @@ class Operand extends TStageOperand { * the empty string. */ private string getInexactSpecifier() { - if isDefinitionInexact() then result = "~" else result = "" + if this.isDefinitionInexact() then result = "~" else result = "" } /** @@ -155,7 +157,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() } + Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() } /** * Gets the language-neutral type of the value consumed by this operand. This is usually the same @@ -164,7 +166,7 @@ class Operand extends TStageOperand { * from the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final IRType getIRType() { result = getLanguageType().getIRType() } + final IRType getIRType() { result = this.getLanguageType().getIRType() } /** * Gets the type of the value consumed by this operand. This is usually the same as the @@ -173,7 +175,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final Language::Type getType() { getLanguageType().hasType(result, _) } + final Language::Type getType() { this.getLanguageType().hasType(result, _) } /** * Holds if the value consumed by this operand is a glvalue. If this @@ -182,13 +184,13 @@ class Operand extends TStageOperand { * not hold, the value of the operand represents a value whose type is * given by `getType()`. */ - final predicate isGLValue() { getLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getLanguageType().hasType(_, true) } /** * Gets the size of the value consumed by this operand, in bytes. If the operand does not have * a known constant size, this predicate does not hold. */ - final int getSize() { result = getLanguageType().getByteSize() } + final int getSize() { result = this.getLanguageType().getByteSize() } } /** @@ -205,7 +207,7 @@ class MemoryOperand extends Operand { /** * Gets the kind of memory access performed by the operand. */ - MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() } + MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() } /** * Holds if the memory access performed by this operand will not always read from every bit in the @@ -215,7 +217,7 @@ class MemoryOperand extends Operand { * conservative estimate of the memory that might actually be accessed at runtime (for example, * the global side effects of a function call). */ - predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() } + predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() } /** * Returns the operand that holds the memory address from which the current operand loads its @@ -223,8 +225,8 @@ class MemoryOperand extends Operand { * is `r1`. */ final AddressOperand getAddressOperand() { - getMemoryAccess().usesAddressOperand() and - result.getUse() = getUse() + this.getMemoryAccess().usesAddressOperand() and + result.getUse() = this.getUse() } } @@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe result = unique(Instruction defInstr | hasDefinition(defInstr, _)) } - final override Overlap getDefinitionOverlap() { hasDefinition(_, result) } + final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) } pragma[noinline] private predicate hasDefinition(Instruction defInstr, Overlap overlap) { @@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand { final override Overlap getDefinitionOverlap() { result = overlap } - final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() } - - final override string getDumpLabel() { - result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" + final override int getDumpSortOrder() { + result = 11 + this.getPredecessorBlock().getDisplayIndex() } - final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() } + final override string getDumpLabel() { + result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":" + } + + final override string getDumpId() { + result = this.getPredecessorBlock().getDisplayIndex().toString() + } /** * Gets the predecessor block from which this value comes. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll index 4b86f9a7cec..bb8630a5e0c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll @@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock { final string toString() { result = getFirstInstruction(this).toString() } /** Gets the source location of the first non-`Phi` instruction in this block. */ - final Language::Location getLocation() { result = getFirstInstruction().getLocation() } + final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() } /** * INTERNAL: Do not use. @@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock { ) and this = rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = getEnclosingFunction() and + funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and // Ensure that the block containing `EnterFunction` always comes first. if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction @@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock { * Get the `Phi` instructions that appear at the start of this block. */ final PhiInstruction getAPhiInstruction() { - Construction::getPhiInstructionBlockStart(result) = getFirstInstruction() + Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction() } /** * Gets an instruction in this block. This includes `Phi` instructions. */ final Instruction getAnInstruction() { - result = getInstruction(_) or - result = getAPhiInstruction() + result = this.getInstruction(_) or + result = this.getAPhiInstruction() } /** @@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock { /** * Gets the last instruction in this block. */ - final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) } + final Instruction getLastInstruction() { + result = this.getInstruction(this.getInstructionCount() - 1) + } /** * Gets the number of non-`Phi` instructions in this block. @@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase { * Block `A` dominates block `B` if any control flow path from the entry block of the function to * block `B` must pass through block `A`. A block always dominates itself. */ - final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block } + final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block } /** * Gets a block on the dominance frontier of this block. @@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock dominanceFrontier() { - dominates(result.getAPredecessor()) and - not strictlyDominates(result) + this.dominates(result.getAPredecessor()) and + not this.strictlyDominates(result) } /** @@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase { * Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the * function must pass through block `A`. A block always post-dominates itself. */ - final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block } + final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block } /** * Gets a block on the post-dominance frontier of this block. @@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase { */ pragma[noinline] final IRBlock postPominanceFrontier() { - postDominates(result.getASuccessor()) and - not strictlyPostDominates(result) + this.postDominates(result.getASuccessor()) and + not this.strictlyPostDominates(result) } /** * Holds if this block is reachable from the entry block of its function. */ final predicate isReachableFromFunctionEntry() { - this = getEnclosingIRFunction().getEntryBlock() or - getAPredecessor().isReachableFromFunctionEntry() + this = this.getEnclosingIRFunction().getEntryBlock() or + this.getAPredecessor().isReachableFromFunctionEntry() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 6f471d8a7e8..88a973fc5a8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction { } /** Gets a textual representation of this element. */ - final string toString() { result = getOpcode().toString() + ": " + getAST().toString() } + final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() } /** * Gets a string showing the result, opcode, and operands of the instruction, equivalent to what @@ -50,7 +50,8 @@ class Instruction extends Construction::TStageInstruction { * `mu0_28(int) = Store r0_26, r0_27` */ final string getDumpString() { - result = getResultString() + " = " + getOperationString() + " " + getOperandsString() + result = + this.getResultString() + " = " + this.getOperationString() + " " + this.getOperandsString() } private predicate shouldGenerateDumpStrings() { @@ -66,10 +67,13 @@ class Instruction extends Construction::TStageInstruction { * VariableAddress[x] */ final string getOperationString() { - shouldGenerateDumpStrings() and - if exists(getImmediateString()) - then result = getOperationPrefix() + getOpcode().toString() + "[" + getImmediateString() + "]" - else result = getOperationPrefix() + getOpcode().toString() + this.shouldGenerateDumpStrings() and + if exists(this.getImmediateString()) + then + result = + this.getOperationPrefix() + this.getOpcode().toString() + "[" + this.getImmediateString() + + "]" + else result = this.getOperationPrefix() + this.getOpcode().toString() } /** @@ -78,17 +82,17 @@ class Instruction extends Construction::TStageInstruction { string getImmediateString() { none() } private string getOperationPrefix() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and if this instanceof SideEffectInstruction then result = "^" else result = "" } private string getResultPrefix() { - shouldGenerateDumpStrings() and - if getResultIRType() instanceof IRVoidType + this.shouldGenerateDumpStrings() and + if this.getResultIRType() instanceof IRVoidType then result = "v" else - if hasMemoryResult() - then if isResultModeled() then result = "m" else result = "mu" + if this.hasMemoryResult() + then if this.isResultModeled() then result = "m" else result = "mu" else result = "r" } @@ -97,7 +101,7 @@ class Instruction extends Construction::TStageInstruction { * used by debugging and printing code only. */ int getDisplayIndexInBlock() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and exists(IRBlock block | this = block.getInstruction(result) or @@ -111,12 +115,12 @@ class Instruction extends Construction::TStageInstruction { } private int getLineRank() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and this = rank[result](Instruction instr | instr = - getAnInstructionAtLine(getEnclosingIRFunction(), getLocation().getFile(), - getLocation().getStartLine()) + getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), + this.getLocation().getStartLine()) | instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() ) @@ -130,8 +134,9 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1` */ string getResultId() { - shouldGenerateDumpStrings() and - result = getResultPrefix() + getAST().getLocation().getStartLine() + "_" + getLineRank() + this.shouldGenerateDumpStrings() and + result = + this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank() } /** @@ -142,8 +147,8 @@ class Instruction extends Construction::TStageInstruction { * Example: `r1_1(int*)` */ final string getResultString() { - shouldGenerateDumpStrings() and - result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")" + this.shouldGenerateDumpStrings() and + result = this.getResultId() + "(" + this.getResultLanguageType().getDumpString() + ")" } /** @@ -153,10 +158,10 @@ class Instruction extends Construction::TStageInstruction { * Example: `func:r3_4, this:r3_5` */ string getOperandsString() { - shouldGenerateDumpStrings() and + this.shouldGenerateDumpStrings() and result = concat(Operand operand | - operand = getAnOperand() + operand = this.getAnOperand() | operand.getDumpString(), ", " order by operand.getDumpSortOrder() ) @@ -190,7 +195,7 @@ class Instruction extends Construction::TStageInstruction { * Gets the function that contains this instruction. */ final Language::Function getEnclosingFunction() { - result = getEnclosingIRFunction().getFunction() + result = this.getEnclosingIRFunction().getFunction() } /** @@ -208,7 +213,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the location of the source code for this instruction. */ - final Language::Location getLocation() { result = getAST().getLocation() } + final Language::Location getLocation() { result = this.getAST().getLocation() } /** * Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a @@ -243,7 +248,7 @@ class Instruction extends Construction::TStageInstruction { * a result, its result type will be `IRVoidType`. */ cached - final IRType getResultIRType() { result = getResultLanguageType().getIRType() } + final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() } /** * Gets the type of the result produced by this instruction. If the @@ -254,7 +259,7 @@ class Instruction extends Construction::TStageInstruction { */ final Language::Type getResultType() { exists(Language::LanguageType resultType | - resultType = getResultLanguageType() and + resultType = this.getResultLanguageType() and ( resultType.hasUnspecifiedType(result, _) or @@ -283,7 +288,7 @@ class Instruction extends Construction::TStageInstruction { * result of the `Load` instruction is a prvalue of type `int`, representing * the integer value loaded from variable `x`. */ - final predicate isGLValue() { getResultLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getResultLanguageType().hasType(_, true) } /** * Gets the size of the result produced by this instruction, in bytes. If the @@ -292,7 +297,7 @@ class Instruction extends Construction::TStageInstruction { * If `this.isGLValue()` holds for this instruction, the value of * `getResultSize()` will always be the size of a pointer. */ - final int getResultSize() { result = getResultLanguageType().getByteSize() } + final int getResultSize() { result = this.getResultLanguageType().getByteSize() } /** * Gets the opcode that specifies the operation performed by this instruction. @@ -314,14 +319,16 @@ class Instruction extends Construction::TStageInstruction { /** * Holds if this instruction produces a memory result. */ - final predicate hasMemoryResult() { exists(getResultMemoryAccess()) } + final predicate hasMemoryResult() { exists(this.getResultMemoryAccess()) } /** * Gets the kind of memory access performed by this instruction's result. * Holds only for instructions with a memory result. */ pragma[inline] - final MemoryAccessKind getResultMemoryAccess() { result = getOpcode().getWriteMemoryAccess() } + final MemoryAccessKind getResultMemoryAccess() { + result = this.getOpcode().getWriteMemoryAccess() + } /** * Holds if the memory access performed by this instruction's result will not always write to @@ -332,7 +339,7 @@ class Instruction extends Construction::TStageInstruction { * (for example, the global side effects of a function call). */ pragma[inline] - final predicate hasResultMayMemoryAccess() { getOpcode().hasMayWriteMemoryAccess() } + final predicate hasResultMayMemoryAccess() { this.getOpcode().hasMayWriteMemoryAccess() } /** * Gets the operand that holds the memory address to which this instruction stores its @@ -340,7 +347,7 @@ class Instruction extends Construction::TStageInstruction { * is `r1`. */ final AddressOperand getResultAddressOperand() { - getResultMemoryAccess().usesAddressOperand() and + this.getResultMemoryAccess().usesAddressOperand() and result.getUse() = this } @@ -349,7 +356,7 @@ class Instruction extends Construction::TStageInstruction { * result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()` * is the instruction that defines `r1`. */ - final Instruction getResultAddress() { result = getResultAddressOperand().getDef() } + final Instruction getResultAddress() { result = this.getResultAddressOperand().getDef() } /** * Holds if the result of this instruction is precisely modeled in SSA. Always @@ -368,7 +375,7 @@ class Instruction extends Construction::TStageInstruction { */ final predicate isResultModeled() { // Register results are always in SSA form. - not hasMemoryResult() or + not this.hasMemoryResult() or Construction::hasModeledMemoryResult(this) } @@ -412,7 +419,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct successors of this instruction. */ - final Instruction getASuccessor() { result = getSuccessor(_) } + final Instruction getASuccessor() { result = this.getSuccessor(_) } /** * Gets a predecessor of this instruction such that the predecessor reaches @@ -423,7 +430,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets all direct predecessors of this instruction. */ - final Instruction getAPredecessor() { result = getPredecessor(_) } + final Instruction getAPredecessor() { result = this.getPredecessor(_) } } /** @@ -543,7 +550,7 @@ class IndexedInstruction extends Instruction { * at this instruction. This instruction has no predecessors. */ class EnterFunctionInstruction extends Instruction { - EnterFunctionInstruction() { getOpcode() instanceof Opcode::EnterFunction } + EnterFunctionInstruction() { this.getOpcode() instanceof Opcode::EnterFunction } } /** @@ -554,7 +561,7 @@ class EnterFunctionInstruction extends Instruction { * struct, or union, see `FieldAddressInstruction`. */ class VariableAddressInstruction extends VariableInstruction { - VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress } + VariableAddressInstruction() { this.getOpcode() instanceof Opcode::VariableAddress } } /** @@ -566,7 +573,7 @@ class VariableAddressInstruction extends VariableInstruction { * The result has an `IRFunctionAddress` type. */ class FunctionAddressInstruction extends FunctionInstruction { - FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress } + FunctionAddressInstruction() { this.getOpcode() instanceof Opcode::FunctionAddress } } /** @@ -577,7 +584,7 @@ class FunctionAddressInstruction extends FunctionInstruction { * initializes that parameter. */ class InitializeParameterInstruction extends VariableInstruction { - InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter } + InitializeParameterInstruction() { this.getOpcode() instanceof Opcode::InitializeParameter } /** * Gets the parameter initialized by this instruction. @@ -603,7 +610,7 @@ class InitializeParameterInstruction extends VariableInstruction { * initialized elsewhere, would not otherwise have a definition in this function. */ class InitializeNonLocalInstruction extends Instruction { - InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal } + InitializeNonLocalInstruction() { this.getOpcode() instanceof Opcode::InitializeNonLocal } } /** @@ -611,7 +618,7 @@ class InitializeNonLocalInstruction extends Instruction { * with the value of that memory on entry to the function. */ class InitializeIndirectionInstruction extends VariableInstruction { - InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + InitializeIndirectionInstruction() { this.getOpcode() instanceof Opcode::InitializeIndirection } /** * Gets the parameter initialized by this instruction. @@ -635,24 +642,24 @@ class InitializeIndirectionInstruction extends VariableInstruction { * An instruction that initializes the `this` pointer parameter of the enclosing function. */ class InitializeThisInstruction extends Instruction { - InitializeThisInstruction() { getOpcode() instanceof Opcode::InitializeThis } + InitializeThisInstruction() { this.getOpcode() instanceof Opcode::InitializeThis } } /** * An instruction that computes the address of a non-static field of an object. */ class FieldAddressInstruction extends FieldInstruction { - FieldAddressInstruction() { getOpcode() instanceof Opcode::FieldAddress } + FieldAddressInstruction() { this.getOpcode() instanceof Opcode::FieldAddress } /** * Gets the operand that provides the address of the object containing the field. */ - final UnaryOperand getObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the object containing the field. */ - final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() } + final Instruction getObjectAddress() { result = this.getObjectAddressOperand().getDef() } } /** @@ -661,17 +668,19 @@ class FieldAddressInstruction extends FieldInstruction { * This instruction is used for element access to C# arrays. */ class ElementsAddressInstruction extends UnaryInstruction { - ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress } + ElementsAddressInstruction() { this.getOpcode() instanceof Opcode::ElementsAddress } /** * Gets the operand that provides the address of the array object. */ - final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() } + final UnaryOperand getArrayObjectAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the array object. */ - final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() } + final Instruction getArrayObjectAddress() { + result = this.getArrayObjectAddressOperand().getDef() + } } /** @@ -685,7 +694,7 @@ class ElementsAddressInstruction extends UnaryInstruction { * taken may want to ignore any function that contains an `ErrorInstruction`. */ class ErrorInstruction extends Instruction { - ErrorInstruction() { getOpcode() instanceof Opcode::Error } + ErrorInstruction() { this.getOpcode() instanceof Opcode::Error } } /** @@ -695,7 +704,7 @@ class ErrorInstruction extends Instruction { * an initializer, or whose initializer only partially initializes the variable. */ class UninitializedInstruction extends VariableInstruction { - UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized } + UninitializedInstruction() { this.getOpcode() instanceof Opcode::Uninitialized } /** * Gets the variable that is uninitialized. @@ -710,7 +719,7 @@ class UninitializedInstruction extends VariableInstruction { * least one instruction, even when the AST has no semantic effect. */ class NoOpInstruction extends Instruction { - NoOpInstruction() { getOpcode() instanceof Opcode::NoOp } + NoOpInstruction() { this.getOpcode() instanceof Opcode::NoOp } } /** @@ -732,32 +741,32 @@ class NoOpInstruction extends Instruction { * `void`-returning function. */ class ReturnInstruction extends Instruction { - ReturnInstruction() { getOpcode() instanceof ReturnOpcode } + ReturnInstruction() { this.getOpcode() instanceof ReturnOpcode } } /** * An instruction that returns control to the caller of the function, without returning a value. */ class ReturnVoidInstruction extends ReturnInstruction { - ReturnVoidInstruction() { getOpcode() instanceof Opcode::ReturnVoid } + ReturnVoidInstruction() { this.getOpcode() instanceof Opcode::ReturnVoid } } /** * An instruction that returns control to the caller of the function, including a return value. */ class ReturnValueInstruction extends ReturnInstruction { - ReturnValueInstruction() { getOpcode() instanceof Opcode::ReturnValue } + ReturnValueInstruction() { this.getOpcode() instanceof Opcode::ReturnValue } /** * Gets the operand that provides the value being returned by the function. */ - final LoadOperand getReturnValueOperand() { result = getAnOperand() } + final LoadOperand getReturnValueOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value being returned by the function, if an * exact definition is available. */ - final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } + final Instruction getReturnValue() { result = this.getReturnValueOperand().getDef() } } /** @@ -770,28 +779,28 @@ class ReturnValueInstruction extends ReturnInstruction { * that the caller initialized the memory pointed to by the parameter before the call. */ class ReturnIndirectionInstruction extends VariableInstruction { - ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + ReturnIndirectionInstruction() { this.getOpcode() instanceof Opcode::ReturnIndirection } /** * Gets the operand that provides the value of the pointed-to memory. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the pointed-to memory, if an exact * definition is available. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** * Gets the operand that provides the address of the pointed-to memory. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the pointed-to memory. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } /** * Gets the parameter for which this instruction reads the final pointed-to value within the @@ -826,7 +835,7 @@ class ReturnIndirectionInstruction extends VariableInstruction { * - `StoreInstruction` - Copies a register operand to a memory result. */ class CopyInstruction extends Instruction { - CopyInstruction() { getOpcode() instanceof CopyOpcode } + CopyInstruction() { this.getOpcode() instanceof CopyOpcode } /** * Gets the operand that provides the input value of the copy. @@ -837,16 +846,16 @@ class CopyInstruction extends Instruction { * Gets the instruction whose result provides the input value of the copy, if an exact definition * is available. */ - final Instruction getSourceValue() { result = getSourceValueOperand().getDef() } + final Instruction getSourceValue() { result = this.getSourceValueOperand().getDef() } } /** * An instruction that returns a register result containing a copy of its register operand. */ class CopyValueInstruction extends CopyInstruction, UnaryInstruction { - CopyValueInstruction() { getOpcode() instanceof Opcode::CopyValue } + CopyValueInstruction() { this.getOpcode() instanceof Opcode::CopyValue } - final override UnaryOperand getSourceValueOperand() { result = getAnOperand() } + final override UnaryOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -863,47 +872,49 @@ private string getAddressOperandDescription(AddressOperand operand) { * An instruction that returns a register result containing a copy of its memory operand. */ class LoadInstruction extends CopyInstruction { - LoadInstruction() { getOpcode() instanceof Opcode::Load } + LoadInstruction() { this.getOpcode() instanceof Opcode::Load } final override string getImmediateString() { - result = getAddressOperandDescription(getSourceAddressOperand()) + result = getAddressOperandDescription(this.getSourceAddressOperand()) } /** * Gets the operand that provides the address of the value being loaded. */ - final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + final AddressOperand getSourceAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the value being loaded. */ - final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + final Instruction getSourceAddress() { result = this.getSourceAddressOperand().getDef() } - final override LoadOperand getSourceValueOperand() { result = getAnOperand() } + final override LoadOperand getSourceValueOperand() { result = this.getAnOperand() } } /** * An instruction that returns a memory result containing a copy of its register operand. */ class StoreInstruction extends CopyInstruction { - StoreInstruction() { getOpcode() instanceof Opcode::Store } + StoreInstruction() { this.getOpcode() instanceof Opcode::Store } final override string getImmediateString() { - result = getAddressOperandDescription(getDestinationAddressOperand()) + result = getAddressOperandDescription(this.getDestinationAddressOperand()) } /** * Gets the operand that provides the address of the location to which the value will be stored. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the location to which the value will * be stored, if an exact definition is available. */ - final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + final Instruction getDestinationAddress() { + result = this.getDestinationAddressOperand().getDef() + } - final override StoreValueOperand getSourceValueOperand() { result = getAnOperand() } + final override StoreValueOperand getSourceValueOperand() { result = this.getAnOperand() } } /** @@ -911,27 +922,27 @@ class StoreInstruction extends CopyInstruction { * operand. */ class ConditionalBranchInstruction extends Instruction { - ConditionalBranchInstruction() { getOpcode() instanceof Opcode::ConditionalBranch } + ConditionalBranchInstruction() { this.getOpcode() instanceof Opcode::ConditionalBranch } /** * Gets the operand that provides the Boolean condition controlling the branch. */ - final ConditionOperand getConditionOperand() { result = getAnOperand() } + final ConditionOperand getConditionOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the Boolean condition controlling the branch. */ - final Instruction getCondition() { result = getConditionOperand().getDef() } + final Instruction getCondition() { result = this.getConditionOperand().getDef() } /** * Gets the instruction to which control will flow if the condition is true. */ - final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) } + final Instruction getTrueSuccessor() { result = this.getSuccessor(EdgeKind::trueEdge()) } /** * Gets the instruction to which control will flow if the condition is false. */ - final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) } + final Instruction getFalseSuccessor() { result = this.getSuccessor(EdgeKind::falseEdge()) } } /** @@ -943,14 +954,14 @@ class ConditionalBranchInstruction extends Instruction { * successors. */ class ExitFunctionInstruction extends Instruction { - ExitFunctionInstruction() { getOpcode() instanceof Opcode::ExitFunction } + ExitFunctionInstruction() { this.getOpcode() instanceof Opcode::ExitFunction } } /** * An instruction whose result is a constant value. */ class ConstantInstruction extends ConstantValueInstruction { - ConstantInstruction() { getOpcode() instanceof Opcode::Constant } + ConstantInstruction() { this.getOpcode() instanceof Opcode::Constant } } /** @@ -959,7 +970,7 @@ class ConstantInstruction extends ConstantValueInstruction { class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { exists(IRType resultType | - resultType = getResultIRType() and + resultType = this.getResultIRType() and (resultType instanceof IRIntegerType or resultType instanceof IRBooleanType) ) } @@ -969,7 +980,7 @@ class IntegerConstantInstruction extends ConstantInstruction { * An instruction whose result is a constant value of floating-point type. */ class FloatConstantInstruction extends ConstantInstruction { - FloatConstantInstruction() { getResultIRType() instanceof IRFloatingPointType } + FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType } } /** @@ -978,7 +989,9 @@ class FloatConstantInstruction extends ConstantInstruction { class StringConstantInstruction extends VariableInstruction { override IRStringLiteral var; - final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } + final override string getImmediateString() { + result = Language::getStringLiteralText(this.getValue()) + } /** * Gets the string literal whose address is returned by this instruction. @@ -990,37 +1003,37 @@ class StringConstantInstruction extends VariableInstruction { * An instruction whose result is computed from two operands. */ class BinaryInstruction extends Instruction { - BinaryInstruction() { getOpcode() instanceof BinaryOpcode } + BinaryInstruction() { this.getOpcode() instanceof BinaryOpcode } /** * Gets the left operand of this binary instruction. */ - final LeftOperand getLeftOperand() { result = getAnOperand() } + final LeftOperand getLeftOperand() { result = this.getAnOperand() } /** * Gets the right operand of this binary instruction. */ - final RightOperand getRightOperand() { result = getAnOperand() } + final RightOperand getRightOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the value of the left operand of this binary * instruction. */ - final Instruction getLeft() { result = getLeftOperand().getDef() } + final Instruction getLeft() { result = this.getLeftOperand().getDef() } /** * Gets the instruction whose result provides the value of the right operand of this binary * instruction. */ - final Instruction getRight() { result = getRightOperand().getDef() } + final Instruction getRight() { result = this.getRightOperand().getDef() } /** * Holds if this instruction's operands are `op1` and `op2`, in either order. */ final predicate hasOperands(Operand op1, Operand op2) { - op1 = getLeftOperand() and op2 = getRightOperand() + op1 = this.getLeftOperand() and op2 = this.getRightOperand() or - op1 = getRightOperand() and op2 = getLeftOperand() + op1 = this.getRightOperand() and op2 = this.getLeftOperand() } } @@ -1028,7 +1041,7 @@ class BinaryInstruction extends Instruction { * An instruction that computes the result of an arithmetic operation. */ class ArithmeticInstruction extends Instruction { - ArithmeticInstruction() { getOpcode() instanceof ArithmeticOpcode } + ArithmeticInstruction() { this.getOpcode() instanceof ArithmeticOpcode } } /** @@ -1050,7 +1063,7 @@ class UnaryArithmeticInstruction extends ArithmeticInstruction, UnaryInstruction * performed according to IEEE-754. */ class AddInstruction extends BinaryArithmeticInstruction { - AddInstruction() { getOpcode() instanceof Opcode::Add } + AddInstruction() { this.getOpcode() instanceof Opcode::Add } } /** @@ -1061,7 +1074,7 @@ class AddInstruction extends BinaryArithmeticInstruction { * according to IEEE-754. */ class SubInstruction extends BinaryArithmeticInstruction { - SubInstruction() { getOpcode() instanceof Opcode::Sub } + SubInstruction() { this.getOpcode() instanceof Opcode::Sub } } /** @@ -1072,7 +1085,7 @@ class SubInstruction extends BinaryArithmeticInstruction { * performed according to IEEE-754. */ class MulInstruction extends BinaryArithmeticInstruction { - MulInstruction() { getOpcode() instanceof Opcode::Mul } + MulInstruction() { this.getOpcode() instanceof Opcode::Mul } } /** @@ -1083,7 +1096,7 @@ class MulInstruction extends BinaryArithmeticInstruction { * to IEEE-754. */ class DivInstruction extends BinaryArithmeticInstruction { - DivInstruction() { getOpcode() instanceof Opcode::Div } + DivInstruction() { this.getOpcode() instanceof Opcode::Div } } /** @@ -1093,7 +1106,7 @@ class DivInstruction extends BinaryArithmeticInstruction { * division by zero or integer overflow is undefined. */ class RemInstruction extends BinaryArithmeticInstruction { - RemInstruction() { getOpcode() instanceof Opcode::Rem } + RemInstruction() { this.getOpcode() instanceof Opcode::Rem } } /** @@ -1104,14 +1117,14 @@ class RemInstruction extends BinaryArithmeticInstruction { * is performed according to IEEE-754. */ class NegateInstruction extends UnaryArithmeticInstruction { - NegateInstruction() { getOpcode() instanceof Opcode::Negate } + NegateInstruction() { this.getOpcode() instanceof Opcode::Negate } } /** * An instruction that computes the result of a bitwise operation. */ class BitwiseInstruction extends Instruction { - BitwiseInstruction() { getOpcode() instanceof BitwiseOpcode } + BitwiseInstruction() { this.getOpcode() instanceof BitwiseOpcode } } /** @@ -1130,7 +1143,7 @@ class UnaryBitwiseInstruction extends BitwiseInstruction, UnaryInstruction { } * Both operands must have the same integer type, which will also be the result type. */ class BitAndInstruction extends BinaryBitwiseInstruction { - BitAndInstruction() { getOpcode() instanceof Opcode::BitAnd } + BitAndInstruction() { this.getOpcode() instanceof Opcode::BitAnd } } /** @@ -1139,7 +1152,7 @@ class BitAndInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitOrInstruction extends BinaryBitwiseInstruction { - BitOrInstruction() { getOpcode() instanceof Opcode::BitOr } + BitOrInstruction() { this.getOpcode() instanceof Opcode::BitOr } } /** @@ -1148,7 +1161,7 @@ class BitOrInstruction extends BinaryBitwiseInstruction { * Both operands must have the same integer type, which will also be the result type. */ class BitXorInstruction extends BinaryBitwiseInstruction { - BitXorInstruction() { getOpcode() instanceof Opcode::BitXor } + BitXorInstruction() { this.getOpcode() instanceof Opcode::BitXor } } /** @@ -1159,7 +1172,7 @@ class BitXorInstruction extends BinaryBitwiseInstruction { * rightmost bits are zero-filled. */ class ShiftLeftInstruction extends BinaryBitwiseInstruction { - ShiftLeftInstruction() { getOpcode() instanceof Opcode::ShiftLeft } + ShiftLeftInstruction() { this.getOpcode() instanceof Opcode::ShiftLeft } } /** @@ -1172,7 +1185,7 @@ class ShiftLeftInstruction extends BinaryBitwiseInstruction { * of the left operand. */ class ShiftRightInstruction extends BinaryBitwiseInstruction { - ShiftRightInstruction() { getOpcode() instanceof Opcode::ShiftRight } + ShiftRightInstruction() { this.getOpcode() instanceof Opcode::ShiftRight } } /** @@ -1183,7 +1196,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { int elementSize; PointerArithmeticInstruction() { - getOpcode() instanceof PointerArithmeticOpcode and + this.getOpcode() instanceof PointerArithmeticOpcode and elementSize = Raw::getInstructionElementSize(this) } @@ -1206,7 +1219,7 @@ class PointerArithmeticInstruction extends BinaryInstruction { * An instruction that adds or subtracts an integer offset from a pointer. */ class PointerOffsetInstruction extends PointerArithmeticInstruction { - PointerOffsetInstruction() { getOpcode() instanceof PointerOffsetOpcode } + PointerOffsetInstruction() { this.getOpcode() instanceof PointerOffsetOpcode } } /** @@ -1217,7 +1230,7 @@ class PointerOffsetInstruction extends PointerArithmeticInstruction { * overflow is undefined. */ class PointerAddInstruction extends PointerOffsetInstruction { - PointerAddInstruction() { getOpcode() instanceof Opcode::PointerAdd } + PointerAddInstruction() { this.getOpcode() instanceof Opcode::PointerAdd } } /** @@ -1228,7 +1241,7 @@ class PointerAddInstruction extends PointerOffsetInstruction { * pointer underflow is undefined. */ class PointerSubInstruction extends PointerOffsetInstruction { - PointerSubInstruction() { getOpcode() instanceof Opcode::PointerSub } + PointerSubInstruction() { this.getOpcode() instanceof Opcode::PointerSub } } /** @@ -1241,31 +1254,31 @@ class PointerSubInstruction extends PointerOffsetInstruction { * undefined. */ class PointerDiffInstruction extends PointerArithmeticInstruction { - PointerDiffInstruction() { getOpcode() instanceof Opcode::PointerDiff } + PointerDiffInstruction() { this.getOpcode() instanceof Opcode::PointerDiff } } /** * An instruction whose result is computed from a single operand. */ class UnaryInstruction extends Instruction { - UnaryInstruction() { getOpcode() instanceof UnaryOpcode } + UnaryInstruction() { this.getOpcode() instanceof UnaryOpcode } /** * Gets the sole operand of this instruction. */ - final UnaryOperand getUnaryOperand() { result = getAnOperand() } + final UnaryOperand getUnaryOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the sole operand of this instruction. */ - final Instruction getUnary() { result = getUnaryOperand().getDef() } + final Instruction getUnary() { result = this.getUnaryOperand().getDef() } } /** * An instruction that converts the value of its operand to a value of a different type. */ class ConvertInstruction extends UnaryInstruction { - ConvertInstruction() { getOpcode() instanceof Opcode::Convert } + ConvertInstruction() { this.getOpcode() instanceof Opcode::Convert } } /** @@ -1279,7 +1292,7 @@ class ConvertInstruction extends UnaryInstruction { * `as` expression. */ class CheckedConvertOrNullInstruction extends UnaryInstruction { - CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull } + CheckedConvertOrNullInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrNull } } /** @@ -1293,7 +1306,7 @@ class CheckedConvertOrNullInstruction extends UnaryInstruction { * expression. */ class CheckedConvertOrThrowInstruction extends UnaryInstruction { - CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow } + CheckedConvertOrThrowInstruction() { this.getOpcode() instanceof Opcode::CheckedConvertOrThrow } } /** @@ -1306,7 +1319,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction { * the most-derived object. */ class CompleteObjectAddressInstruction extends UnaryInstruction { - CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress } + CompleteObjectAddressInstruction() { this.getOpcode() instanceof Opcode::CompleteObjectAddress } } /** @@ -1351,7 +1364,7 @@ class InheritanceConversionInstruction extends UnaryInstruction { * An instruction that converts from the address of a derived class to the address of a base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } + ConvertToBaseInstruction() { this.getOpcode() instanceof ConvertToBaseOpcode } } /** @@ -1361,7 +1374,9 @@ class ConvertToBaseInstruction extends InheritanceConversionInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } + ConvertToNonVirtualBaseInstruction() { + this.getOpcode() instanceof Opcode::ConvertToNonVirtualBase + } } /** @@ -1371,7 +1386,7 @@ class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { - ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } + ConvertToVirtualBaseInstruction() { this.getOpcode() instanceof Opcode::ConvertToVirtualBase } } /** @@ -1381,7 +1396,7 @@ class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { * If the operand holds a null address, the result is a null address. */ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { - ConvertToDerivedInstruction() { getOpcode() instanceof Opcode::ConvertToDerived } + ConvertToDerivedInstruction() { this.getOpcode() instanceof Opcode::ConvertToDerived } } /** @@ -1390,7 +1405,7 @@ class ConvertToDerivedInstruction extends InheritanceConversionInstruction { * The operand must have an integer type, which will also be the result type. */ class BitComplementInstruction extends UnaryBitwiseInstruction { - BitComplementInstruction() { getOpcode() instanceof Opcode::BitComplement } + BitComplementInstruction() { this.getOpcode() instanceof Opcode::BitComplement } } /** @@ -1399,14 +1414,14 @@ class BitComplementInstruction extends UnaryBitwiseInstruction { * The operand must have a Boolean type, which will also be the result type. */ class LogicalNotInstruction extends UnaryInstruction { - LogicalNotInstruction() { getOpcode() instanceof Opcode::LogicalNot } + LogicalNotInstruction() { this.getOpcode() instanceof Opcode::LogicalNot } } /** * An instruction that compares two numeric operands. */ class CompareInstruction extends BinaryInstruction { - CompareInstruction() { getOpcode() instanceof CompareOpcode } + CompareInstruction() { this.getOpcode() instanceof CompareOpcode } } /** @@ -1417,7 +1432,7 @@ class CompareInstruction extends BinaryInstruction { * unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareEQInstruction extends CompareInstruction { - CompareEQInstruction() { getOpcode() instanceof Opcode::CompareEQ } + CompareEQInstruction() { this.getOpcode() instanceof Opcode::CompareEQ } } /** @@ -1428,14 +1443,14 @@ class CompareEQInstruction extends CompareInstruction { * `left == right`. Floating-point comparison is performed according to IEEE-754. */ class CompareNEInstruction extends CompareInstruction { - CompareNEInstruction() { getOpcode() instanceof Opcode::CompareNE } + CompareNEInstruction() { this.getOpcode() instanceof Opcode::CompareNE } } /** * An instruction that does a relative comparison of two values, such as `<` or `>=`. */ class RelationalInstruction extends CompareInstruction { - RelationalInstruction() { getOpcode() instanceof RelationalOpcode } + RelationalInstruction() { this.getOpcode() instanceof RelationalOpcode } /** * Gets the operand on the "greater" (or "greater-or-equal") side @@ -1467,11 +1482,11 @@ class RelationalInstruction extends CompareInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLTInstruction extends RelationalInstruction { - CompareLTInstruction() { getOpcode() instanceof Opcode::CompareLT } + CompareLTInstruction() { this.getOpcode() instanceof Opcode::CompareLT } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { any() } } @@ -1484,11 +1499,11 @@ class CompareLTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGTInstruction extends RelationalInstruction { - CompareGTInstruction() { getOpcode() instanceof Opcode::CompareGT } + CompareGTInstruction() { this.getOpcode() instanceof Opcode::CompareGT } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { any() } } @@ -1502,11 +1517,11 @@ class CompareGTInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareLEInstruction extends RelationalInstruction { - CompareLEInstruction() { getOpcode() instanceof Opcode::CompareLE } + CompareLEInstruction() { this.getOpcode() instanceof Opcode::CompareLE } - override Instruction getLesser() { result = getLeft() } + override Instruction getLesser() { result = this.getLeft() } - override Instruction getGreater() { result = getRight() } + override Instruction getGreater() { result = this.getRight() } override predicate isStrict() { none() } } @@ -1520,11 +1535,11 @@ class CompareLEInstruction extends RelationalInstruction { * are unordered. Floating-point comparison is performed according to IEEE-754. */ class CompareGEInstruction extends RelationalInstruction { - CompareGEInstruction() { getOpcode() instanceof Opcode::CompareGE } + CompareGEInstruction() { this.getOpcode() instanceof Opcode::CompareGE } - override Instruction getLesser() { result = getRight() } + override Instruction getLesser() { result = this.getRight() } - override Instruction getGreater() { result = getLeft() } + override Instruction getGreater() { result = this.getLeft() } override predicate isStrict() { none() } } @@ -1543,78 +1558,78 @@ class CompareGEInstruction extends RelationalInstruction { * of any case edge. */ class SwitchInstruction extends Instruction { - SwitchInstruction() { getOpcode() instanceof Opcode::Switch } + SwitchInstruction() { this.getOpcode() instanceof Opcode::Switch } /** Gets the operand that provides the integer value controlling the switch. */ - final ConditionOperand getExpressionOperand() { result = getAnOperand() } + final ConditionOperand getExpressionOperand() { result = this.getAnOperand() } /** Gets the instruction whose result provides the integer value controlling the switch. */ - final Instruction getExpression() { result = getExpressionOperand().getDef() } + final Instruction getExpression() { result = this.getExpressionOperand().getDef() } /** Gets the successor instructions along the case edges of the switch. */ - final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) } + final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = this.getSuccessor(edge)) } /** Gets the successor instruction along the default edge of the switch, if any. */ - final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) } + final Instruction getDefaultSuccessor() { result = this.getSuccessor(EdgeKind::defaultEdge()) } } /** * An instruction that calls a function. */ class CallInstruction extends Instruction { - CallInstruction() { getOpcode() instanceof Opcode::Call } + CallInstruction() { this.getOpcode() instanceof Opcode::Call } final override string getImmediateString() { - result = getStaticCallTarget().toString() + result = this.getStaticCallTarget().toString() or - not exists(getStaticCallTarget()) and result = "?" + not exists(this.getStaticCallTarget()) and result = "?" } /** * Gets the operand the specifies the target function of the call. */ - final CallTargetOperand getCallTargetOperand() { result = getAnOperand() } + final CallTargetOperand getCallTargetOperand() { result = this.getAnOperand() } /** * Gets the `Instruction` that computes the target function of the call. This is usually a * `FunctionAddress` instruction, but can also be an arbitrary instruction that produces a * function pointer. */ - final Instruction getCallTarget() { result = getCallTargetOperand().getDef() } + final Instruction getCallTarget() { result = this.getCallTargetOperand().getDef() } /** * Gets all of the argument operands of the call, including the `this` pointer, if any. */ - final ArgumentOperand getAnArgumentOperand() { result = getAnOperand() } + final ArgumentOperand getAnArgumentOperand() { result = this.getAnOperand() } /** * Gets the `Function` that the call targets, if this is statically known. */ final Language::Function getStaticCallTarget() { - result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() + result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() } /** * Gets all of the arguments of the call, including the `this` pointer, if any. */ - final Instruction getAnArgument() { result = getAnArgumentOperand().getDef() } + final Instruction getAnArgument() { result = this.getAnArgumentOperand().getDef() } /** * Gets the `this` pointer argument operand of the call, if any. */ - final ThisArgumentOperand getThisArgumentOperand() { result = getAnOperand() } + final ThisArgumentOperand getThisArgumentOperand() { result = this.getAnOperand() } /** * Gets the `this` pointer argument of the call, if any. */ - final Instruction getThisArgument() { result = getThisArgumentOperand().getDef() } + final Instruction getThisArgument() { result = this.getThisArgumentOperand().getDef() } /** * Gets the argument operand at the specified index. */ pragma[noinline] final PositionalArgumentOperand getPositionalArgumentOperand(int index) { - result = getAnOperand() and + result = this.getAnOperand() and result.getIndex() = index } @@ -1623,7 +1638,7 @@ class CallInstruction extends Instruction { */ pragma[noinline] final Instruction getPositionalArgument(int index) { - result = getPositionalArgumentOperand(index).getDef() + result = this.getPositionalArgumentOperand(index).getDef() } /** @@ -1631,16 +1646,16 @@ class CallInstruction extends Instruction { */ pragma[noinline] final ArgumentOperand getArgumentOperand(int index) { - index >= 0 and result = getPositionalArgumentOperand(index) + index >= 0 and result = this.getPositionalArgumentOperand(index) or - index = -1 and result = getThisArgumentOperand() + index = -1 and result = this.getThisArgumentOperand() } /** * Gets the argument at the specified index, or `this` if `index` is `-1`. */ pragma[noinline] - final Instruction getArgument(int index) { result = getArgumentOperand(index).getDef() } + final Instruction getArgument(int index) { result = this.getArgumentOperand(index).getDef() } /** * Gets the number of arguments of the call, including the `this` pointer, if any. @@ -1665,7 +1680,7 @@ class CallInstruction extends Instruction { * An instruction representing a side effect of a function call. */ class SideEffectInstruction extends Instruction { - SideEffectInstruction() { getOpcode() instanceof SideEffectOpcode } + SideEffectInstruction() { this.getOpcode() instanceof SideEffectOpcode } /** * Gets the instruction whose execution causes this side effect. @@ -1680,7 +1695,7 @@ class SideEffectInstruction extends Instruction { * accessed by that call. */ class CallSideEffectInstruction extends SideEffectInstruction { - CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect } + CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } } /** @@ -1691,7 +1706,7 @@ class CallSideEffectInstruction extends SideEffectInstruction { * call target cannot write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { - CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } + CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } } /** @@ -1699,33 +1714,33 @@ class CallReadSideEffectInstruction extends SideEffectInstruction { * specific parameter. */ class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + ReadSideEffectInstruction() { this.getOpcode() instanceof ReadSideEffectOpcode } /** Gets the operand for the value that will be read from this instruction, if known. */ - final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } /** Gets the value that will be read from this instruction, if known. */ - final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + final Instruction getSideEffect() { result = this.getSideEffectOperand().getDef() } /** Gets the operand for the address from which this instruction may read. */ - final AddressOperand getArgumentOperand() { result = getAnOperand() } + final AddressOperand getArgumentOperand() { result = this.getAnOperand() } /** Gets the address from which this instruction may read. */ - final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } + final Instruction getArgumentDef() { result = this.getArgumentOperand().getDef() } } /** * An instruction representing the read of an indirect parameter within a function call. */ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { - IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } + IndirectReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::IndirectReadSideEffect } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } + BufferReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::BufferReadSideEffect } } /** @@ -1733,18 +1748,18 @@ class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferReadSideEffect + this.getOpcode() instanceof Opcode::SizedBufferReadSideEffect } /** * Gets the operand that holds the number of bytes read from the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes read from the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1752,17 +1767,17 @@ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { - WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } + WriteSideEffectInstruction() { this.getOpcode() instanceof WriteSideEffectOpcode } /** * Get the operand that holds the address of the memory to be written. */ - final AddressOperand getDestinationAddressOperand() { result = getAnOperand() } + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the address of the memory to be written. */ - Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() } + Instruction getDestinationAddress() { result = this.getDestinationAddressOperand().getDef() } } /** @@ -1770,7 +1785,7 @@ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstructi */ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMustWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMustWriteSideEffect } } @@ -1780,7 +1795,7 @@ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction */ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { BufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::BufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::BufferMustWriteSideEffect } } @@ -1790,18 +1805,18 @@ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMustWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1812,7 +1827,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi */ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { IndirectMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::IndirectMayWriteSideEffect + this.getOpcode() instanceof Opcode::IndirectMayWriteSideEffect } } @@ -1822,7 +1837,9 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction { * Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten. */ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { - BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect } + BufferMayWriteSideEffectInstruction() { + this.getOpcode() instanceof Opcode::BufferMayWriteSideEffect + } } /** @@ -1832,18 +1849,18 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { */ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction { SizedBufferMayWriteSideEffectInstruction() { - getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect + this.getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect } /** * Gets the operand that holds the number of bytes written to the buffer. */ - final BufferSizeOperand getBufferSizeOperand() { result = getAnOperand() } + final BufferSizeOperand getBufferSizeOperand() { result = this.getAnOperand() } /** * Gets the instruction whose result provides the number of bytes written to the buffer. */ - final Instruction getBufferSize() { result = getBufferSizeOperand().getDef() } + final Instruction getBufferSize() { result = this.getBufferSizeOperand().getDef() } } /** @@ -1852,80 +1869,80 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio */ class InitializeDynamicAllocationInstruction extends SideEffectInstruction { InitializeDynamicAllocationInstruction() { - getOpcode() instanceof Opcode::InitializeDynamicAllocation + this.getOpcode() instanceof Opcode::InitializeDynamicAllocation } /** * Gets the operand that represents the address of the allocation this instruction is initializing. */ - final AddressOperand getAllocationAddressOperand() { result = getAnOperand() } + final AddressOperand getAllocationAddressOperand() { result = this.getAnOperand() } /** * Gets the address for the allocation this instruction is initializing. */ - final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() } + final Instruction getAllocationAddress() { result = this.getAllocationAddressOperand().getDef() } } /** * An instruction representing a GNU or MSVC inline assembly statement. */ class InlineAsmInstruction extends Instruction { - InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm } + InlineAsmInstruction() { this.getOpcode() instanceof Opcode::InlineAsm } } /** * An instruction that throws an exception. */ class ThrowInstruction extends Instruction { - ThrowInstruction() { getOpcode() instanceof ThrowOpcode } + ThrowInstruction() { this.getOpcode() instanceof ThrowOpcode } } /** * An instruction that throws a new exception. */ class ThrowValueInstruction extends ThrowInstruction { - ThrowValueInstruction() { getOpcode() instanceof Opcode::ThrowValue } + ThrowValueInstruction() { this.getOpcode() instanceof Opcode::ThrowValue } /** * Gets the address operand of the exception thrown by this instruction. */ - final AddressOperand getExceptionAddressOperand() { result = getAnOperand() } + final AddressOperand getExceptionAddressOperand() { result = this.getAnOperand() } /** * Gets the address of the exception thrown by this instruction. */ - final Instruction getExceptionAddress() { result = getExceptionAddressOperand().getDef() } + final Instruction getExceptionAddress() { result = this.getExceptionAddressOperand().getDef() } /** * Gets the operand for the exception thrown by this instruction. */ - final LoadOperand getExceptionOperand() { result = getAnOperand() } + final LoadOperand getExceptionOperand() { result = this.getAnOperand() } /** * Gets the exception thrown by this instruction. */ - final Instruction getException() { result = getExceptionOperand().getDef() } + final Instruction getException() { result = this.getExceptionOperand().getDef() } } /** * An instruction that re-throws the current exception. */ class ReThrowInstruction extends ThrowInstruction { - ReThrowInstruction() { getOpcode() instanceof Opcode::ReThrow } + ReThrowInstruction() { this.getOpcode() instanceof Opcode::ReThrow } } /** * An instruction that exits the current function by propagating an exception. */ class UnwindInstruction extends Instruction { - UnwindInstruction() { getOpcode() instanceof Opcode::Unwind } + UnwindInstruction() { this.getOpcode() instanceof Opcode::Unwind } } /** * An instruction that starts a `catch` handler. */ class CatchInstruction extends Instruction { - CatchInstruction() { getOpcode() instanceof CatchOpcode } + CatchInstruction() { this.getOpcode() instanceof CatchOpcode } } /** @@ -1935,7 +1952,7 @@ class CatchByTypeInstruction extends CatchInstruction { Language::LanguageType exceptionType; CatchByTypeInstruction() { - getOpcode() instanceof Opcode::CatchByType and + this.getOpcode() instanceof Opcode::CatchByType and exceptionType = Raw::getInstructionExceptionType(this) } @@ -1951,21 +1968,21 @@ class CatchByTypeInstruction extends CatchInstruction { * An instruction that catches any exception. */ class CatchAnyInstruction extends CatchInstruction { - CatchAnyInstruction() { getOpcode() instanceof Opcode::CatchAny } + CatchAnyInstruction() { this.getOpcode() instanceof Opcode::CatchAny } } /** * An instruction that initializes all escaped memory. */ class AliasedDefinitionInstruction extends Instruction { - AliasedDefinitionInstruction() { getOpcode() instanceof Opcode::AliasedDefinition } + AliasedDefinitionInstruction() { this.getOpcode() instanceof Opcode::AliasedDefinition } } /** * An instruction that consumes all escaped memory on exit from the function. */ class AliasedUseInstruction extends Instruction { - AliasedUseInstruction() { getOpcode() instanceof Opcode::AliasedUse } + AliasedUseInstruction() { this.getOpcode() instanceof Opcode::AliasedUse } } /** @@ -1979,7 +1996,7 @@ class AliasedUseInstruction extends Instruction { * runtime. */ class PhiInstruction extends Instruction { - PhiInstruction() { getOpcode() instanceof Opcode::Phi } + PhiInstruction() { this.getOpcode() instanceof Opcode::Phi } /** * Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block. @@ -2047,29 +2064,29 @@ class PhiInstruction extends Instruction { * https://link.springer.com/content/pdf/10.1007%2F3-540-61053-7_66.pdf. */ class ChiInstruction extends Instruction { - ChiInstruction() { getOpcode() instanceof Opcode::Chi } + ChiInstruction() { this.getOpcode() instanceof Opcode::Chi } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final ChiTotalOperand getTotalOperand() { result = getAnOperand() } + final ChiTotalOperand getTotalOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the previous state of all memory that might be aliased by the * memory write. */ - final Instruction getTotal() { result = getTotalOperand().getDef() } + final Instruction getTotal() { result = this.getTotalOperand().getDef() } /** * Gets the operand that represents the new value written by the memory write. */ - final ChiPartialOperand getPartialOperand() { result = getAnOperand() } + final ChiPartialOperand getPartialOperand() { result = this.getAnOperand() } /** * Gets the operand that represents the new value written by the memory write. */ - final Instruction getPartial() { result = getPartialOperand().getDef() } + final Instruction getPartial() { result = this.getPartialOperand().getDef() } /** * Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand. @@ -2093,7 +2110,7 @@ class ChiInstruction extends Instruction { * or `Switch` instruction where that particular edge is infeasible. */ class UnreachedInstruction extends Instruction { - UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached } + UnreachedInstruction() { this.getOpcode() instanceof Opcode::Unreached } } /** @@ -2106,7 +2123,7 @@ class BuiltInOperationInstruction extends Instruction { Language::BuiltInOperation operation; BuiltInOperationInstruction() { - getOpcode() instanceof BuiltInOperationOpcode and + this.getOpcode() instanceof BuiltInOperationOpcode and operation = Raw::getInstructionBuiltInOperation(this) } @@ -2122,9 +2139,9 @@ class BuiltInOperationInstruction extends Instruction { * actual operation is specified by the `getBuiltInOperation()` predicate. */ class BuiltInInstruction extends BuiltInOperationInstruction { - BuiltInInstruction() { getOpcode() instanceof Opcode::BuiltIn } + BuiltInInstruction() { this.getOpcode() instanceof Opcode::BuiltIn } - final override string getImmediateString() { result = getBuiltInOperation().toString() } + final override string getImmediateString() { result = this.getBuiltInOperation().toString() } } /** @@ -2135,7 +2152,7 @@ class BuiltInInstruction extends BuiltInOperationInstruction { * to the `...` parameter. */ class VarArgsStartInstruction extends UnaryInstruction { - VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart } + VarArgsStartInstruction() { this.getOpcode() instanceof Opcode::VarArgsStart } } /** @@ -2145,7 +2162,7 @@ class VarArgsStartInstruction extends UnaryInstruction { * a result. */ class VarArgsEndInstruction extends UnaryInstruction { - VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd } + VarArgsEndInstruction() { this.getOpcode() instanceof Opcode::VarArgsEnd } } /** @@ -2155,7 +2172,7 @@ class VarArgsEndInstruction extends UnaryInstruction { * argument. */ class VarArgInstruction extends UnaryInstruction { - VarArgInstruction() { getOpcode() instanceof Opcode::VarArg } + VarArgInstruction() { this.getOpcode() instanceof Opcode::VarArg } } /** @@ -2166,7 +2183,7 @@ class VarArgInstruction extends UnaryInstruction { * argument of the `...` parameter. */ class NextVarArgInstruction extends UnaryInstruction { - NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg } + NextVarArgInstruction() { this.getOpcode() instanceof Opcode::NextVarArg } } /** @@ -2180,5 +2197,5 @@ class NextVarArgInstruction extends UnaryInstruction { * The result is the address of the newly allocated object. */ class NewObjInstruction extends Instruction { - NewObjInstruction() { getOpcode() instanceof Opcode::NewObj } + NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll index d7cf89ca9aa..85d217bd361 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -46,12 +46,12 @@ class Operand extends TStageOperand { /** * Gets the location of the source code for this operand. */ - final Language::Location getLocation() { result = getUse().getLocation() } + final Language::Location getLocation() { result = this.getUse().getLocation() } /** * Gets the function that contains this operand. */ - final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() } + final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() } /** * Gets the `Instruction` that consumes this operand. @@ -74,7 +74,7 @@ class Operand extends TStageOperand { */ final Instruction getDef() { result = this.getAnyDef() and - getDefinitionOverlap() instanceof MustExactlyOverlap + this.getDefinitionOverlap() instanceof MustExactlyOverlap } /** @@ -82,7 +82,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` that consumes this operand. */ - deprecated final Instruction getUseInstruction() { result = getUse() } + deprecated final Instruction getUseInstruction() { result = this.getUse() } /** * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this @@ -91,7 +91,7 @@ class Operand extends TStageOperand { * * Gets the `Instruction` whose result is the value of the operand. */ - deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() } + deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } /** * Gets the overlap relationship between the operand's definition and its use. @@ -101,7 +101,9 @@ class Operand extends TStageOperand { /** * Holds if the result of the definition instruction does not exactly overlap this use. */ - final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap } + final predicate isDefinitionInexact() { + not this.getDefinitionOverlap() instanceof MustExactlyOverlap + } /** * Gets a prefix to use when dumping the operand in an operand list. @@ -121,7 +123,7 @@ class Operand extends TStageOperand { * For example: `this:r3_5` */ final string getDumpString() { - result = getDumpLabel() + getInexactSpecifier() + getDefinitionId() + result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId() } /** @@ -129,9 +131,9 @@ class Operand extends TStageOperand { * definition is not modeled in SSA. */ private string getDefinitionId() { - result = getAnyDef().getResultId() + result = this.getAnyDef().getResultId() or - not exists(getAnyDef()) and result = "m?" + not exists(this.getAnyDef()) and result = "m?" } /** @@ -140,7 +142,7 @@ class Operand extends TStageOperand { * the empty string. */ private string getInexactSpecifier() { - if isDefinitionInexact() then result = "~" else result = "" + if this.isDefinitionInexact() then result = "~" else result = "" } /** @@ -155,7 +157,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() } + Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() } /** * Gets the language-neutral type of the value consumed by this operand. This is usually the same @@ -164,7 +166,7 @@ class Operand extends TStageOperand { * from the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final IRType getIRType() { result = getLanguageType().getIRType() } + final IRType getIRType() { result = this.getLanguageType().getIRType() } /** * Gets the type of the value consumed by this operand. This is usually the same as the @@ -173,7 +175,7 @@ class Operand extends TStageOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - final Language::Type getType() { getLanguageType().hasType(result, _) } + final Language::Type getType() { this.getLanguageType().hasType(result, _) } /** * Holds if the value consumed by this operand is a glvalue. If this @@ -182,13 +184,13 @@ class Operand extends TStageOperand { * not hold, the value of the operand represents a value whose type is * given by `getType()`. */ - final predicate isGLValue() { getLanguageType().hasType(_, true) } + final predicate isGLValue() { this.getLanguageType().hasType(_, true) } /** * Gets the size of the value consumed by this operand, in bytes. If the operand does not have * a known constant size, this predicate does not hold. */ - final int getSize() { result = getLanguageType().getByteSize() } + final int getSize() { result = this.getLanguageType().getByteSize() } } /** @@ -205,7 +207,7 @@ class MemoryOperand extends Operand { /** * Gets the kind of memory access performed by the operand. */ - MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() } + MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() } /** * Holds if the memory access performed by this operand will not always read from every bit in the @@ -215,7 +217,7 @@ class MemoryOperand extends Operand { * conservative estimate of the memory that might actually be accessed at runtime (for example, * the global side effects of a function call). */ - predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() } + predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() } /** * Returns the operand that holds the memory address from which the current operand loads its @@ -223,8 +225,8 @@ class MemoryOperand extends Operand { * is `r1`. */ final AddressOperand getAddressOperand() { - getMemoryAccess().usesAddressOperand() and - result.getUse() = getUse() + this.getMemoryAccess().usesAddressOperand() and + result.getUse() = this.getUse() } } @@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe result = unique(Instruction defInstr | hasDefinition(defInstr, _)) } - final override Overlap getDefinitionOverlap() { hasDefinition(_, result) } + final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) } pragma[noinline] private predicate hasDefinition(Instruction defInstr, Overlap overlap) { @@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand { final override Overlap getDefinitionOverlap() { result = overlap } - final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() } - - final override string getDumpLabel() { - result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" + final override int getDumpSortOrder() { + result = 11 + this.getPredecessorBlock().getDisplayIndex() } - final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() } + final override string getDumpLabel() { + result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":" + } + + final override string getDumpId() { + result = this.getPredecessorBlock().getDisplayIndex().toString() + } /** * Gets the predecessor block from which this value comes. 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 c3b2fc44f14..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index c3b2fc44f14..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index c3b2fc44f14..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index c3b2fc44f14..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index c3b2fc44f14..4ca06c93362 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) 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 f43a550af57..494780d2e1b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -937,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { } override predicate relevantFor(DataFlowCallable callable) { - recordDataFlowCallSite(getCall(), callable) + recordDataFlowCallSite(this.getCall(), callable) } override predicate matchesCall(DataFlowCall call) { call = this.getCall() } @@ -1257,7 +1257,7 @@ abstract class AccessPathFront extends TAccessPathFront { TypedContent getHead() { this = TFrontHead(result) } - predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) } + predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll index 558ecd1b88b..e450c11b5ab 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll @@ -28,7 +28,7 @@ class SsaReadPositionBlock extends SsaReadPosition, TSsaReadPositionBlock { /** Gets the basic block corresponding to this position. */ BasicBlock getBlock() { this = TSsaReadPositionBlock(result) } - override predicate hasReadOfVar(SsaVariable v) { getBlock() = getAReadBasicBlock(v) } + override predicate hasReadOfVar(SsaVariable v) { this.getBlock() = getAReadBasicBlock(v) } override string toString() { result = "block" } } @@ -49,8 +49,8 @@ class SsaReadPositionPhiInputEdge extends SsaReadPosition, TSsaReadPositionPhiIn /** Holds if `inp` is an input to `phi` along this edge. */ predicate phiInput(SsaPhiNode phi, SsaVariable inp) { - phi.hasInputFromBlock(inp, getOrigBlock()) and - getPhiBlock() = phi.getBasicBlock() + phi.hasInputFromBlock(inp, this.getOrigBlock()) and + this.getPhiBlock() = phi.getBasicBlock() } override string toString() { result = "edge" } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/java/ql/lib/semmle/code/xml/XML.qll b/java/ql/lib/semmle/code/xml/XML.qll index 4c762f4bf65..76f3b3cb022 100755 --- a/java/ql/lib/semmle/code/xml/XML.qll +++ b/java/ql/lib/semmle/code/xml/XML.qll @@ -108,7 +108,7 @@ class XMLParent extends @xmlparent { } /** Gets the text value contained in this XML parent. */ - string getTextValue() { result = allCharactersString() } + string getTextValue() { result = this.allCharactersString() } /** Gets a printable representation of this XML parent. */ string toString() { result = this.getName() } @@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File { XMLFile() { xmlEncoding(this, _) } /** Gets a printable representation of this XML file. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } /** Gets the name of this XML file. */ override string getName() { result = File.super.getAbsolutePath() } @@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File { * * Gets the path of this XML file. */ - deprecated string getPath() { result = getAbsolutePath() } + deprecated string getPath() { result = this.getAbsolutePath() } /** * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. * * Gets the path of the folder that contains this XML file. */ - deprecated string getFolder() { result = getParentContainer().getAbsolutePath() } + deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() } /** Gets the encoding of this XML file. */ string getEncoding() { xmlEncoding(this, result) } @@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd { */ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { /** Holds if this XML element has the given `name`. */ - predicate hasName(string name) { name = getName() } + predicate hasName(string name) { name = this.getName() } /** Gets the name of this XML element. */ override string getName() { xmlElements(this, result, _, _, _) } @@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } /** Gets a printable representation of this XML element. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } } /** diff --git a/javascript/ql/lib/semmle/javascript/XML.qll b/javascript/ql/lib/semmle/javascript/XML.qll index 4c762f4bf65..76f3b3cb022 100755 --- a/javascript/ql/lib/semmle/javascript/XML.qll +++ b/javascript/ql/lib/semmle/javascript/XML.qll @@ -108,7 +108,7 @@ class XMLParent extends @xmlparent { } /** Gets the text value contained in this XML parent. */ - string getTextValue() { result = allCharactersString() } + string getTextValue() { result = this.allCharactersString() } /** Gets a printable representation of this XML parent. */ string toString() { result = this.getName() } @@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File { XMLFile() { xmlEncoding(this, _) } /** Gets a printable representation of this XML file. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } /** Gets the name of this XML file. */ override string getName() { result = File.super.getAbsolutePath() } @@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File { * * Gets the path of this XML file. */ - deprecated string getPath() { result = getAbsolutePath() } + deprecated string getPath() { result = this.getAbsolutePath() } /** * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. * * Gets the path of the folder that contains this XML file. */ - deprecated string getFolder() { result = getParentContainer().getAbsolutePath() } + deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() } /** Gets the encoding of this XML file. */ string getEncoding() { xmlEncoding(this, result) } @@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd { */ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { /** Holds if this XML element has the given `name`. */ - predicate hasName(string name) { name = getName() } + predicate hasName(string name) { name = this.getName() } /** Gets the name of this XML element. */ override string getName() { xmlElements(this, result, _, _, _) } @@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } /** Gets a printable representation of this XML element. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } } /** 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 f43a550af57..494780d2e1b 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -937,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { } override predicate relevantFor(DataFlowCallable callable) { - recordDataFlowCallSite(getCall(), callable) + recordDataFlowCallSite(this.getCall(), callable) } override predicate matchesCall(DataFlowCall call) { call = this.getCall() } @@ -1257,7 +1257,7 @@ abstract class AccessPathFront extends TAccessPathFront { TypedContent getHead() { this = TFrontHead(result) } - predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) } + predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll index f4f73b8247c..acb029c23d9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll @@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration { predicate isSanitizer(DataFlow::Node node) { none() } final override predicate isBarrier(DataFlow::Node node) { - isSanitizer(node) or + this.isSanitizer(node) or defaultTaintSanitizer(node) } /** Holds if taint propagation into `node` is prohibited. */ predicate isSanitizerIn(DataFlow::Node node) { none() } - final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } + final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } /** Holds if taint propagation out of `node` is prohibited. */ predicate isSanitizerOut(DataFlow::Node node) { none() } - final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } + final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } + final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { + this.isSanitizerGuard(guard) + } /** * Holds if the additional taint propagation step from `node1` to `node2` @@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration { predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isAdditionalTaintStep(node1, node2) or + this.isAdditionalTaintStep(node1, node2) or defaultAdditionalTaintStep(node1, node2) } diff --git a/python/ql/lib/semmle/python/xml/XML.qll b/python/ql/lib/semmle/python/xml/XML.qll index 4c762f4bf65..76f3b3cb022 100755 --- a/python/ql/lib/semmle/python/xml/XML.qll +++ b/python/ql/lib/semmle/python/xml/XML.qll @@ -108,7 +108,7 @@ class XMLParent extends @xmlparent { } /** Gets the text value contained in this XML parent. */ - string getTextValue() { result = allCharactersString() } + string getTextValue() { result = this.allCharactersString() } /** Gets a printable representation of this XML parent. */ string toString() { result = this.getName() } @@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File { XMLFile() { xmlEncoding(this, _) } /** Gets a printable representation of this XML file. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } /** Gets the name of this XML file. */ override string getName() { result = File.super.getAbsolutePath() } @@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File { * * Gets the path of this XML file. */ - deprecated string getPath() { result = getAbsolutePath() } + deprecated string getPath() { result = this.getAbsolutePath() } /** * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. * * Gets the path of the folder that contains this XML file. */ - deprecated string getFolder() { result = getParentContainer().getAbsolutePath() } + deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() } /** Gets the encoding of this XML file. */ string getEncoding() { xmlEncoding(this, result) } @@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd { */ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { /** Holds if this XML element has the given `name`. */ - predicate hasName(string name) { name = getName() } + predicate hasName(string name) { name = this.getName() } /** Gets the name of this XML element. */ override string getName() { xmlElements(this, result, _, _, _) } @@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } /** Gets a printable representation of this XML element. */ - override string toString() { result = getName() } + override string toString() { result = this.getName() } } /** From 69ed7c543ff87b42807a598a7c8633b1c9290422 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Thu, 14 Oct 2021 11:59:59 +0100 Subject: [PATCH 279/361] C++: Remove unnecessary 'exists'. --- cpp/ql/lib/semmle/code/cpp/Type.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/Type.qll b/cpp/ql/lib/semmle/code/cpp/Type.qll index bf3defd4f40..b390e24a0fa 100644 --- a/cpp/ql/lib/semmle/code/cpp/Type.qll +++ b/cpp/ql/lib/semmle/code/cpp/Type.qll @@ -1650,7 +1650,6 @@ class RoutineType extends Type, @routinetype { i = 0 and result = "" and not exists(this.getAParameterType()) or ( - exists(this.getParameterType(i)) and if i < max(int j | exists(this.getParameterType(j))) then // Not the last one From 8049d3f73826d9db9bd0e321550b929ae0d2101d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Thu, 14 Oct 2021 12:02:57 +0100 Subject: [PATCH 280/361] Python: Remove unnecessary 'exists'. --- python/ql/lib/semmle/python/PrintAst.qll | 3 +-- .../ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/python/ql/lib/semmle/python/PrintAst.qll b/python/ql/lib/semmle/python/PrintAst.qll index e06e8bc9ffb..d76285ee3fa 100644 --- a/python/ql/lib/semmle/python/PrintAst.qll +++ b/python/ql/lib/semmle/python/PrintAst.qll @@ -52,8 +52,7 @@ private newtype TPrintAstNode = TStmtListNode(StmtList list) { shouldPrint(list.getAnItem(), _) and not list = any(Module mod).getBody() and - not forall(AstNode child | child = list.getAnItem() | isNotNeeded(child)) and - exists(list.getAnItem()) + not forall(AstNode child | child = list.getAnItem() | isNotNeeded(child)) } or TRegExpTermNode(RegExpTerm term) { exists(StrConst str | term.getRootTerm() = getParsedRegExp(str) and shouldPrint(str, _)) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll b/python/ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll index 234019a498c..c7fd7dcecf3 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll @@ -58,7 +58,6 @@ string prettyNode(DataFlow::Node node) { */ bindingset[node] string prettyNodeForInlineTest(DataFlow::Node node) { - exists(node.asExpr()) and result = prettyExpr(node.asExpr()) or exists(Expr e | e = node.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() | From ed6a182cd135af1257b986267a46b8ea214d2fab Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 14 Oct 2021 15:14:47 +0200 Subject: [PATCH 281/361] C#: Adopt inline test expectations framework --- config/identical-files.json | 3 +- csharp/ql/lib/semmle/code/csharp/Comments.qll | 2 +- .../TestUtilities/InlineExpectationsTest.qll | 346 ++++++++++++++++++ .../InlineExpectationsTestPrivate.qll | 10 + .../ql/test/TestUtilities/InlineFlowTest.qll | 110 ++++++ 5 files changed, 469 insertions(+), 2 deletions(-) create mode 100644 csharp/ql/test/TestUtilities/InlineExpectationsTest.qll create mode 100644 csharp/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll create mode 100644 csharp/ql/test/TestUtilities/InlineFlowTest.qll diff --git a/config/identical-files.json b/config/identical-files.json index f968690fc49..74d39cc691d 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -367,6 +367,7 @@ ], "Inline Test Expectations": [ "cpp/ql/test/TestUtilities/InlineExpectationsTest.qll", + "csharp/ql/test/TestUtilities/InlineExpectationsTest.qll", "java/ql/test/TestUtilities/InlineExpectationsTest.qll", "python/ql/test/TestUtilities/InlineExpectationsTest.qll" ], @@ -469,4 +470,4 @@ "javascript/ql/lib/tutorial.qll", "python/ql/lib/tutorial.qll" ] -} +} \ No newline at end of file diff --git a/csharp/ql/lib/semmle/code/csharp/Comments.qll b/csharp/ql/lib/semmle/code/csharp/Comments.qll index 41f4e5b0be8..9a611b851e8 100644 --- a/csharp/ql/lib/semmle/code/csharp/Comments.qll +++ b/csharp/ql/lib/semmle/code/csharp/Comments.qll @@ -11,7 +11,7 @@ import Location /** * A single line of comment. * - * Either a single line comment (`SingleLineComment`), an XML comment (`XmlComment`), + * Either a single line comment (`SinglelineComment`), an XML comment (`XmlComment`), * or a line in a multi-line comment (`MultilineComment`). */ class CommentLine extends @commentline { diff --git a/csharp/ql/test/TestUtilities/InlineExpectationsTest.qll b/csharp/ql/test/TestUtilities/InlineExpectationsTest.qll new file mode 100644 index 00000000000..52a790cca28 --- /dev/null +++ b/csharp/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -0,0 +1,346 @@ +/** + * Provides a library for writing QL tests whose success or failure is based on expected results + * embedded in the test source code as comments, rather than the contents of an `.expected` file + * (in that the `.expected` file should always be empty). + * + * To add this framework to a new language: + * - Add a file `InlineExpectationsTestPrivate.qll` that defines a `ExpectationComment` class. This class + * must support a `getContents` method that returns the contents of the given comment, _excluding_ + * the comment indicator itself. It should also define `toString` and `getLocation` as usual. + * + * To create a new inline expectations test: + * - Declare a class that extends `InlineExpectationsTest`. In the characteristic predicate of the + * new class, bind `this` to a unique string (usually the name of the test). + * - Override the `hasActualResult()` predicate to produce the actual results of the query. For each + * result, specify a `Location`, a text description of the element for which the result was + * reported, a short string to serve as the tag to identify expected results for this test, and the + * expected value of the result. + * - Override `getARelevantTag()` to return the set of tags that can be produced by + * `hasActualResult()`. Often this is just a single tag. + * + * Example: + * ```ql + * class ConstantValueTest extends InlineExpectationsTest { + * ConstantValueTest() { this = "ConstantValueTest" } + * + * override string getARelevantTag() { + * // We only use one tag for this test. + * result = "const" + * } + * + * override predicate hasActualResult( + * Location location, string element, string tag, string value + * ) { + * exists(Expr e | + * tag = "const" and // The tag for this test. + * value = e.getValue() and // The expected value. Will only hold for constant expressions. + * location = e.getLocation() and // The location of the result to be reported. + * element = e.toString() // The display text for the result. + * ) + * } + * } + * ``` + * + * There is no need to write a `select` clause or query predicate. All of the differences between + * expected results and actual results will be reported in the `failures()` query predicate. + * + * To annotate the test source code with an expected result, place a comment starting with a `$` on the + * same line as the expected result, with text of the following format as the body of the comment: + * + * `tag=expected-value` + * + * Where `tag` is the value of the `tag` parameter from `hasActualResult()`, and `expected-value` is + * the value of the `value` parameter from `hasActualResult()`. The `=expected-value` portion may be + * omitted, in which case `expected-value` is treated as the empty string. Multiple expectations may + * be placed in the same comment. Any actual result that + * appears on a line that does not contain a matching expected result comment will be reported with + * a message of the form "Unexpected result: tag=value". Any expected result comment for which there + * is no matching actual result will be reported with a message of the form + * "Missing result: tag=expected-value". + * + * Example: + * ```cpp + * int i = x + 5; // $ const=5 + * int j = y + (7 - 3) // $ const=7 const=3 const=4 // The result of the subtraction is a constant. + * ``` + * + * For tests that contain known missing and spurious results, it is possible to further + * annotate that a particular expected result is known to be spurious, or that a particular + * missing result is known to be missing: + * + * `$ SPURIOUS: tag=expected-value` // Spurious result + * `$ MISSING: tag=expected-value` // Missing result + * + * A spurious expectation is treated as any other expected result, except that if there is no + * matching actual result, the message will be of the form "Fixed spurious result: tag=value". A + * missing expectation is treated as if there were no expected result, except that if a + * matching expected result is found, the message will be of the form + * "Fixed missing result: tag=value". + * + * A single line can contain all the expected, spurious and missing results of that line. For instance: + * `$ tag1=value1 SPURIOUS: tag2=value2 MISSING: tag3=value3`. + * + * If the same result value is expected for two or more tags on the same line, there is a shorthand + * notation available: + * + * `tag1,tag2=expected-value` + * + * is equivalent to: + * + * `tag1=expected-value tag2=expected-value` + */ + +private import InlineExpectationsTestPrivate + +/** + * Base class for tests with inline expectations. The test extends this class to provide the actual + * results of the query, which are then compared with the expected results in comments to produce a + * list of failure messages that point out where the actual results differ from the expected + * results. + */ +abstract class InlineExpectationsTest extends string { + bindingset[this] + InlineExpectationsTest() { any() } + + /** + * Returns all tags that can be generated by this test. Most tests will only ever produce a single + * tag. Any expected result comments for a tag that is not returned by the `getARelevantTag()` + * predicate for an active test will be ignored. This makes it possible to write multiple tests in + * different `.ql` files that all query the same source code. + */ + abstract string getARelevantTag(); + + /** + * Returns the actual results of the query that is being tested. Each result consist of the + * following values: + * - `location` - The source code location of the result. Any expected result comment must appear + * on the start line of this location. + * - `element` - Display text for the element on which the result is reported. + * - `tag` - The tag that marks this result as coming from this test. This must be one of the tags + * returned by `getARelevantTag()`. + * - `value` - The value of the result, which will be matched against the value associated with + * `tag` in any expected result comment on that line. + */ + abstract predicate hasActualResult(Location location, string element, string tag, string value); + + final predicate hasFailureMessage(FailureLocatable element, string message) { + exists(ActualResult actualResult | + actualResult.getTest() = this and + element = actualResult and + ( + exists(FalseNegativeExpectation falseNegative | + falseNegative.matchesActualResult(actualResult) and + message = "Fixed missing result:" + falseNegative.getExpectationText() + ) + or + not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and + message = "Unexpected result: " + actualResult.getExpectationText() + ) + ) + or + exists(ValidExpectation expectation | + not exists(ActualResult actualResult | expectation.matchesActualResult(actualResult)) and + expectation.getTag() = getARelevantTag() and + element = expectation and + ( + expectation instanceof GoodExpectation and + message = "Missing result:" + expectation.getExpectationText() + or + expectation instanceof FalsePositiveExpectation and + message = "Fixed spurious result:" + expectation.getExpectationText() + ) + ) + or + exists(InvalidExpectation expectation | + element = expectation and + message = "Invalid expectation syntax: " + expectation.getExpectation() + ) + } +} + +/** + * RegEx pattern to match a comment containing one or more expected results. The comment must have + * `$` as its first non-whitespace character. Any subsequent character + * is treated as part of the expected results, except that the comment may contain a `//` sequence + * to treat the remainder of the line as a regular (non-interpreted) comment. + */ +private string expectationCommentPattern() { result = "\\s*\\$((?:[^/]|/[^/])*)(?://.*)?" } + +/** + * The possible columns in an expectation comment. The `TDefaultColumn` branch represents the first + * column in a comment. This column is not precedeeded by a name. `TNamedColumn(name)` represents a + * column containing expected results preceeded by the string `name:`. + */ +private newtype TColumn = + TDefaultColumn() or + TNamedColumn(string name) { name = ["MISSING", "SPURIOUS"] } + +bindingset[start, content] +private int getEndOfColumnPosition(int start, string content) { + result = + min(string name, int cand | + exists(TNamedColumn(name)) and + cand = content.indexOf(name + ":") and + cand >= start + | + cand + ) + or + not exists(string name | + exists(TNamedColumn(name)) and + content.indexOf(name + ":") >= start + ) and + result = content.length() +} + +private predicate getAnExpectation( + ExpectationComment comment, TColumn column, string expectation, string tags, string value +) { + exists(string content | + content = comment.getContents().regexpCapture(expectationCommentPattern(), 1) and + ( + column = TDefaultColumn() and + exists(int end | + end = getEndOfColumnPosition(0, content) and + expectation = content.prefix(end).regexpFind(expectationPattern(), _, _).trim() + ) + or + exists(string name, int start, int end | + column = TNamedColumn(name) and + start = content.indexOf(name + ":") + name.length() + 1 and + end = getEndOfColumnPosition(start, content) and + expectation = content.substring(start, end).regexpFind(expectationPattern(), _, _).trim() + ) + ) + ) and + tags = expectation.regexpCapture(expectationPattern(), 1) and + if exists(expectation.regexpCapture(expectationPattern(), 2)) + then value = expectation.regexpCapture(expectationPattern(), 2) + else value = "" +} + +private string getColumnString(TColumn column) { + column = TDefaultColumn() and result = "" + or + column = TNamedColumn(result) +} + +/** + * RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or + * more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character + * must not be a digit), optionally followed by `=` and the expected value. + */ +private string expectationPattern() { + exists(string tag, string tags, string value | + tag = "[A-Za-z-_][A-Za-z-_0-9]*" and + tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and + // In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`. + // For example, `b"foo"`. + value = "((?:[bru]*\"[^\"]*\"|[bru]*'[^']*'|\\S+)*)" and + result = tags + "(?:=" + value + ")?" + ) +} + +private newtype TFailureLocatable = + TActualResult( + InlineExpectationsTest test, Location location, string element, string tag, string value + ) { + test.hasActualResult(location, element, tag, value) + } or + TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) { + exists(TColumn column, string tags | + getAnExpectation(comment, column, _, tags, value) and + tag = tags.splitAt(",") and + knownFailure = getColumnString(column) + ) + } or + TInvalidExpectation(ExpectationComment comment, string expectation) { + getAnExpectation(comment, _, expectation, _, _) and + not expectation.regexpMatch(expectationPattern()) + } + +class FailureLocatable extends TFailureLocatable { + string toString() { none() } + + Location getLocation() { none() } + + final string getExpectationText() { result = getTag() + "=" + getValue() } + + string getTag() { none() } + + string getValue() { none() } +} + +class ActualResult extends FailureLocatable, TActualResult { + InlineExpectationsTest test; + Location location; + string element; + string tag; + string value; + + ActualResult() { this = TActualResult(test, location, element, tag, value) } + + override string toString() { result = element } + + override Location getLocation() { result = location } + + InlineExpectationsTest getTest() { result = test } + + override string getTag() { result = tag } + + override string getValue() { result = value } +} + +abstract private class Expectation extends FailureLocatable { + ExpectationComment comment; + + override string toString() { result = comment.toString() } + + override Location getLocation() { result = comment.getLocation() } +} + +private class ValidExpectation extends Expectation, TValidExpectation { + string tag; + string value; + string knownFailure; + + ValidExpectation() { this = TValidExpectation(comment, tag, value, knownFailure) } + + override string getTag() { result = tag } + + override string getValue() { result = value } + + string getKnownFailure() { result = knownFailure } + + predicate matchesActualResult(ActualResult actualResult) { + getLocation().getStartLine() = actualResult.getLocation().getStartLine() and + getLocation().getFile() = actualResult.getLocation().getFile() and + getTag() = actualResult.getTag() and + getValue() = actualResult.getValue() + } +} + +/* Note: These next three classes correspond to all the possible values of type `TColumn`. */ +class GoodExpectation extends ValidExpectation { + GoodExpectation() { getKnownFailure() = "" } +} + +class FalsePositiveExpectation extends ValidExpectation { + FalsePositiveExpectation() { getKnownFailure() = "SPURIOUS" } +} + +class FalseNegativeExpectation extends ValidExpectation { + FalseNegativeExpectation() { getKnownFailure() = "MISSING" } +} + +class InvalidExpectation extends Expectation, TInvalidExpectation { + string expectation; + + InvalidExpectation() { this = TInvalidExpectation(comment, expectation) } + + string getExpectation() { result = expectation } +} + +query predicate failures(FailureLocatable element, string message) { + exists(InlineExpectationsTest test | test.hasFailureMessage(element, message)) +} diff --git a/csharp/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll b/csharp/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll new file mode 100644 index 00000000000..3df85cc0fd6 --- /dev/null +++ b/csharp/ql/test/TestUtilities/InlineExpectationsTestPrivate.qll @@ -0,0 +1,10 @@ +import csharp +import semmle.code.csharp.Comments + +/** + * A class representing line comments in C# used by the InlineExpectations core code + */ +class ExpectationComment extends SinglelineComment { + /** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */ + string getContents() { result = this.getText() } +} diff --git a/csharp/ql/test/TestUtilities/InlineFlowTest.qll b/csharp/ql/test/TestUtilities/InlineFlowTest.qll new file mode 100644 index 00000000000..6bd44e81df3 --- /dev/null +++ b/csharp/ql/test/TestUtilities/InlineFlowTest.qll @@ -0,0 +1,110 @@ +/** + * Provides a simple base test for flow-related tests using inline expectations. + * + * Example for a test.ql: + * ```ql + * import csharp + * import DataFlow::PathGraph + * import TestUtilities.InlineFlowTest + * + * from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf + * where conf.hasFlowPath(source, sink) + * select sink, source, sink, "$@", source, source.toString() + * ``` + * + * To declare expecations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files. + * Example of the corresponding test file, e.g. Test.cs + * ```csharp + * public class Test + * { + * object Source() { return null; } + * string Taint() { return null; } + * void Sink(object o) { } + * + * public void test() + * { + * var s = Source(1); + * Sink(s); // $ hasValueFlow=1 + * var t = "foo" + Taint(2); + * Sink(t); // $ hasTaintFlow=2 + * } + * } + * ``` + * + * If you're not interested in a specific flow type, you can disable either value or taint flow expectations as follows: + * ```ql + * class HasFlowTest extends InlineFlowTest { + * override DataFlow::Configuration getTaintFlowConfig() { none() } + * + * override DataFlow::Configuration getValueFlowConfig() { none() } + * } + * ``` + * + * If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`. + */ + +import csharp +import TestUtilities.InlineExpectationsTest + +private predicate defaultSource(DataFlow::Node src) { + src.asExpr().(MethodCall).getTarget().getUndecoratedName() = ["Source", "Taint"] +} + +private predicate defaultSink(DataFlow::Node sink) { + exists(MethodCall mc | mc.getTarget().hasUndecoratedName("Sink") | + sink.asExpr() = mc.getAnArgument() + ) +} + +class DefaultValueFlowConf extends DataFlow::Configuration { + DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" } + + override predicate isSource(DataFlow::Node n) { defaultSource(n) } + + override predicate isSink(DataFlow::Node n) { defaultSink(n) } + + override int fieldFlowBranchLimit() { result = 1000 } +} + +class DefaultTaintFlowConf extends TaintTracking::Configuration { + DefaultTaintFlowConf() { this = "qltest:defaultTaintFlowConf" } + + override predicate isSource(DataFlow::Node n) { defaultSource(n) } + + override predicate isSink(DataFlow::Node n) { defaultSink(n) } + + override int fieldFlowBranchLimit() { result = 1000 } +} + +private string getSourceArgString(DataFlow::Node src) { + defaultSource(src) and + src.asExpr().(MethodCall).getAnArgument().getValue() = result +} + +class InlineFlowTest extends InlineExpectationsTest { + InlineFlowTest() { this = "HasFlowTest" } + + override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" + ) + or + tag = "hasTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink | + getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" + ) + } + + DataFlow::Configuration getValueFlowConfig() { result = any(DefaultValueFlowConf config) } + + DataFlow::Configuration getTaintFlowConfig() { result = any(DefaultTaintFlowConf config) } +} From 083214f85aac3a712c46d0b5b873fa34649f6ba9 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 14 Oct 2021 15:19:37 +0200 Subject: [PATCH 282/361] C#: Use inline test expectations for `FieldFlow.ql` --- .../test/library-tests/dataflow/fields/A.cs | 50 +- .../test/library-tests/dataflow/fields/B.cs | 10 +- .../test/library-tests/dataflow/fields/C.cs | 26 +- .../test/library-tests/dataflow/fields/D.cs | 22 +- .../test/library-tests/dataflow/fields/E.cs | 6 +- .../test/library-tests/dataflow/fields/F.cs | 18 +- .../dataflow/fields/FieldFlow.expected | 1329 ++++++++++++++--- .../dataflow/fields/FieldFlow.ql | 16 +- .../test/library-tests/dataflow/fields/G.cs | 16 +- .../test/library-tests/dataflow/fields/H.cs | 46 +- .../test/library-tests/dataflow/fields/I.cs | 18 +- .../test/library-tests/dataflow/fields/J.cs | 14 +- 12 files changed, 1227 insertions(+), 344 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/fields/A.cs b/csharp/ql/test/library-tests/dataflow/fields/A.cs index d56ab3adc1e..663bbb1dab6 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/A.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/A.cs @@ -2,35 +2,35 @@ public class A { public void M1() { - var c = new C(); + var c = Source<C>(1); var b = B.Make(c); - Sink(b.c); // flow + Sink(b.c); // $ hasValueFlow=1 } public void M2() { var b = new B(); - b.Set(new C1()); - Sink(b.Get()); // flow - Sink((new B(new C())).Get()); // flow + b.Set(Source<C1>(2.1)); + Sink(b.Get()); // $ hasValueFlow=2.1 + Sink((new B(Source<C>(2.2))).Get()); // $ hasValueFlow=2.2 } public void M3() { var b1 = new B(); B b2; - b2 = SetOnB(b1, new C2()); - Sink(b1.c); // no flow - Sink(b2.c); // flow + b2 = SetOnB(b1, Source<C2>(3)); + Sink(b1.c); + Sink(b2.c); // $ hasValueFlow=3 } public void M4() { var b1 = new B(); B b2; - b2 = SetOnBWrap(b1, new C2()); - Sink(b1.c); // no flow - Sink(b2.c); // flow + b2 = SetOnBWrap(b1, Source<C2>(4)); + Sink(b1.c); + Sink(b2.c); // $ hasValueFlow=4 } public B SetOnBWrap(B b1, C c) @@ -52,7 +52,7 @@ public class A public void M5() { - var a = new A(); + var a = Source<A>(5); C1 c1 = new C1(); c1.a = a; M6(c1); @@ -61,7 +61,7 @@ public class A { if (c is C1) { - Sink(((C1)c).a); // flow + Sink(((C1)c).a); // $ hasValueFlow=5 } C cc; if (c is C2) @@ -80,13 +80,13 @@ public class A public void M7(B b) { - b.Set(new C()); + b.Set(Source<C>(7)); } public void M8() { var b = new B(); M7(b); - Sink(b.c); // flow + Sink(b.c); // $ hasValueFlow=7 } public class D @@ -94,33 +94,33 @@ public class A public B b; public D(B b, bool x) { - b.c = new C(); - this.b = x ? b : new B(); + b.c = Source<C>(9.1); + this.b = x ? b : Source<B>(9.2); } } public void M9() { - var b = new B(); + var b = Source<B>(9.3); var d = new D(b, R()); - Sink(d.b); // flow x2 - Sink(d.b.c); // flow - Sink(b.c); // flow + Sink(d.b); // $ hasValueFlow=9.2 $ hasValueFlow=9.3 + Sink(d.b.c); // $ hasValueFlow=9.1 + Sink(b.c); // $ hasValueFlow=9.1 } public void M10() { - var b = new B(); + var b = Source<B>(10); var l1 = new MyList(b, new MyList(null, null)); var l2 = new MyList(null, l1); var l3 = new MyList(null, l2); Sink(l3.head); // no flow, b is nested beneath at least one .next Sink(l3.next.head); // flow, the precise nesting depth isn't tracked - Sink(l3.next.next.head); // flow + Sink(l3.next.next.head); // $ hasValueFlow=10 Sink(l3.next.next.next.head); // no flow for (var l = l3; l != null; l = l.next) { - Sink(l.head); // flow + Sink(l.head); // $ hasValueFlow=10 } } @@ -160,4 +160,6 @@ public class A this.next = next; } } + + static T Source<T>(object source) => throw null; } diff --git a/csharp/ql/test/library-tests/dataflow/fields/B.cs b/csharp/ql/test/library-tests/dataflow/fields/B.cs index f25b8959d22..84c87e7298f 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/B.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/B.cs @@ -2,20 +2,20 @@ public class B { public void M1() { - var e = new Elem(); + var e = Source<Elem>(1); var b1 = new Box1(e, null); var b2 = new Box2(b1); - Sink(b2.box1.elem1); // flow + Sink(b2.box1.elem1); // $ hasValueFlow=1 Sink(b2.box1.elem2); // no flow } public void M2() { - var e = new Elem(); + var e = Source<Elem>(2); var b1 = new Box1(null, e); var b2 = new Box2(b1); Sink(b2.box1.elem1); // no flow - Sink(b2.box1.elem2); // flow + Sink(b2.box1.elem2); // $ hasValueFlow=2 } public static void Sink(object o) { } @@ -41,4 +41,6 @@ public class B this.box1 = b1; } } + + static T Source<T>(object source) => throw null; } diff --git a/csharp/ql/test/library-tests/dataflow/fields/C.cs b/csharp/ql/test/library-tests/dataflow/fields/C.cs index da7b5f14fee..9ebe9ec27ed 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/C.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/C.cs @@ -1,11 +1,11 @@ public class C { - private Elem s1 = new Elem(); - private readonly Elem s2 = new Elem(); + private Elem s1 = Source<Elem>(1); + private readonly Elem s2 = Source<Elem>(2); private Elem s3; - private static Elem s4 = new Elem(); - private Elem s5 { get; set; } = new Elem(); - private Elem s6 { get => new Elem(); set { } } + private static Elem s4 = Source<Elem>(4); + private Elem s5 { get; set; } = Source<Elem>(5); + private Elem s6 { get => Source<Elem>(6); set { } } void M1() { @@ -15,20 +15,22 @@ public class C private C() { - this.s3 = new Elem(); + this.s3 = Source<Elem>(3); } public void M2() { - Sink(s1); - Sink(s2); - Sink(s3); - Sink(s4); - Sink(s5); - Sink(s6); + Sink(s1); // $ hasValueFlow=1 + Sink(s2); // $ hasValueFlow=2 + Sink(s3); // $ hasValueFlow=3 + Sink(s4); // $ hasValueFlow=4 + Sink(s5); // $ hasValueFlow=5 + Sink(s6); // $ hasValueFlow=6 } public static void Sink(object o) { } + static T Source<T>(object source) => throw null; + public class Elem { } } diff --git a/csharp/ql/test/library-tests/dataflow/fields/D.cs b/csharp/ql/test/library-tests/dataflow/fields/D.cs index 505f56bd388..7a3fe985137 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/D.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/D.cs @@ -26,26 +26,28 @@ public class D private void M() { - var o = new object(); + var o = Source<object>(1); var d = Create(o, null, null); - Sink(d.AutoProp); // flow + Sink(d.AutoProp); // $ hasValueFlow=1 Sink(d.TrivialProp); // no flow Sink(d.trivialPropField); // no flow Sink(d.ComplexProp); // no flow - d = Create(null, o, null); + d = Create(null, Source<object>(2), null); Sink(d.AutoProp); // no flow - Sink(d.TrivialProp); // flow - Sink(d.trivialPropField); // flow - Sink(d.ComplexProp); // flow + Sink(d.TrivialProp); // $ hasValueFlow=2 + Sink(d.trivialPropField); // $ hasValueFlow=2 + Sink(d.ComplexProp); // $ hasValueFlow=2 - d = Create(null, null, o); + d = Create(null, null, Source<object>(3)); Sink(d.AutoProp); // no flow - Sink(d.TrivialProp); // flow - Sink(d.trivialPropField); // flow - Sink(d.ComplexProp); // flow + Sink(d.TrivialProp); // $ hasValueFlow=3 + Sink(d.trivialPropField); // $ hasValueFlow=3 + Sink(d.ComplexProp); // $ hasValueFlow=3 } public static void Sink(object o) { } + + static T Source<T>(object source) => throw null; } diff --git a/csharp/ql/test/library-tests/dataflow/fields/E.cs b/csharp/ql/test/library-tests/dataflow/fields/E.cs index 45ee1994256..975952c8f64 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/E.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/E.cs @@ -19,9 +19,9 @@ public class E private void M() { - var o = new object(); + var o = Source<object>(1); var s = CreateS(o); - Sink(s.Field); // flow + Sink(s.Field); // $ hasValueFlow=1 s = new S(); NotASetter(s, o); @@ -29,4 +29,6 @@ public class E } public static void Sink(object o) { } + + static T Source<T>(object source) => throw null; } diff --git a/csharp/ql/test/library-tests/dataflow/fields/F.cs b/csharp/ql/test/library-tests/dataflow/fields/F.cs index 81076f72a93..2e7cd9b6e2c 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/F.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/F.cs @@ -7,23 +7,25 @@ public class F private void M() { - var o = new object(); + var o = Source<object>(1); var f = Create(o, null); - Sink(f.Field1); // flow + Sink(f.Field1); // $ hasValueFlow=1 Sink(f.Field2); // no flow - f = Create(null, o); + f = Create(null, Source<object>(2)); Sink(f.Field1); // no flow - Sink(f.Field2); // flow + Sink(f.Field2); // $ hasValueFlow=2 - f = new F() { Field1 = o }; - Sink(f.Field1); // flow + f = new F() { Field1 = Source<object>(3) }; + Sink(f.Field1); // $ hasValueFlow=3 Sink(f.Field2); // no flow - f = new F() { Field2 = o }; + f = new F() { Field2 = Source<object>(4) }; Sink(f.Field1); // no flow - Sink(f.Field2); // flow + Sink(f.Field2); // $ hasValueFlow=4 } public static void Sink(object o) { } + + static T Source<T>(object source) => throw null; } diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index e8a74f347dc..14e2c3d27b7 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -1,946 +1,1821 @@ +failures edges -| A.cs:5:17:5:23 | object creation of type C : C | A.cs:6:24:6:24 | access to local variable c : C | +| A.cs:5:17:5:28 | call to method Source<C> : C | A.cs:6:24:6:24 | access to local variable c : C | +| A.cs:5:17:5:28 | call to method Source<C> : C | A.cs:6:24:6:24 | access to local variable c : C | +| A.cs:6:17:6:25 | call to method Make [field c] : C | A.cs:7:14:7:14 | access to local variable b [field c] : C | | A.cs:6:17:6:25 | call to method Make [field c] : C | A.cs:7:14:7:14 | access to local variable b [field c] : C | | A.cs:6:24:6:24 | access to local variable c : C | A.cs:6:17:6:25 | call to method Make [field c] : C | +| A.cs:6:24:6:24 | access to local variable c : C | A.cs:6:17:6:25 | call to method Make [field c] : C | +| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | | A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | | A.cs:7:14:7:14 | access to local variable b [field c] : C | A.cs:7:14:7:16 | access to field c | +| A.cs:7:14:7:14 | access to local variable b [field c] : C | A.cs:7:14:7:16 | access to field c | | A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | A.cs:14:14:14:14 | access to local variable b [field c] : C1 | -| A.cs:13:15:13:22 | object creation of type C1 : C1 | A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | -| A.cs:13:15:13:22 | object creation of type C1 : C1 | A.cs:145:27:145:27 | c : C1 | +| A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | A.cs:14:14:14:14 | access to local variable b [field c] : C1 | +| A.cs:13:15:13:29 | call to method Source<C1> : C1 | A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | +| A.cs:13:15:13:29 | call to method Source<C1> : C1 | A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | +| A.cs:13:15:13:29 | call to method Source<C1> : C1 | A.cs:145:27:145:27 | c : C1 | +| A.cs:13:15:13:29 | call to method Source<C1> : C1 | A.cs:145:27:145:27 | c : C1 | +| A.cs:14:14:14:14 | access to local variable b [field c] : C1 | A.cs:14:14:14:20 | call to method Get | | A.cs:14:14:14:14 | access to local variable b [field c] : C1 | A.cs:14:14:14:20 | call to method Get | | A.cs:14:14:14:14 | access to local variable b [field c] : C1 | A.cs:146:18:146:20 | this [field c] : C1 | -| A.cs:15:15:15:28 | object creation of type B [field c] : C | A.cs:15:14:15:35 | call to method Get | -| A.cs:15:15:15:28 | object creation of type B [field c] : C | A.cs:146:18:146:20 | this [field c] : C | -| A.cs:15:21:15:27 | object creation of type C : C | A.cs:15:15:15:28 | object creation of type B [field c] : C | -| A.cs:15:21:15:27 | object creation of type C : C | A.cs:141:20:141:20 | c : C | -| A.cs:22:14:22:33 | call to method SetOnB [field c] : C2 | A.cs:24:14:24:15 | access to local variable b2 [field c] : C2 | -| A.cs:22:25:22:32 | object creation of type C2 : C2 | A.cs:22:14:22:33 | call to method SetOnB [field c] : C2 | -| A.cs:22:25:22:32 | object creation of type C2 : C2 | A.cs:42:29:42:29 | c : C2 | +| A.cs:14:14:14:14 | access to local variable b [field c] : C1 | A.cs:146:18:146:20 | this [field c] : C1 | +| A.cs:15:15:15:35 | object creation of type B [field c] : C | A.cs:15:14:15:42 | call to method Get | +| A.cs:15:15:15:35 | object creation of type B [field c] : C | A.cs:15:14:15:42 | call to method Get | +| A.cs:15:15:15:35 | object creation of type B [field c] : C | A.cs:146:18:146:20 | this [field c] : C | +| A.cs:15:15:15:35 | object creation of type B [field c] : C | A.cs:146:18:146:20 | this [field c] : C | +| A.cs:15:21:15:34 | call to method Source<C> : C | A.cs:15:15:15:35 | object creation of type B [field c] : C | +| A.cs:15:21:15:34 | call to method Source<C> : C | A.cs:15:15:15:35 | object creation of type B [field c] : C | +| A.cs:15:21:15:34 | call to method Source<C> : C | A.cs:141:20:141:20 | c : C | +| A.cs:15:21:15:34 | call to method Source<C> : C | A.cs:141:20:141:20 | c : C | +| A.cs:22:14:22:38 | call to method SetOnB [field c] : C2 | A.cs:24:14:24:15 | access to local variable b2 [field c] : C2 | +| A.cs:22:14:22:38 | call to method SetOnB [field c] : C2 | A.cs:24:14:24:15 | access to local variable b2 [field c] : C2 | +| A.cs:22:25:22:37 | call to method Source<C2> : C2 | A.cs:22:14:22:38 | call to method SetOnB [field c] : C2 | +| A.cs:22:25:22:37 | call to method Source<C2> : C2 | A.cs:22:14:22:38 | call to method SetOnB [field c] : C2 | +| A.cs:22:25:22:37 | call to method Source<C2> : C2 | A.cs:42:29:42:29 | c : C2 | +| A.cs:22:25:22:37 | call to method Source<C2> : C2 | A.cs:42:29:42:29 | c : C2 | | A.cs:24:14:24:15 | access to local variable b2 [field c] : C2 | A.cs:24:14:24:17 | access to field c | -| A.cs:31:14:31:37 | call to method SetOnBWrap [field c] : C2 | A.cs:33:14:33:15 | access to local variable b2 [field c] : C2 | -| A.cs:31:29:31:36 | object creation of type C2 : C2 | A.cs:31:14:31:37 | call to method SetOnBWrap [field c] : C2 | -| A.cs:31:29:31:36 | object creation of type C2 : C2 | A.cs:36:33:36:33 | c : C2 | +| A.cs:24:14:24:15 | access to local variable b2 [field c] : C2 | A.cs:24:14:24:17 | access to field c | +| A.cs:31:14:31:42 | call to method SetOnBWrap [field c] : C2 | A.cs:33:14:33:15 | access to local variable b2 [field c] : C2 | +| A.cs:31:14:31:42 | call to method SetOnBWrap [field c] : C2 | A.cs:33:14:33:15 | access to local variable b2 [field c] : C2 | +| A.cs:31:29:31:41 | call to method Source<C2> : C2 | A.cs:31:14:31:42 | call to method SetOnBWrap [field c] : C2 | +| A.cs:31:29:31:41 | call to method Source<C2> : C2 | A.cs:31:14:31:42 | call to method SetOnBWrap [field c] : C2 | +| A.cs:31:29:31:41 | call to method Source<C2> : C2 | A.cs:36:33:36:33 | c : C2 | +| A.cs:31:29:31:41 | call to method Source<C2> : C2 | A.cs:36:33:36:33 | c : C2 | +| A.cs:33:14:33:15 | access to local variable b2 [field c] : C2 | A.cs:33:14:33:17 | access to field c | | A.cs:33:14:33:15 | access to local variable b2 [field c] : C2 | A.cs:33:14:33:17 | access to field c | | A.cs:36:33:36:33 | c : C2 | A.cs:38:29:38:29 | access to parameter c : C2 | +| A.cs:36:33:36:33 | c : C2 | A.cs:38:29:38:29 | access to parameter c : C2 | +| A.cs:38:18:38:30 | call to method SetOnB [field c] : C2 | A.cs:39:16:39:28 | ... ? ... : ... [field c] : C2 | | A.cs:38:18:38:30 | call to method SetOnB [field c] : C2 | A.cs:39:16:39:28 | ... ? ... : ... [field c] : C2 | | A.cs:38:29:38:29 | access to parameter c : C2 | A.cs:38:18:38:30 | call to method SetOnB [field c] : C2 | +| A.cs:38:29:38:29 | access to parameter c : C2 | A.cs:38:18:38:30 | call to method SetOnB [field c] : C2 | +| A.cs:38:29:38:29 | access to parameter c : C2 | A.cs:42:29:42:29 | c : C2 | | A.cs:38:29:38:29 | access to parameter c : C2 | A.cs:42:29:42:29 | c : C2 | | A.cs:42:29:42:29 | c : C2 | A.cs:47:20:47:20 | access to parameter c : C2 | +| A.cs:42:29:42:29 | c : C2 | A.cs:47:20:47:20 | access to parameter c : C2 | +| A.cs:47:13:47:14 | [post] access to local variable b2 [field c] : C2 | A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | | A.cs:47:13:47:14 | [post] access to local variable b2 [field c] : C2 | A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | | A.cs:47:20:47:20 | access to parameter c : C2 | A.cs:47:13:47:14 | [post] access to local variable b2 [field c] : C2 | +| A.cs:47:20:47:20 | access to parameter c : C2 | A.cs:47:13:47:14 | [post] access to local variable b2 [field c] : C2 | | A.cs:47:20:47:20 | access to parameter c : C2 | A.cs:145:27:145:27 | c : C2 | -| A.cs:55:17:55:23 | object creation of type A : A | A.cs:57:16:57:16 | access to local variable a : A | +| A.cs:47:20:47:20 | access to parameter c : C2 | A.cs:145:27:145:27 | c : C2 | +| A.cs:55:17:55:28 | call to method Source<A> : A | A.cs:57:16:57:16 | access to local variable a : A | +| A.cs:55:17:55:28 | call to method Source<A> : A | A.cs:57:16:57:16 | access to local variable a : A | +| A.cs:57:9:57:10 | [post] access to local variable c1 [field a] : A | A.cs:58:12:58:13 | access to local variable c1 [field a] : A | | A.cs:57:9:57:10 | [post] access to local variable c1 [field a] : A | A.cs:58:12:58:13 | access to local variable c1 [field a] : A | | A.cs:57:16:57:16 | access to local variable a : A | A.cs:57:9:57:10 | [post] access to local variable c1 [field a] : A | +| A.cs:57:16:57:16 | access to local variable a : A | A.cs:57:9:57:10 | [post] access to local variable c1 [field a] : A | +| A.cs:58:12:58:13 | access to local variable c1 [field a] : A | A.cs:60:22:60:22 | c [field a] : A | | A.cs:58:12:58:13 | access to local variable c1 [field a] : A | A.cs:60:22:60:22 | c [field a] : A | | A.cs:60:22:60:22 | c [field a] : A | A.cs:64:19:64:23 | (...) ... [field a] : A | +| A.cs:60:22:60:22 | c [field a] : A | A.cs:64:19:64:23 | (...) ... [field a] : A | +| A.cs:64:19:64:23 | (...) ... [field a] : A | A.cs:64:18:64:26 | access to field a | | A.cs:64:19:64:23 | (...) ... [field a] : A | A.cs:64:18:64:26 | access to field a | | A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | A.cs:88:12:88:12 | [post] access to local variable b [field c] : C | -| A.cs:83:15:83:21 | object creation of type C : C | A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | -| A.cs:83:15:83:21 | object creation of type C : C | A.cs:145:27:145:27 | c : C | +| A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | A.cs:88:12:88:12 | [post] access to local variable b [field c] : C | +| A.cs:83:15:83:26 | call to method Source<C> : C | A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | +| A.cs:83:15:83:26 | call to method Source<C> : C | A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | +| A.cs:83:15:83:26 | call to method Source<C> : C | A.cs:145:27:145:27 | c : C | +| A.cs:83:15:83:26 | call to method Source<C> : C | A.cs:145:27:145:27 | c : C | +| A.cs:88:12:88:12 | [post] access to local variable b [field c] : C | A.cs:89:14:89:14 | access to local variable b [field c] : C | | A.cs:88:12:88:12 | [post] access to local variable b [field c] : C | A.cs:89:14:89:14 | access to local variable b [field c] : C | | A.cs:89:14:89:14 | access to local variable b [field c] : C | A.cs:89:14:89:16 | access to field c | +| A.cs:89:14:89:14 | access to local variable b [field c] : C | A.cs:89:14:89:16 | access to field c | | A.cs:95:20:95:20 | b : B | A.cs:97:13:97:13 | access to parameter b : B | -| A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | A.cs:98:22:98:36 | ... ? ... : ... [field c] : C | +| A.cs:95:20:95:20 | b : B | A.cs:97:13:97:13 | access to parameter b : B | +| A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | A.cs:98:22:98:43 | ... ? ... : ... [field c] : C | +| A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | A.cs:98:22:98:43 | ... ? ... : ... [field c] : C | | A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | A.cs:105:23:105:23 | [post] access to local variable b [field c] : C | -| A.cs:97:13:97:13 | access to parameter b : B | A.cs:98:22:98:36 | ... ? ... : ... : B | -| A.cs:97:19:97:25 | object creation of type C : C | A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | +| A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | A.cs:105:23:105:23 | [post] access to local variable b [field c] : C | +| A.cs:97:13:97:13 | access to parameter b : B | A.cs:98:22:98:43 | ... ? ... : ... : B | +| A.cs:97:13:97:13 | access to parameter b : B | A.cs:98:22:98:43 | ... ? ... : ... : B | +| A.cs:97:19:97:32 | call to method Source<C> : C | A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | +| A.cs:97:19:97:32 | call to method Source<C> : C | A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | +| A.cs:98:13:98:16 | [post] this access [field b, field c] : C | A.cs:105:17:105:29 | object creation of type D [field b, field c] : C | | A.cs:98:13:98:16 | [post] this access [field b, field c] : C | A.cs:105:17:105:29 | object creation of type D [field b, field c] : C | | A.cs:98:13:98:16 | [post] this access [field b] : B | A.cs:105:17:105:29 | object creation of type D [field b] : B | -| A.cs:98:22:98:36 | ... ? ... : ... : B | A.cs:98:13:98:16 | [post] this access [field b] : B | -| A.cs:98:22:98:36 | ... ? ... : ... : B | A.cs:98:13:98:16 | [post] this access [field b] : B | -| A.cs:98:22:98:36 | ... ? ... : ... [field c] : C | A.cs:98:13:98:16 | [post] this access [field b, field c] : C | -| A.cs:98:30:98:36 | object creation of type B : B | A.cs:98:22:98:36 | ... ? ... : ... : B | -| A.cs:104:17:104:23 | object creation of type B : B | A.cs:105:23:105:23 | access to local variable b : B | +| A.cs:98:13:98:16 | [post] this access [field b] : B | A.cs:105:17:105:29 | object creation of type D [field b] : B | +| A.cs:98:22:98:43 | ... ? ... : ... : B | A.cs:98:13:98:16 | [post] this access [field b] : B | +| A.cs:98:22:98:43 | ... ? ... : ... : B | A.cs:98:13:98:16 | [post] this access [field b] : B | +| A.cs:98:22:98:43 | ... ? ... : ... : B | A.cs:98:13:98:16 | [post] this access [field b] : B | +| A.cs:98:22:98:43 | ... ? ... : ... : B | A.cs:98:13:98:16 | [post] this access [field b] : B | +| A.cs:98:22:98:43 | ... ? ... : ... [field c] : C | A.cs:98:13:98:16 | [post] this access [field b, field c] : C | +| A.cs:98:22:98:43 | ... ? ... : ... [field c] : C | A.cs:98:13:98:16 | [post] this access [field b, field c] : C | +| A.cs:98:30:98:43 | call to method Source<B> : B | A.cs:98:22:98:43 | ... ? ... : ... : B | +| A.cs:98:30:98:43 | call to method Source<B> : B | A.cs:98:22:98:43 | ... ? ... : ... : B | +| A.cs:104:17:104:30 | call to method Source<B> : B | A.cs:105:23:105:23 | access to local variable b : B | +| A.cs:104:17:104:30 | call to method Source<B> : B | A.cs:105:23:105:23 | access to local variable b : B | +| A.cs:105:17:105:29 | object creation of type D [field b, field c] : C | A.cs:107:14:107:14 | access to local variable d [field b, field c] : C | | A.cs:105:17:105:29 | object creation of type D [field b, field c] : C | A.cs:107:14:107:14 | access to local variable d [field b, field c] : C | | A.cs:105:17:105:29 | object creation of type D [field b] : B | A.cs:106:14:106:14 | access to local variable d [field b] : B | +| A.cs:105:17:105:29 | object creation of type D [field b] : B | A.cs:106:14:106:14 | access to local variable d [field b] : B | +| A.cs:105:23:105:23 | [post] access to local variable b [field c] : C | A.cs:108:14:108:14 | access to local variable b [field c] : C | | A.cs:105:23:105:23 | [post] access to local variable b [field c] : C | A.cs:108:14:108:14 | access to local variable b [field c] : C | | A.cs:105:23:105:23 | access to local variable b : B | A.cs:95:20:95:20 | b : B | +| A.cs:105:23:105:23 | access to local variable b : B | A.cs:95:20:95:20 | b : B | +| A.cs:105:23:105:23 | access to local variable b : B | A.cs:105:17:105:29 | object creation of type D [field b] : B | | A.cs:105:23:105:23 | access to local variable b : B | A.cs:105:17:105:29 | object creation of type D [field b] : B | | A.cs:106:14:106:14 | access to local variable d [field b] : B | A.cs:106:14:106:16 | access to field b | +| A.cs:106:14:106:14 | access to local variable d [field b] : B | A.cs:106:14:106:16 | access to field b | +| A.cs:107:14:107:14 | access to local variable d [field b, field c] : C | A.cs:107:14:107:16 | access to field b [field c] : C | | A.cs:107:14:107:14 | access to local variable d [field b, field c] : C | A.cs:107:14:107:16 | access to field b [field c] : C | | A.cs:107:14:107:16 | access to field b [field c] : C | A.cs:107:14:107:18 | access to field c | +| A.cs:107:14:107:16 | access to field b [field c] : C | A.cs:107:14:107:18 | access to field c | | A.cs:108:14:108:14 | access to local variable b [field c] : C | A.cs:108:14:108:16 | access to field c | -| A.cs:113:17:113:23 | object creation of type B : B | A.cs:114:29:114:29 | access to local variable b : B | +| A.cs:108:14:108:14 | access to local variable b [field c] : C | A.cs:108:14:108:16 | access to field c | +| A.cs:113:17:113:29 | call to method Source<B> : B | A.cs:114:29:114:29 | access to local variable b : B | +| A.cs:113:17:113:29 | call to method Source<B> : B | A.cs:114:29:114:29 | access to local variable b : B | +| A.cs:114:18:114:54 | object creation of type MyList [field head] : B | A.cs:115:35:115:36 | access to local variable l1 [field head] : B | | A.cs:114:18:114:54 | object creation of type MyList [field head] : B | A.cs:115:35:115:36 | access to local variable l1 [field head] : B | | A.cs:114:29:114:29 | access to local variable b : B | A.cs:114:18:114:54 | object creation of type MyList [field head] : B | +| A.cs:114:29:114:29 | access to local variable b : B | A.cs:114:18:114:54 | object creation of type MyList [field head] : B | +| A.cs:114:29:114:29 | access to local variable b : B | A.cs:157:25:157:28 | head : B | | A.cs:114:29:114:29 | access to local variable b : B | A.cs:157:25:157:28 | head : B | | A.cs:115:18:115:37 | object creation of type MyList [field next, field head] : B | A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | +| A.cs:115:18:115:37 | object creation of type MyList [field next, field head] : B | A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | +| A.cs:115:35:115:36 | access to local variable l1 [field head] : B | A.cs:115:18:115:37 | object creation of type MyList [field next, field head] : B | | A.cs:115:35:115:36 | access to local variable l1 [field head] : B | A.cs:115:18:115:37 | object creation of type MyList [field next, field head] : B | | A.cs:115:35:115:36 | access to local variable l1 [field head] : B | A.cs:157:38:157:41 | next [field head] : B | +| A.cs:115:35:115:36 | access to local variable l1 [field head] : B | A.cs:157:38:157:41 | next [field head] : B | +| A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | A.cs:119:14:119:15 | access to local variable l3 [field next, field next, field head] : B | | A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | A.cs:119:14:119:15 | access to local variable l3 [field next, field next, field head] : B | | A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | A.cs:121:41:121:41 | access to local variable l [field next, field next, field head] : B | +| A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | A.cs:121:41:121:41 | access to local variable l [field next, field next, field head] : B | +| A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | | A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | | A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | A.cs:157:38:157:41 | next [field next, field head] : B | +| A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | A.cs:157:38:157:41 | next [field next, field head] : B | +| A.cs:119:14:119:15 | access to local variable l3 [field next, field next, field head] : B | A.cs:119:14:119:20 | access to field next [field next, field head] : B | | A.cs:119:14:119:15 | access to local variable l3 [field next, field next, field head] : B | A.cs:119:14:119:20 | access to field next [field next, field head] : B | | A.cs:119:14:119:20 | access to field next [field next, field head] : B | A.cs:119:14:119:25 | access to field next [field head] : B | +| A.cs:119:14:119:20 | access to field next [field next, field head] : B | A.cs:119:14:119:25 | access to field next [field head] : B | +| A.cs:119:14:119:25 | access to field next [field head] : B | A.cs:119:14:119:30 | access to field head | | A.cs:119:14:119:25 | access to field next [field head] : B | A.cs:119:14:119:30 | access to field head | | A.cs:121:41:121:41 | access to local variable l [field next, field head] : B | A.cs:121:41:121:46 | access to field next [field head] : B | +| A.cs:121:41:121:41 | access to local variable l [field next, field head] : B | A.cs:121:41:121:46 | access to field next [field head] : B | +| A.cs:121:41:121:41 | access to local variable l [field next, field next, field head] : B | A.cs:121:41:121:46 | access to field next [field next, field head] : B | | A.cs:121:41:121:41 | access to local variable l [field next, field next, field head] : B | A.cs:121:41:121:46 | access to field next [field next, field head] : B | | A.cs:121:41:121:46 | access to field next [field head] : B | A.cs:123:18:123:18 | access to local variable l [field head] : B | +| A.cs:121:41:121:46 | access to field next [field head] : B | A.cs:123:18:123:18 | access to local variable l [field head] : B | +| A.cs:121:41:121:46 | access to field next [field next, field head] : B | A.cs:121:41:121:41 | access to local variable l [field next, field head] : B | | A.cs:121:41:121:46 | access to field next [field next, field head] : B | A.cs:121:41:121:41 | access to local variable l [field next, field head] : B | | A.cs:123:18:123:18 | access to local variable l [field head] : B | A.cs:123:18:123:23 | access to field head | +| A.cs:123:18:123:18 | access to local variable l [field head] : B | A.cs:123:18:123:23 | access to field head | +| A.cs:141:20:141:20 | c : C | A.cs:143:22:143:22 | access to parameter c : C | | A.cs:141:20:141:20 | c : C | A.cs:143:22:143:22 | access to parameter c : C | | A.cs:143:22:143:22 | access to parameter c : C | A.cs:143:13:143:16 | [post] this access [field c] : C | +| A.cs:143:22:143:22 | access to parameter c : C | A.cs:143:13:143:16 | [post] this access [field c] : C | +| A.cs:145:27:145:27 | c : C | A.cs:145:41:145:41 | access to parameter c : C | | A.cs:145:27:145:27 | c : C | A.cs:145:41:145:41 | access to parameter c : C | | A.cs:145:27:145:27 | c : C1 | A.cs:145:41:145:41 | access to parameter c : C1 | +| A.cs:145:27:145:27 | c : C1 | A.cs:145:41:145:41 | access to parameter c : C1 | +| A.cs:145:27:145:27 | c : C2 | A.cs:145:41:145:41 | access to parameter c : C2 | | A.cs:145:27:145:27 | c : C2 | A.cs:145:41:145:41 | access to parameter c : C2 | | A.cs:145:41:145:41 | access to parameter c : C | A.cs:145:32:145:35 | [post] this access [field c] : C | +| A.cs:145:41:145:41 | access to parameter c : C | A.cs:145:32:145:35 | [post] this access [field c] : C | +| A.cs:145:41:145:41 | access to parameter c : C1 | A.cs:145:32:145:35 | [post] this access [field c] : C1 | | A.cs:145:41:145:41 | access to parameter c : C1 | A.cs:145:32:145:35 | [post] this access [field c] : C1 | | A.cs:145:41:145:41 | access to parameter c : C2 | A.cs:145:32:145:35 | [post] this access [field c] : C2 | +| A.cs:145:41:145:41 | access to parameter c : C2 | A.cs:145:32:145:35 | [post] this access [field c] : C2 | +| A.cs:146:18:146:20 | this [field c] : C | A.cs:146:33:146:36 | this access [field c] : C | | A.cs:146:18:146:20 | this [field c] : C | A.cs:146:33:146:36 | this access [field c] : C | | A.cs:146:18:146:20 | this [field c] : C1 | A.cs:146:33:146:36 | this access [field c] : C1 | +| A.cs:146:18:146:20 | this [field c] : C1 | A.cs:146:33:146:36 | this access [field c] : C1 | +| A.cs:146:33:146:36 | this access [field c] : C | A.cs:146:33:146:38 | access to field c : C | | A.cs:146:33:146:36 | this access [field c] : C | A.cs:146:33:146:38 | access to field c : C | | A.cs:146:33:146:36 | this access [field c] : C1 | A.cs:146:33:146:38 | access to field c : C1 | +| A.cs:146:33:146:36 | this access [field c] : C1 | A.cs:146:33:146:38 | access to field c : C1 | +| A.cs:147:32:147:32 | c : C | A.cs:149:26:149:26 | access to parameter c : C | | A.cs:147:32:147:32 | c : C | A.cs:149:26:149:26 | access to parameter c : C | | A.cs:149:26:149:26 | access to parameter c : C | A.cs:141:20:141:20 | c : C | +| A.cs:149:26:149:26 | access to parameter c : C | A.cs:141:20:141:20 | c : C | +| A.cs:149:26:149:26 | access to parameter c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | | A.cs:149:26:149:26 | access to parameter c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | | A.cs:157:25:157:28 | head : B | A.cs:159:25:159:28 | access to parameter head : B | +| A.cs:157:25:157:28 | head : B | A.cs:159:25:159:28 | access to parameter head : B | +| A.cs:157:38:157:41 | next [field head] : B | A.cs:160:25:160:28 | access to parameter next [field head] : B | | A.cs:157:38:157:41 | next [field head] : B | A.cs:160:25:160:28 | access to parameter next [field head] : B | | A.cs:157:38:157:41 | next [field next, field head] : B | A.cs:160:25:160:28 | access to parameter next [field next, field head] : B | +| A.cs:157:38:157:41 | next [field next, field head] : B | A.cs:160:25:160:28 | access to parameter next [field next, field head] : B | +| A.cs:159:25:159:28 | access to parameter head : B | A.cs:159:13:159:16 | [post] this access [field head] : B | | A.cs:159:25:159:28 | access to parameter head : B | A.cs:159:13:159:16 | [post] this access [field head] : B | | A.cs:160:25:160:28 | access to parameter next [field head] : B | A.cs:160:13:160:16 | [post] this access [field next, field head] : B | +| A.cs:160:25:160:28 | access to parameter next [field head] : B | A.cs:160:13:160:16 | [post] this access [field next, field head] : B | | A.cs:160:25:160:28 | access to parameter next [field next, field head] : B | A.cs:160:13:160:16 | [post] this access [field next, field next, field head] : B | -| B.cs:5:17:5:26 | object creation of type Elem : Elem | B.cs:6:27:6:27 | access to local variable e : Elem | +| A.cs:160:25:160:28 | access to parameter next [field next, field head] : B | A.cs:160:13:160:16 | [post] this access [field next, field next, field head] : B | +| B.cs:5:17:5:31 | call to method Source<Elem> : Elem | B.cs:6:27:6:27 | access to local variable e : Elem | +| B.cs:5:17:5:31 | call to method Source<Elem> : Elem | B.cs:6:27:6:27 | access to local variable e : Elem | +| B.cs:6:18:6:34 | object creation of type Box1 [field elem1] : Elem | B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | | B.cs:6:18:6:34 | object creation of type Box1 [field elem1] : Elem | B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | | B.cs:6:27:6:27 | access to local variable e : Elem | B.cs:6:18:6:34 | object creation of type Box1 [field elem1] : Elem | +| B.cs:6:27:6:27 | access to local variable e : Elem | B.cs:6:18:6:34 | object creation of type Box1 [field elem1] : Elem | +| B.cs:6:27:6:27 | access to local variable e : Elem | B.cs:29:26:29:27 | e1 : Elem | | B.cs:6:27:6:27 | access to local variable e : Elem | B.cs:29:26:29:27 | e1 : Elem | | B.cs:7:18:7:29 | object creation of type Box2 [field box1, field elem1] : Elem | B.cs:8:14:8:15 | access to local variable b2 [field box1, field elem1] : Elem | +| B.cs:7:18:7:29 | object creation of type Box2 [field box1, field elem1] : Elem | B.cs:8:14:8:15 | access to local variable b2 [field box1, field elem1] : Elem | +| B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | B.cs:7:18:7:29 | object creation of type Box2 [field box1, field elem1] : Elem | | B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | B.cs:7:18:7:29 | object creation of type Box2 [field box1, field elem1] : Elem | | B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | B.cs:39:26:39:27 | b1 [field elem1] : Elem | +| B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | B.cs:39:26:39:27 | b1 [field elem1] : Elem | +| B.cs:8:14:8:15 | access to local variable b2 [field box1, field elem1] : Elem | B.cs:8:14:8:20 | access to field box1 [field elem1] : Elem | | B.cs:8:14:8:15 | access to local variable b2 [field box1, field elem1] : Elem | B.cs:8:14:8:20 | access to field box1 [field elem1] : Elem | | B.cs:8:14:8:20 | access to field box1 [field elem1] : Elem | B.cs:8:14:8:26 | access to field elem1 | -| B.cs:14:17:14:26 | object creation of type Elem : Elem | B.cs:15:33:15:33 | access to local variable e : Elem | +| B.cs:8:14:8:20 | access to field box1 [field elem1] : Elem | B.cs:8:14:8:26 | access to field elem1 | +| B.cs:14:17:14:31 | call to method Source<Elem> : Elem | B.cs:15:33:15:33 | access to local variable e : Elem | +| B.cs:14:17:14:31 | call to method Source<Elem> : Elem | B.cs:15:33:15:33 | access to local variable e : Elem | +| B.cs:15:18:15:34 | object creation of type Box1 [field elem2] : Elem | B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | | B.cs:15:18:15:34 | object creation of type Box1 [field elem2] : Elem | B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | | B.cs:15:33:15:33 | access to local variable e : Elem | B.cs:15:18:15:34 | object creation of type Box1 [field elem2] : Elem | +| B.cs:15:33:15:33 | access to local variable e : Elem | B.cs:15:18:15:34 | object creation of type Box1 [field elem2] : Elem | +| B.cs:15:33:15:33 | access to local variable e : Elem | B.cs:29:35:29:36 | e2 : Elem | | B.cs:15:33:15:33 | access to local variable e : Elem | B.cs:29:35:29:36 | e2 : Elem | | B.cs:16:18:16:29 | object creation of type Box2 [field box1, field elem2] : Elem | B.cs:18:14:18:15 | access to local variable b2 [field box1, field elem2] : Elem | +| B.cs:16:18:16:29 | object creation of type Box2 [field box1, field elem2] : Elem | B.cs:18:14:18:15 | access to local variable b2 [field box1, field elem2] : Elem | +| B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | B.cs:16:18:16:29 | object creation of type Box2 [field box1, field elem2] : Elem | | B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | B.cs:16:18:16:29 | object creation of type Box2 [field box1, field elem2] : Elem | | B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | B.cs:39:26:39:27 | b1 [field elem2] : Elem | +| B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | B.cs:39:26:39:27 | b1 [field elem2] : Elem | +| B.cs:18:14:18:15 | access to local variable b2 [field box1, field elem2] : Elem | B.cs:18:14:18:20 | access to field box1 [field elem2] : Elem | | B.cs:18:14:18:15 | access to local variable b2 [field box1, field elem2] : Elem | B.cs:18:14:18:20 | access to field box1 [field elem2] : Elem | | B.cs:18:14:18:20 | access to field box1 [field elem2] : Elem | B.cs:18:14:18:26 | access to field elem2 | +| B.cs:18:14:18:20 | access to field box1 [field elem2] : Elem | B.cs:18:14:18:26 | access to field elem2 | +| B.cs:29:26:29:27 | e1 : Elem | B.cs:31:26:31:27 | access to parameter e1 : Elem | | B.cs:29:26:29:27 | e1 : Elem | B.cs:31:26:31:27 | access to parameter e1 : Elem | | B.cs:29:35:29:36 | e2 : Elem | B.cs:32:26:32:27 | access to parameter e2 : Elem | +| B.cs:29:35:29:36 | e2 : Elem | B.cs:32:26:32:27 | access to parameter e2 : Elem | +| B.cs:31:26:31:27 | access to parameter e1 : Elem | B.cs:31:13:31:16 | [post] this access [field elem1] : Elem | | B.cs:31:26:31:27 | access to parameter e1 : Elem | B.cs:31:13:31:16 | [post] this access [field elem1] : Elem | | B.cs:32:26:32:27 | access to parameter e2 : Elem | B.cs:32:13:32:16 | [post] this access [field elem2] : Elem | +| B.cs:32:26:32:27 | access to parameter e2 : Elem | B.cs:32:13:32:16 | [post] this access [field elem2] : Elem | +| B.cs:39:26:39:27 | b1 [field elem1] : Elem | B.cs:41:25:41:26 | access to parameter b1 [field elem1] : Elem | | B.cs:39:26:39:27 | b1 [field elem1] : Elem | B.cs:41:25:41:26 | access to parameter b1 [field elem1] : Elem | | B.cs:39:26:39:27 | b1 [field elem2] : Elem | B.cs:41:25:41:26 | access to parameter b1 [field elem2] : Elem | +| B.cs:39:26:39:27 | b1 [field elem2] : Elem | B.cs:41:25:41:26 | access to parameter b1 [field elem2] : Elem | +| B.cs:41:25:41:26 | access to parameter b1 [field elem1] : Elem | B.cs:41:13:41:16 | [post] this access [field box1, field elem1] : Elem | | B.cs:41:25:41:26 | access to parameter b1 [field elem1] : Elem | B.cs:41:13:41:16 | [post] this access [field box1, field elem1] : Elem | | B.cs:41:25:41:26 | access to parameter b1 [field elem2] : Elem | B.cs:41:13:41:16 | [post] this access [field box1, field elem2] : Elem | +| B.cs:41:25:41:26 | access to parameter b1 [field elem2] : Elem | B.cs:41:13:41:16 | [post] this access [field box1, field elem2] : Elem | | C.cs:3:18:3:19 | [post] this access [field s1] : Elem | C.cs:12:15:12:21 | object creation of type C [field s1] : Elem | -| C.cs:3:23:3:32 | object creation of type Elem : Elem | C.cs:3:18:3:19 | [post] this access [field s1] : Elem | +| C.cs:3:18:3:19 | [post] this access [field s1] : Elem | C.cs:12:15:12:21 | object creation of type C [field s1] : Elem | +| C.cs:3:23:3:37 | call to method Source<Elem> : Elem | C.cs:3:18:3:19 | [post] this access [field s1] : Elem | +| C.cs:3:23:3:37 | call to method Source<Elem> : Elem | C.cs:3:18:3:19 | [post] this access [field s1] : Elem | | C.cs:4:27:4:28 | [post] this access [field s2] : Elem | C.cs:12:15:12:21 | object creation of type C [field s2] : Elem | -| C.cs:4:32:4:41 | object creation of type Elem : Elem | C.cs:4:27:4:28 | [post] this access [field s2] : Elem | -| C.cs:6:30:6:39 | object creation of type Elem : Elem | C.cs:26:14:26:15 | access to field s4 | +| C.cs:4:27:4:28 | [post] this access [field s2] : Elem | C.cs:12:15:12:21 | object creation of type C [field s2] : Elem | +| C.cs:4:32:4:46 | call to method Source<Elem> : Elem | C.cs:4:27:4:28 | [post] this access [field s2] : Elem | +| C.cs:4:32:4:46 | call to method Source<Elem> : Elem | C.cs:4:27:4:28 | [post] this access [field s2] : Elem | +| C.cs:6:30:6:44 | call to method Source<Elem> : Elem | C.cs:26:14:26:15 | access to field s4 | +| C.cs:6:30:6:44 | call to method Source<Elem> : Elem | C.cs:26:14:26:15 | access to field s4 | | C.cs:7:18:7:19 | [post] this access [property s5] : Elem | C.cs:12:15:12:21 | object creation of type C [property s5] : Elem | -| C.cs:7:37:7:46 | object creation of type Elem : Elem | C.cs:7:18:7:19 | [post] this access [property s5] : Elem | -| C.cs:8:30:8:39 | object creation of type Elem : Elem | C.cs:28:14:28:15 | access to property s6 | +| C.cs:7:18:7:19 | [post] this access [property s5] : Elem | C.cs:12:15:12:21 | object creation of type C [property s5] : Elem | +| C.cs:7:37:7:51 | call to method Source<Elem> : Elem | C.cs:7:18:7:19 | [post] this access [property s5] : Elem | +| C.cs:7:37:7:51 | call to method Source<Elem> : Elem | C.cs:7:18:7:19 | [post] this access [property s5] : Elem | +| C.cs:8:30:8:44 | call to method Source<Elem> : Elem | C.cs:28:14:28:15 | access to property s6 | +| C.cs:8:30:8:44 | call to method Source<Elem> : Elem | C.cs:28:14:28:15 | access to property s6 | +| C.cs:12:15:12:21 | object creation of type C [field s1] : Elem | C.cs:13:9:13:9 | access to local variable c [field s1] : Elem | | C.cs:12:15:12:21 | object creation of type C [field s1] : Elem | C.cs:13:9:13:9 | access to local variable c [field s1] : Elem | | C.cs:12:15:12:21 | object creation of type C [field s2] : Elem | C.cs:13:9:13:9 | access to local variable c [field s2] : Elem | +| C.cs:12:15:12:21 | object creation of type C [field s2] : Elem | C.cs:13:9:13:9 | access to local variable c [field s2] : Elem | +| C.cs:12:15:12:21 | object creation of type C [field s3] : Elem | C.cs:13:9:13:9 | access to local variable c [field s3] : Elem | | C.cs:12:15:12:21 | object creation of type C [field s3] : Elem | C.cs:13:9:13:9 | access to local variable c [field s3] : Elem | | C.cs:12:15:12:21 | object creation of type C [property s5] : Elem | C.cs:13:9:13:9 | access to local variable c [property s5] : Elem | +| C.cs:12:15:12:21 | object creation of type C [property s5] : Elem | C.cs:13:9:13:9 | access to local variable c [property s5] : Elem | +| C.cs:13:9:13:9 | access to local variable c [field s1] : Elem | C.cs:21:17:21:18 | this [field s1] : Elem | | C.cs:13:9:13:9 | access to local variable c [field s1] : Elem | C.cs:21:17:21:18 | this [field s1] : Elem | | C.cs:13:9:13:9 | access to local variable c [field s2] : Elem | C.cs:21:17:21:18 | this [field s2] : Elem | +| C.cs:13:9:13:9 | access to local variable c [field s2] : Elem | C.cs:21:17:21:18 | this [field s2] : Elem | +| C.cs:13:9:13:9 | access to local variable c [field s3] : Elem | C.cs:21:17:21:18 | this [field s3] : Elem | | C.cs:13:9:13:9 | access to local variable c [field s3] : Elem | C.cs:21:17:21:18 | this [field s3] : Elem | | C.cs:13:9:13:9 | access to local variable c [property s5] : Elem | C.cs:21:17:21:18 | this [property s5] : Elem | +| C.cs:13:9:13:9 | access to local variable c [property s5] : Elem | C.cs:21:17:21:18 | this [property s5] : Elem | | C.cs:18:9:18:12 | [post] this access [field s3] : Elem | C.cs:12:15:12:21 | object creation of type C [field s3] : Elem | -| C.cs:18:19:18:28 | object creation of type Elem : Elem | C.cs:18:9:18:12 | [post] this access [field s3] : Elem | +| C.cs:18:9:18:12 | [post] this access [field s3] : Elem | C.cs:12:15:12:21 | object creation of type C [field s3] : Elem | +| C.cs:18:19:18:33 | call to method Source<Elem> : Elem | C.cs:18:9:18:12 | [post] this access [field s3] : Elem | +| C.cs:18:19:18:33 | call to method Source<Elem> : Elem | C.cs:18:9:18:12 | [post] this access [field s3] : Elem | +| C.cs:21:17:21:18 | this [field s1] : Elem | C.cs:23:14:23:15 | this access [field s1] : Elem | | C.cs:21:17:21:18 | this [field s1] : Elem | C.cs:23:14:23:15 | this access [field s1] : Elem | | C.cs:21:17:21:18 | this [field s2] : Elem | C.cs:24:14:24:15 | this access [field s2] : Elem | +| C.cs:21:17:21:18 | this [field s2] : Elem | C.cs:24:14:24:15 | this access [field s2] : Elem | +| C.cs:21:17:21:18 | this [field s3] : Elem | C.cs:25:14:25:15 | this access [field s3] : Elem | | C.cs:21:17:21:18 | this [field s3] : Elem | C.cs:25:14:25:15 | this access [field s3] : Elem | | C.cs:21:17:21:18 | this [property s5] : Elem | C.cs:27:14:27:15 | this access [property s5] : Elem | +| C.cs:21:17:21:18 | this [property s5] : Elem | C.cs:27:14:27:15 | this access [property s5] : Elem | +| C.cs:23:14:23:15 | this access [field s1] : Elem | C.cs:23:14:23:15 | access to field s1 | | C.cs:23:14:23:15 | this access [field s1] : Elem | C.cs:23:14:23:15 | access to field s1 | | C.cs:24:14:24:15 | this access [field s2] : Elem | C.cs:24:14:24:15 | access to field s2 | +| C.cs:24:14:24:15 | this access [field s2] : Elem | C.cs:24:14:24:15 | access to field s2 | +| C.cs:25:14:25:15 | this access [field s3] : Elem | C.cs:25:14:25:15 | access to field s3 | | C.cs:25:14:25:15 | this access [field s3] : Elem | C.cs:25:14:25:15 | access to field s3 | | C.cs:27:14:27:15 | this access [property s5] : Elem | C.cs:27:14:27:15 | access to property s5 | +| C.cs:27:14:27:15 | this access [property s5] : Elem | C.cs:27:14:27:15 | access to property s5 | +| D.cs:8:9:8:11 | this [field trivialPropField] : Object | D.cs:8:22:8:25 | this access [field trivialPropField] : Object | | D.cs:8:9:8:11 | this [field trivialPropField] : Object | D.cs:8:22:8:25 | this access [field trivialPropField] : Object | | D.cs:8:22:8:25 | this access [field trivialPropField] : Object | D.cs:8:22:8:42 | access to field trivialPropField : Object | +| D.cs:8:22:8:25 | this access [field trivialPropField] : Object | D.cs:8:22:8:42 | access to field trivialPropField : Object | +| D.cs:9:9:9:11 | value : Object | D.cs:9:39:9:43 | access to parameter value : Object | | D.cs:9:9:9:11 | value : Object | D.cs:9:39:9:43 | access to parameter value : Object | | D.cs:9:39:9:43 | access to parameter value : Object | D.cs:9:15:9:18 | [post] this access [field trivialPropField] : Object | +| D.cs:9:39:9:43 | access to parameter value : Object | D.cs:9:15:9:18 | [post] this access [field trivialPropField] : Object | +| D.cs:14:9:14:11 | this [field trivialPropField] : Object | D.cs:14:22:14:25 | this access [field trivialPropField] : Object | | D.cs:14:9:14:11 | this [field trivialPropField] : Object | D.cs:14:22:14:25 | this access [field trivialPropField] : Object | | D.cs:14:22:14:25 | this access [field trivialPropField] : Object | D.cs:14:22:14:42 | access to field trivialPropField : Object | +| D.cs:14:22:14:25 | this access [field trivialPropField] : Object | D.cs:14:22:14:42 | access to field trivialPropField : Object | +| D.cs:15:9:15:11 | value : Object | D.cs:15:34:15:38 | access to parameter value : Object | | D.cs:15:9:15:11 | value : Object | D.cs:15:34:15:38 | access to parameter value : Object | | D.cs:15:34:15:38 | access to parameter value : Object | D.cs:9:9:9:11 | value : Object | +| D.cs:15:34:15:38 | access to parameter value : Object | D.cs:9:9:9:11 | value : Object | +| D.cs:15:34:15:38 | access to parameter value : Object | D.cs:15:15:15:18 | [post] this access [field trivialPropField] : Object | | D.cs:15:34:15:38 | access to parameter value : Object | D.cs:15:15:15:18 | [post] this access [field trivialPropField] : Object | | D.cs:18:28:18:29 | o1 : Object | D.cs:21:24:21:25 | access to parameter o1 : Object | +| D.cs:18:28:18:29 | o1 : Object | D.cs:21:24:21:25 | access to parameter o1 : Object | +| D.cs:18:39:18:40 | o2 : Object | D.cs:22:27:22:28 | access to parameter o2 : Object | | D.cs:18:39:18:40 | o2 : Object | D.cs:22:27:22:28 | access to parameter o2 : Object | | D.cs:18:50:18:51 | o3 : Object | D.cs:23:27:23:28 | access to parameter o3 : Object | +| D.cs:18:50:18:51 | o3 : Object | D.cs:23:27:23:28 | access to parameter o3 : Object | +| D.cs:21:9:21:11 | [post] access to local variable ret [property AutoProp] : Object | D.cs:24:16:24:18 | access to local variable ret [property AutoProp] : Object | | D.cs:21:9:21:11 | [post] access to local variable ret [property AutoProp] : Object | D.cs:24:16:24:18 | access to local variable ret [property AutoProp] : Object | | D.cs:21:24:21:25 | access to parameter o1 : Object | D.cs:21:9:21:11 | [post] access to local variable ret [property AutoProp] : Object | +| D.cs:21:24:21:25 | access to parameter o1 : Object | D.cs:21:9:21:11 | [post] access to local variable ret [property AutoProp] : Object | +| D.cs:22:9:22:11 | [post] access to local variable ret [field trivialPropField] : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | | D.cs:22:9:22:11 | [post] access to local variable ret [field trivialPropField] : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | | D.cs:22:27:22:28 | access to parameter o2 : Object | D.cs:9:9:9:11 | value : Object | +| D.cs:22:27:22:28 | access to parameter o2 : Object | D.cs:9:9:9:11 | value : Object | +| D.cs:22:27:22:28 | access to parameter o2 : Object | D.cs:22:9:22:11 | [post] access to local variable ret [field trivialPropField] : Object | | D.cs:22:27:22:28 | access to parameter o2 : Object | D.cs:22:9:22:11 | [post] access to local variable ret [field trivialPropField] : Object | | D.cs:23:9:23:11 | [post] access to local variable ret [field trivialPropField] : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | +| D.cs:23:9:23:11 | [post] access to local variable ret [field trivialPropField] : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | +| D.cs:23:27:23:28 | access to parameter o3 : Object | D.cs:15:9:15:11 | value : Object | | D.cs:23:27:23:28 | access to parameter o3 : Object | D.cs:15:9:15:11 | value : Object | | D.cs:23:27:23:28 | access to parameter o3 : Object | D.cs:23:9:23:11 | [post] access to local variable ret [field trivialPropField] : Object | -| D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:31:24:31:24 | access to local variable o : Object | -| D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:37:26:37:26 | access to local variable o : Object | -| D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:43:32:43:32 | access to local variable o : Object | +| D.cs:23:27:23:28 | access to parameter o3 : Object | D.cs:23:9:23:11 | [post] access to local variable ret [field trivialPropField] : Object | +| D.cs:29:17:29:33 | call to method Source<Object> : Object | D.cs:31:24:31:24 | access to local variable o : Object | +| D.cs:29:17:29:33 | call to method Source<Object> : Object | D.cs:31:24:31:24 | access to local variable o : Object | +| D.cs:31:17:31:37 | call to method Create [property AutoProp] : Object | D.cs:32:14:32:14 | access to local variable d [property AutoProp] : Object | | D.cs:31:17:31:37 | call to method Create [property AutoProp] : Object | D.cs:32:14:32:14 | access to local variable d [property AutoProp] : Object | | D.cs:31:24:31:24 | access to local variable o : Object | D.cs:18:28:18:29 | o1 : Object | +| D.cs:31:24:31:24 | access to local variable o : Object | D.cs:18:28:18:29 | o1 : Object | +| D.cs:31:24:31:24 | access to local variable o : Object | D.cs:31:17:31:37 | call to method Create [property AutoProp] : Object | | D.cs:31:24:31:24 | access to local variable o : Object | D.cs:31:17:31:37 | call to method Create [property AutoProp] : Object | | D.cs:32:14:32:14 | access to local variable d [property AutoProp] : Object | D.cs:32:14:32:23 | access to property AutoProp | -| D.cs:37:13:37:33 | call to method Create [field trivialPropField] : Object | D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | -| D.cs:37:13:37:33 | call to method Create [field trivialPropField] : Object | D.cs:40:14:40:14 | access to local variable d [field trivialPropField] : Object | -| D.cs:37:13:37:33 | call to method Create [field trivialPropField] : Object | D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | -| D.cs:37:26:37:26 | access to local variable o : Object | D.cs:18:39:18:40 | o2 : Object | -| D.cs:37:26:37:26 | access to local variable o : Object | D.cs:37:13:37:33 | call to method Create [field trivialPropField] : Object | +| D.cs:32:14:32:14 | access to local variable d [property AutoProp] : Object | D.cs:32:14:32:23 | access to property AutoProp | +| D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | D.cs:40:14:40:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | D.cs:40:14:40:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:18:39:18:40 | o2 : Object | +| D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:18:39:18:40 | o2 : Object | +| D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | +| D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | +| D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | D.cs:8:9:8:11 | this [field trivialPropField] : Object | | D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | D.cs:8:9:8:11 | this [field trivialPropField] : Object | | D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | D.cs:39:14:39:26 | access to property TrivialProp | +| D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | D.cs:39:14:39:26 | access to property TrivialProp | +| D.cs:40:14:40:14 | access to local variable d [field trivialPropField] : Object | D.cs:40:14:40:31 | access to field trivialPropField | | D.cs:40:14:40:14 | access to local variable d [field trivialPropField] : Object | D.cs:40:14:40:31 | access to field trivialPropField | | D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | D.cs:14:9:14:11 | this [field trivialPropField] : Object | +| D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | D.cs:14:9:14:11 | this [field trivialPropField] : Object | | D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | D.cs:41:14:41:26 | access to property ComplexProp | -| D.cs:43:13:43:33 | call to method Create [field trivialPropField] : Object | D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | -| D.cs:43:13:43:33 | call to method Create [field trivialPropField] : Object | D.cs:46:14:46:14 | access to local variable d [field trivialPropField] : Object | -| D.cs:43:13:43:33 | call to method Create [field trivialPropField] : Object | D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | -| D.cs:43:32:43:32 | access to local variable o : Object | D.cs:18:50:18:51 | o3 : Object | -| D.cs:43:32:43:32 | access to local variable o : Object | D.cs:43:13:43:33 | call to method Create [field trivialPropField] : Object | +| D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | D.cs:41:14:41:26 | access to property ComplexProp | +| D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | D.cs:46:14:46:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | D.cs:46:14:46:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | +| D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:18:50:18:51 | o3 : Object | +| D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:18:50:18:51 | o3 : Object | +| D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | +| D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | +| D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | D.cs:8:9:8:11 | this [field trivialPropField] : Object | | D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | D.cs:8:9:8:11 | this [field trivialPropField] : Object | | D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | D.cs:45:14:45:26 | access to property TrivialProp | +| D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | D.cs:45:14:45:26 | access to property TrivialProp | +| D.cs:46:14:46:14 | access to local variable d [field trivialPropField] : Object | D.cs:46:14:46:31 | access to field trivialPropField | | D.cs:46:14:46:14 | access to local variable d [field trivialPropField] : Object | D.cs:46:14:46:31 | access to field trivialPropField | | D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | D.cs:14:9:14:11 | this [field trivialPropField] : Object | +| D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | D.cs:14:9:14:11 | this [field trivialPropField] : Object | +| D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | D.cs:47:14:47:26 | access to property ComplexProp | | D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | D.cs:47:14:47:26 | access to property ComplexProp | | E.cs:8:29:8:29 | o : Object | E.cs:11:21:11:21 | access to parameter o : Object | +| E.cs:8:29:8:29 | o : Object | E.cs:11:21:11:21 | access to parameter o : Object | +| E.cs:11:9:11:11 | [post] access to local variable ret [field Field] : Object | E.cs:12:16:12:18 | access to local variable ret [field Field] : Object | | E.cs:11:9:11:11 | [post] access to local variable ret [field Field] : Object | E.cs:12:16:12:18 | access to local variable ret [field Field] : Object | | E.cs:11:21:11:21 | access to parameter o : Object | E.cs:11:9:11:11 | [post] access to local variable ret [field Field] : Object | -| E.cs:22:17:22:28 | object creation of type Object : Object | E.cs:23:25:23:25 | access to local variable o : Object | +| E.cs:11:21:11:21 | access to parameter o : Object | E.cs:11:9:11:11 | [post] access to local variable ret [field Field] : Object | +| E.cs:22:17:22:33 | call to method Source<Object> : Object | E.cs:23:25:23:25 | access to local variable o : Object | +| E.cs:22:17:22:33 | call to method Source<Object> : Object | E.cs:23:25:23:25 | access to local variable o : Object | +| E.cs:23:17:23:26 | call to method CreateS [field Field] : Object | E.cs:24:14:24:14 | access to local variable s [field Field] : Object | | E.cs:23:17:23:26 | call to method CreateS [field Field] : Object | E.cs:24:14:24:14 | access to local variable s [field Field] : Object | | E.cs:23:25:23:25 | access to local variable o : Object | E.cs:8:29:8:29 | o : Object | +| E.cs:23:25:23:25 | access to local variable o : Object | E.cs:8:29:8:29 | o : Object | +| E.cs:23:25:23:25 | access to local variable o : Object | E.cs:23:17:23:26 | call to method CreateS [field Field] : Object | | E.cs:23:25:23:25 | access to local variable o : Object | E.cs:23:17:23:26 | call to method CreateS [field Field] : Object | | E.cs:24:14:24:14 | access to local variable s [field Field] : Object | E.cs:24:14:24:20 | access to field Field | +| E.cs:24:14:24:14 | access to local variable s [field Field] : Object | E.cs:24:14:24:20 | access to field Field | +| F.cs:6:28:6:29 | o1 : Object | F.cs:6:65:6:66 | access to parameter o1 : Object | | F.cs:6:28:6:29 | o1 : Object | F.cs:6:65:6:66 | access to parameter o1 : Object | | F.cs:6:39:6:40 | o2 : Object | F.cs:6:78:6:79 | access to parameter o2 : Object | +| F.cs:6:39:6:40 | o2 : Object | F.cs:6:78:6:79 | access to parameter o2 : Object | +| F.cs:6:54:6:81 | { ..., ... } [field Field1] : Object | F.cs:6:46:6:81 | object creation of type F [field Field1] : Object | | F.cs:6:54:6:81 | { ..., ... } [field Field1] : Object | F.cs:6:46:6:81 | object creation of type F [field Field1] : Object | | F.cs:6:54:6:81 | { ..., ... } [field Field2] : Object | F.cs:6:46:6:81 | object creation of type F [field Field2] : Object | +| F.cs:6:54:6:81 | { ..., ... } [field Field2] : Object | F.cs:6:46:6:81 | object creation of type F [field Field2] : Object | +| F.cs:6:65:6:66 | access to parameter o1 : Object | F.cs:6:54:6:81 | { ..., ... } [field Field1] : Object | | F.cs:6:65:6:66 | access to parameter o1 : Object | F.cs:6:54:6:81 | { ..., ... } [field Field1] : Object | | F.cs:6:78:6:79 | access to parameter o2 : Object | F.cs:6:54:6:81 | { ..., ... } [field Field2] : Object | -| F.cs:10:17:10:28 | object creation of type Object : Object | F.cs:11:24:11:24 | access to local variable o : Object | -| F.cs:10:17:10:28 | object creation of type Object : Object | F.cs:15:26:15:26 | access to local variable o : Object | -| F.cs:10:17:10:28 | object creation of type Object : Object | F.cs:19:32:19:32 | access to local variable o : Object | -| F.cs:10:17:10:28 | object creation of type Object : Object | F.cs:23:32:23:32 | access to local variable o : Object | +| F.cs:6:78:6:79 | access to parameter o2 : Object | F.cs:6:54:6:81 | { ..., ... } [field Field2] : Object | +| F.cs:10:17:10:33 | call to method Source<Object> : Object | F.cs:11:24:11:24 | access to local variable o : Object | +| F.cs:10:17:10:33 | call to method Source<Object> : Object | F.cs:11:24:11:24 | access to local variable o : Object | +| F.cs:11:17:11:31 | call to method Create [field Field1] : Object | F.cs:12:14:12:14 | access to local variable f [field Field1] : Object | | F.cs:11:17:11:31 | call to method Create [field Field1] : Object | F.cs:12:14:12:14 | access to local variable f [field Field1] : Object | | F.cs:11:24:11:24 | access to local variable o : Object | F.cs:6:28:6:29 | o1 : Object | +| F.cs:11:24:11:24 | access to local variable o : Object | F.cs:6:28:6:29 | o1 : Object | +| F.cs:11:24:11:24 | access to local variable o : Object | F.cs:11:17:11:31 | call to method Create [field Field1] : Object | | F.cs:11:24:11:24 | access to local variable o : Object | F.cs:11:17:11:31 | call to method Create [field Field1] : Object | | F.cs:12:14:12:14 | access to local variable f [field Field1] : Object | F.cs:12:14:12:21 | access to field Field1 | -| F.cs:15:13:15:27 | call to method Create [field Field2] : Object | F.cs:17:14:17:14 | access to local variable f [field Field2] : Object | -| F.cs:15:26:15:26 | access to local variable o : Object | F.cs:6:39:6:40 | o2 : Object | -| F.cs:15:26:15:26 | access to local variable o : Object | F.cs:15:13:15:27 | call to method Create [field Field2] : Object | +| F.cs:12:14:12:14 | access to local variable f [field Field1] : Object | F.cs:12:14:12:21 | access to field Field1 | +| F.cs:15:13:15:43 | call to method Create [field Field2] : Object | F.cs:17:14:17:14 | access to local variable f [field Field2] : Object | +| F.cs:15:13:15:43 | call to method Create [field Field2] : Object | F.cs:17:14:17:14 | access to local variable f [field Field2] : Object | +| F.cs:15:26:15:42 | call to method Source<Object> : Object | F.cs:6:39:6:40 | o2 : Object | +| F.cs:15:26:15:42 | call to method Source<Object> : Object | F.cs:6:39:6:40 | o2 : Object | +| F.cs:15:26:15:42 | call to method Source<Object> : Object | F.cs:15:13:15:43 | call to method Create [field Field2] : Object | +| F.cs:15:26:15:42 | call to method Source<Object> : Object | F.cs:15:13:15:43 | call to method Create [field Field2] : Object | | F.cs:17:14:17:14 | access to local variable f [field Field2] : Object | F.cs:17:14:17:21 | access to field Field2 | -| F.cs:19:21:19:34 | { ..., ... } [field Field1] : Object | F.cs:20:14:20:14 | access to local variable f [field Field1] : Object | -| F.cs:19:32:19:32 | access to local variable o : Object | F.cs:19:21:19:34 | { ..., ... } [field Field1] : Object | +| F.cs:17:14:17:14 | access to local variable f [field Field2] : Object | F.cs:17:14:17:21 | access to field Field2 | +| F.cs:19:21:19:50 | { ..., ... } [field Field1] : Object | F.cs:20:14:20:14 | access to local variable f [field Field1] : Object | +| F.cs:19:21:19:50 | { ..., ... } [field Field1] : Object | F.cs:20:14:20:14 | access to local variable f [field Field1] : Object | +| F.cs:19:32:19:48 | call to method Source<Object> : Object | F.cs:19:21:19:50 | { ..., ... } [field Field1] : Object | +| F.cs:19:32:19:48 | call to method Source<Object> : Object | F.cs:19:21:19:50 | { ..., ... } [field Field1] : Object | | F.cs:20:14:20:14 | access to local variable f [field Field1] : Object | F.cs:20:14:20:21 | access to field Field1 | -| F.cs:23:21:23:34 | { ..., ... } [field Field2] : Object | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | -| F.cs:23:32:23:32 | access to local variable o : Object | F.cs:23:21:23:34 | { ..., ... } [field Field2] : Object | +| F.cs:20:14:20:14 | access to local variable f [field Field1] : Object | F.cs:20:14:20:21 | access to field Field1 | +| F.cs:23:21:23:50 | { ..., ... } [field Field2] : Object | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | +| F.cs:23:21:23:50 | { ..., ... } [field Field2] : Object | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | +| F.cs:23:32:23:48 | call to method Source<Object> : Object | F.cs:23:21:23:50 | { ..., ... } [field Field2] : Object | +| F.cs:23:32:23:48 | call to method Source<Object> : Object | F.cs:23:21:23:50 | { ..., ... } [field Field2] : Object | | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | F.cs:25:14:25:21 | access to field Field2 | -| G.cs:7:18:7:27 | object creation of type Elem : Elem | G.cs:9:23:9:23 | access to local variable e : Elem | +| F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | F.cs:25:14:25:21 | access to field Field2 | +| G.cs:7:18:7:32 | call to method Source<Elem> : Elem | G.cs:9:23:9:23 | access to local variable e : Elem | +| G.cs:7:18:7:32 | call to method Source<Elem> : Elem | G.cs:9:23:9:23 | access to local variable e : Elem | +| G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:10:18:10:18 | access to local variable b [field Box1, field Elem] : Elem | | G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:10:18:10:18 | access to local variable b [field Box1, field Elem] : Elem | | G.cs:9:9:9:14 | [post] access to field Box1 [field Elem] : Elem | G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | +| G.cs:9:9:9:14 | [post] access to field Box1 [field Elem] : Elem | G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | +| G.cs:9:23:9:23 | access to local variable e : Elem | G.cs:9:9:9:14 | [post] access to field Box1 [field Elem] : Elem | | G.cs:9:23:9:23 | access to local variable e : Elem | G.cs:9:9:9:14 | [post] access to field Box1 [field Elem] : Elem | | G.cs:10:18:10:18 | access to local variable b [field Box1, field Elem] : Elem | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | -| G.cs:15:18:15:27 | object creation of type Elem : Elem | G.cs:17:24:17:24 | access to local variable e : Elem | +| G.cs:10:18:10:18 | access to local variable b [field Box1, field Elem] : Elem | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | +| G.cs:15:18:15:32 | call to method Source<Elem> : Elem | G.cs:17:24:17:24 | access to local variable e : Elem | +| G.cs:15:18:15:32 | call to method Source<Elem> : Elem | G.cs:17:24:17:24 | access to local variable e : Elem | +| G.cs:17:9:17:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:18:18:18:18 | access to local variable b [field Box1, field Elem] : Elem | | G.cs:17:9:17:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:18:18:18:18 | access to local variable b [field Box1, field Elem] : Elem | | G.cs:17:9:17:14 | [post] access to field Box1 [field Elem] : Elem | G.cs:17:9:17:9 | [post] access to local variable b [field Box1, field Elem] : Elem | +| G.cs:17:9:17:14 | [post] access to field Box1 [field Elem] : Elem | G.cs:17:9:17:9 | [post] access to local variable b [field Box1, field Elem] : Elem | +| G.cs:17:24:17:24 | access to local variable e : Elem | G.cs:17:9:17:14 | [post] access to field Box1 [field Elem] : Elem | | G.cs:17:24:17:24 | access to local variable e : Elem | G.cs:17:9:17:14 | [post] access to field Box1 [field Elem] : Elem | | G.cs:17:24:17:24 | access to local variable e : Elem | G.cs:64:34:64:34 | e : Elem | +| G.cs:17:24:17:24 | access to local variable e : Elem | G.cs:64:34:64:34 | e : Elem | | G.cs:18:18:18:18 | access to local variable b [field Box1, field Elem] : Elem | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | -| G.cs:23:18:23:27 | object creation of type Elem : Elem | G.cs:25:28:25:28 | access to local variable e : Elem | +| G.cs:18:18:18:18 | access to local variable b [field Box1, field Elem] : Elem | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | +| G.cs:23:18:23:32 | call to method Source<Elem> : Elem | G.cs:25:28:25:28 | access to local variable e : Elem | +| G.cs:23:18:23:32 | call to method Source<Elem> : Elem | G.cs:25:28:25:28 | access to local variable e : Elem | +| G.cs:25:9:25:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:26:18:26:18 | access to local variable b [field Box1, field Elem] : Elem | | G.cs:25:9:25:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:26:18:26:18 | access to local variable b [field Box1, field Elem] : Elem | | G.cs:25:9:25:19 | [post] call to method GetBox1 [field Elem] : Elem | G.cs:25:9:25:9 | [post] access to local variable b [field Box1, field Elem] : Elem | +| G.cs:25:9:25:19 | [post] call to method GetBox1 [field Elem] : Elem | G.cs:25:9:25:9 | [post] access to local variable b [field Box1, field Elem] : Elem | +| G.cs:25:28:25:28 | access to local variable e : Elem | G.cs:25:9:25:19 | [post] call to method GetBox1 [field Elem] : Elem | | G.cs:25:28:25:28 | access to local variable e : Elem | G.cs:25:9:25:19 | [post] call to method GetBox1 [field Elem] : Elem | | G.cs:26:18:26:18 | access to local variable b [field Box1, field Elem] : Elem | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | -| G.cs:31:18:31:27 | object creation of type Elem : Elem | G.cs:33:29:33:29 | access to local variable e : Elem | +| G.cs:26:18:26:18 | access to local variable b [field Box1, field Elem] : Elem | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | +| G.cs:31:18:31:32 | call to method Source<Elem> : Elem | G.cs:33:29:33:29 | access to local variable e : Elem | +| G.cs:31:18:31:32 | call to method Source<Elem> : Elem | G.cs:33:29:33:29 | access to local variable e : Elem | +| G.cs:33:9:33:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:34:18:34:18 | access to local variable b [field Box1, field Elem] : Elem | | G.cs:33:9:33:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:34:18:34:18 | access to local variable b [field Box1, field Elem] : Elem | | G.cs:33:9:33:19 | [post] call to method GetBox1 [field Elem] : Elem | G.cs:33:9:33:9 | [post] access to local variable b [field Box1, field Elem] : Elem | +| G.cs:33:9:33:19 | [post] call to method GetBox1 [field Elem] : Elem | G.cs:33:9:33:9 | [post] access to local variable b [field Box1, field Elem] : Elem | +| G.cs:33:29:33:29 | access to local variable e : Elem | G.cs:33:9:33:19 | [post] call to method GetBox1 [field Elem] : Elem | | G.cs:33:29:33:29 | access to local variable e : Elem | G.cs:33:9:33:19 | [post] call to method GetBox1 [field Elem] : Elem | | G.cs:33:29:33:29 | access to local variable e : Elem | G.cs:64:34:64:34 | e : Elem | +| G.cs:33:29:33:29 | access to local variable e : Elem | G.cs:64:34:64:34 | e : Elem | +| G.cs:34:18:34:18 | access to local variable b [field Box1, field Elem] : Elem | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | | G.cs:34:18:34:18 | access to local variable b [field Box1, field Elem] : Elem | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | +| G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | +| G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | | G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | | G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | G.cs:71:21:71:27 | this [field Box1, field Elem] : Elem | +| G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | G.cs:71:21:71:27 | this [field Box1, field Elem] : Elem | +| G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | G.cs:39:14:39:35 | call to method GetElem | | G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | G.cs:39:14:39:35 | call to method GetElem | | G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | G.cs:63:21:63:27 | this [field Elem] : Elem | -| G.cs:44:18:44:27 | object creation of type Elem : Elem | G.cs:46:30:46:30 | access to local variable e : Elem | +| G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | G.cs:63:21:63:27 | this [field Elem] : Elem | +| G.cs:44:18:44:32 | call to method Source<Elem> : Elem | G.cs:46:30:46:30 | access to local variable e : Elem | +| G.cs:44:18:44:32 | call to method Source<Elem> : Elem | G.cs:46:30:46:30 | access to local variable e : Elem | +| G.cs:46:9:46:16 | [post] access to field boxfield [field Box1, field Elem] : Elem | G.cs:46:9:46:16 | [post] this access [field boxfield, field Box1, field Elem] : Elem | | G.cs:46:9:46:16 | [post] access to field boxfield [field Box1, field Elem] : Elem | G.cs:46:9:46:16 | [post] this access [field boxfield, field Box1, field Elem] : Elem | | G.cs:46:9:46:16 | [post] this access [field boxfield, field Box1, field Elem] : Elem | G.cs:47:9:47:13 | this access [field boxfield, field Box1, field Elem] : Elem | +| G.cs:46:9:46:16 | [post] this access [field boxfield, field Box1, field Elem] : Elem | G.cs:47:9:47:13 | this access [field boxfield, field Box1, field Elem] : Elem | +| G.cs:46:9:46:21 | [post] access to field Box1 [field Elem] : Elem | G.cs:46:9:46:16 | [post] access to field boxfield [field Box1, field Elem] : Elem | | G.cs:46:9:46:21 | [post] access to field Box1 [field Elem] : Elem | G.cs:46:9:46:16 | [post] access to field boxfield [field Box1, field Elem] : Elem | | G.cs:46:30:46:30 | access to local variable e : Elem | G.cs:46:9:46:21 | [post] access to field Box1 [field Elem] : Elem | +| G.cs:46:30:46:30 | access to local variable e : Elem | G.cs:46:9:46:21 | [post] access to field Box1 [field Elem] : Elem | +| G.cs:47:9:47:13 | this access [field boxfield, field Box1, field Elem] : Elem | G.cs:50:18:50:20 | this [field boxfield, field Box1, field Elem] : Elem | | G.cs:47:9:47:13 | this access [field boxfield, field Box1, field Elem] : Elem | G.cs:50:18:50:20 | this [field boxfield, field Box1, field Elem] : Elem | | G.cs:50:18:50:20 | this [field boxfield, field Box1, field Elem] : Elem | G.cs:52:14:52:21 | this access [field boxfield, field Box1, field Elem] : Elem | +| G.cs:50:18:50:20 | this [field boxfield, field Box1, field Elem] : Elem | G.cs:52:14:52:21 | this access [field boxfield, field Box1, field Elem] : Elem | +| G.cs:52:14:52:21 | access to field boxfield [field Box1, field Elem] : Elem | G.cs:52:14:52:26 | access to field Box1 [field Elem] : Elem | | G.cs:52:14:52:21 | access to field boxfield [field Box1, field Elem] : Elem | G.cs:52:14:52:26 | access to field Box1 [field Elem] : Elem | | G.cs:52:14:52:21 | this access [field boxfield, field Box1, field Elem] : Elem | G.cs:52:14:52:21 | access to field boxfield [field Box1, field Elem] : Elem | +| G.cs:52:14:52:21 | this access [field boxfield, field Box1, field Elem] : Elem | G.cs:52:14:52:21 | access to field boxfield [field Box1, field Elem] : Elem | +| G.cs:52:14:52:26 | access to field Box1 [field Elem] : Elem | G.cs:52:14:52:31 | access to field Elem | | G.cs:52:14:52:26 | access to field Box1 [field Elem] : Elem | G.cs:52:14:52:31 | access to field Elem | | G.cs:63:21:63:27 | this [field Elem] : Elem | G.cs:63:34:63:37 | this access [field Elem] : Elem | +| G.cs:63:21:63:27 | this [field Elem] : Elem | G.cs:63:34:63:37 | this access [field Elem] : Elem | +| G.cs:63:34:63:37 | this access [field Elem] : Elem | G.cs:63:34:63:37 | access to field Elem : Elem | | G.cs:63:34:63:37 | this access [field Elem] : Elem | G.cs:63:34:63:37 | access to field Elem : Elem | | G.cs:64:34:64:34 | e : Elem | G.cs:64:46:64:46 | access to parameter e : Elem | +| G.cs:64:34:64:34 | e : Elem | G.cs:64:46:64:46 | access to parameter e : Elem | +| G.cs:64:46:64:46 | access to parameter e : Elem | G.cs:64:39:64:42 | [post] this access [field Elem] : Elem | | G.cs:64:46:64:46 | access to parameter e : Elem | G.cs:64:39:64:42 | [post] this access [field Elem] : Elem | | G.cs:71:21:71:27 | this [field Box1, field Elem] : Elem | G.cs:71:34:71:37 | this access [field Box1, field Elem] : Elem | +| G.cs:71:21:71:27 | this [field Box1, field Elem] : Elem | G.cs:71:34:71:37 | this access [field Box1, field Elem] : Elem | +| G.cs:71:34:71:37 | this access [field Box1, field Elem] : Elem | G.cs:71:34:71:37 | access to field Box1 [field Elem] : Elem | | G.cs:71:34:71:37 | this access [field Box1, field Elem] : Elem | G.cs:71:34:71:37 | access to field Box1 [field Elem] : Elem | | H.cs:13:15:13:15 | a [field FieldA] : Object | H.cs:16:22:16:22 | access to parameter a [field FieldA] : Object | +| H.cs:13:15:13:15 | a [field FieldA] : Object | H.cs:16:22:16:22 | access to parameter a [field FieldA] : Object | +| H.cs:16:9:16:11 | [post] access to local variable ret [field FieldA] : Object | H.cs:17:16:17:18 | access to local variable ret [field FieldA] : Object | | H.cs:16:9:16:11 | [post] access to local variable ret [field FieldA] : Object | H.cs:17:16:17:18 | access to local variable ret [field FieldA] : Object | | H.cs:16:22:16:22 | access to parameter a [field FieldA] : Object | H.cs:16:22:16:29 | access to field FieldA : Object | +| H.cs:16:22:16:22 | access to parameter a [field FieldA] : Object | H.cs:16:22:16:29 | access to field FieldA : Object | +| H.cs:16:22:16:29 | access to field FieldA : Object | H.cs:16:9:16:11 | [post] access to local variable ret [field FieldA] : Object | | H.cs:16:22:16:29 | access to field FieldA : Object | H.cs:16:9:16:11 | [post] access to local variable ret [field FieldA] : Object | | H.cs:23:9:23:9 | [post] access to local variable a [field FieldA] : Object | H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | -| H.cs:23:20:23:31 | object creation of type Object : Object | H.cs:23:9:23:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:23:9:23:9 | [post] access to local variable a [field FieldA] : Object | H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | +| H.cs:23:20:23:36 | call to method Source<Object> : Object | H.cs:23:9:23:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:23:20:23:36 | call to method Source<Object> : Object | H.cs:23:9:23:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:24:21:24:28 | call to method Clone [field FieldA] : Object | H.cs:25:14:25:18 | access to local variable clone [field FieldA] : Object | | H.cs:24:21:24:28 | call to method Clone [field FieldA] : Object | H.cs:25:14:25:18 | access to local variable clone [field FieldA] : Object | | H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | H.cs:13:15:13:15 | a [field FieldA] : Object | +| H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | H.cs:13:15:13:15 | a [field FieldA] : Object | +| H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | H.cs:24:21:24:28 | call to method Clone [field FieldA] : Object | | H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | H.cs:24:21:24:28 | call to method Clone [field FieldA] : Object | | H.cs:25:14:25:18 | access to local variable clone [field FieldA] : Object | H.cs:25:14:25:25 | access to field FieldA | +| H.cs:25:14:25:18 | access to local variable clone [field FieldA] : Object | H.cs:25:14:25:25 | access to field FieldA | +| H.cs:33:19:33:19 | a [field FieldA] : A | H.cs:36:20:36:20 | access to parameter a [field FieldA] : A | | H.cs:33:19:33:19 | a [field FieldA] : A | H.cs:36:20:36:20 | access to parameter a [field FieldA] : A | | H.cs:33:19:33:19 | a [field FieldA] : Object | H.cs:36:20:36:20 | access to parameter a [field FieldA] : Object | +| H.cs:33:19:33:19 | a [field FieldA] : Object | H.cs:36:20:36:20 | access to parameter a [field FieldA] : Object | +| H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : A | H.cs:37:16:37:16 | access to local variable b [field FieldB] : A | | H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : A | H.cs:37:16:37:16 | access to local variable b [field FieldB] : A | | H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : Object | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | +| H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : Object | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | +| H.cs:36:20:36:20 | access to parameter a [field FieldA] : A | H.cs:36:20:36:27 | access to field FieldA : A | | H.cs:36:20:36:20 | access to parameter a [field FieldA] : A | H.cs:36:20:36:27 | access to field FieldA : A | | H.cs:36:20:36:20 | access to parameter a [field FieldA] : Object | H.cs:36:20:36:27 | access to field FieldA : Object | +| H.cs:36:20:36:20 | access to parameter a [field FieldA] : Object | H.cs:36:20:36:27 | access to field FieldA : Object | +| H.cs:36:20:36:27 | access to field FieldA : A | H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : A | | H.cs:36:20:36:27 | access to field FieldA : A | H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : A | | H.cs:36:20:36:27 | access to field FieldA : Object | H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : Object | +| H.cs:36:20:36:27 | access to field FieldA : Object | H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : Object | | H.cs:43:9:43:9 | [post] access to local variable a [field FieldA] : Object | H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | -| H.cs:43:20:43:31 | object creation of type Object : Object | H.cs:43:9:43:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:43:9:43:9 | [post] access to local variable a [field FieldA] : Object | H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | +| H.cs:43:20:43:36 | call to method Source<Object> : Object | H.cs:43:9:43:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:43:20:43:36 | call to method Source<Object> : Object | H.cs:43:9:43:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:44:17:44:28 | call to method Transform [field FieldB] : Object | H.cs:45:14:45:14 | access to local variable b [field FieldB] : Object | | H.cs:44:17:44:28 | call to method Transform [field FieldB] : Object | H.cs:45:14:45:14 | access to local variable b [field FieldB] : Object | | H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | +| H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | +| H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | H.cs:44:17:44:28 | call to method Transform [field FieldB] : Object | | H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | H.cs:44:17:44:28 | call to method Transform [field FieldB] : Object | | H.cs:45:14:45:14 | access to local variable b [field FieldB] : Object | H.cs:45:14:45:21 | access to field FieldB | +| H.cs:45:14:45:14 | access to local variable b [field FieldB] : Object | H.cs:45:14:45:21 | access to field FieldB | +| H.cs:53:25:53:25 | a [field FieldA] : Object | H.cs:55:21:55:21 | access to parameter a [field FieldA] : Object | | H.cs:53:25:53:25 | a [field FieldA] : Object | H.cs:55:21:55:21 | access to parameter a [field FieldA] : Object | | H.cs:55:21:55:21 | access to parameter a [field FieldA] : Object | H.cs:55:21:55:28 | access to field FieldA : Object | +| H.cs:55:21:55:21 | access to parameter a [field FieldA] : Object | H.cs:55:21:55:28 | access to field FieldA : Object | +| H.cs:55:21:55:28 | access to field FieldA : Object | H.cs:55:9:55:10 | [post] access to parameter b1 [field FieldB] : Object | | H.cs:55:21:55:28 | access to field FieldA : Object | H.cs:55:9:55:10 | [post] access to parameter b1 [field FieldB] : Object | | H.cs:63:9:63:9 | [post] access to local variable a [field FieldA] : Object | H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | -| H.cs:63:20:63:31 | object creation of type Object : Object | H.cs:63:9:63:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:63:9:63:9 | [post] access to local variable a [field FieldA] : Object | H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | +| H.cs:63:20:63:36 | call to method Source<Object> : Object | H.cs:63:9:63:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:63:20:63:36 | call to method Source<Object> : Object | H.cs:63:9:63:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | H.cs:53:25:53:25 | a [field FieldA] : Object | | H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | H.cs:53:25:53:25 | a [field FieldA] : Object | | H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | H.cs:64:25:64:26 | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | H.cs:64:25:64:26 | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:64:25:64:26 | [post] access to local variable b1 [field FieldB] : Object | H.cs:65:14:65:15 | access to local variable b1 [field FieldB] : Object | | H.cs:64:25:64:26 | [post] access to local variable b1 [field FieldB] : Object | H.cs:65:14:65:15 | access to local variable b1 [field FieldB] : Object | | H.cs:65:14:65:15 | access to local variable b1 [field FieldB] : Object | H.cs:65:14:65:22 | access to field FieldB | +| H.cs:65:14:65:15 | access to local variable b1 [field FieldB] : Object | H.cs:65:14:65:22 | access to field FieldB | +| H.cs:77:30:77:30 | o : Object | H.cs:79:20:79:20 | access to parameter o : Object | | H.cs:77:30:77:30 | o : Object | H.cs:79:20:79:20 | access to parameter o : Object | | H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | +| H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | +| H.cs:79:20:79:20 | access to parameter o : Object | H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | | H.cs:79:20:79:20 | access to parameter o : Object | H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | | H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | H.cs:53:25:53:25 | a [field FieldA] : Object | +| H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | H.cs:53:25:53:25 | a [field FieldA] : Object | +| H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | | H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | | H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | H.cs:89:14:89:14 | access to local variable a [field FieldA] : Object | -| H.cs:88:20:88:31 | object creation of type Object : Object | H.cs:77:30:77:30 | o : Object | -| H.cs:88:20:88:31 | object creation of type Object : Object | H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | -| H.cs:88:20:88:31 | object creation of type Object : Object | H.cs:88:34:88:35 | [post] access to local variable b1 [field FieldB] : Object | -| H.cs:88:34:88:35 | [post] access to local variable b1 [field FieldB] : Object | H.cs:90:14:90:15 | access to local variable b1 [field FieldB] : Object | +| H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | H.cs:89:14:89:14 | access to local variable a [field FieldA] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:77:30:77:30 | o : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:77:30:77:30 | o : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:88:39:88:40 | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:88:39:88:40 | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:88:39:88:40 | [post] access to local variable b1 [field FieldB] : Object | H.cs:90:14:90:15 | access to local variable b1 [field FieldB] : Object | +| H.cs:88:39:88:40 | [post] access to local variable b1 [field FieldB] : Object | H.cs:90:14:90:15 | access to local variable b1 [field FieldB] : Object | +| H.cs:89:14:89:14 | access to local variable a [field FieldA] : Object | H.cs:89:14:89:21 | access to field FieldA | | H.cs:89:14:89:14 | access to local variable a [field FieldA] : Object | H.cs:89:14:89:21 | access to field FieldA | | H.cs:90:14:90:15 | access to local variable b1 [field FieldB] : Object | H.cs:90:14:90:22 | access to field FieldB | +| H.cs:90:14:90:15 | access to local variable b1 [field FieldB] : Object | H.cs:90:14:90:22 | access to field FieldB | +| H.cs:102:23:102:23 | a [field FieldA] : Object | H.cs:105:23:105:23 | access to parameter a [field FieldA] : Object | | H.cs:102:23:102:23 | a [field FieldA] : Object | H.cs:105:23:105:23 | access to parameter a [field FieldA] : Object | | H.cs:105:9:105:12 | [post] access to local variable temp [field FieldB, field FieldA] : Object | H.cs:106:29:106:32 | access to local variable temp [field FieldB, field FieldA] : Object | +| H.cs:105:9:105:12 | [post] access to local variable temp [field FieldB, field FieldA] : Object | H.cs:106:29:106:32 | access to local variable temp [field FieldB, field FieldA] : Object | +| H.cs:105:23:105:23 | access to parameter a [field FieldA] : Object | H.cs:105:9:105:12 | [post] access to local variable temp [field FieldB, field FieldA] : Object | | H.cs:105:23:105:23 | access to parameter a [field FieldA] : Object | H.cs:105:9:105:12 | [post] access to local variable temp [field FieldB, field FieldA] : Object | | H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | +| H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | +| H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | H.cs:106:16:106:40 | call to method Transform [field FieldB] : Object | | H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | H.cs:106:16:106:40 | call to method Transform [field FieldB] : Object | | H.cs:106:29:106:32 | access to local variable temp [field FieldB, field FieldA] : Object | H.cs:106:29:106:39 | access to field FieldB [field FieldA] : Object | +| H.cs:106:29:106:32 | access to local variable temp [field FieldB, field FieldA] : Object | H.cs:106:29:106:39 | access to field FieldB [field FieldA] : Object | +| H.cs:106:29:106:39 | access to field FieldB [field FieldA] : Object | H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | | H.cs:106:29:106:39 | access to field FieldB [field FieldA] : Object | H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | | H.cs:112:9:112:9 | [post] access to local variable a [field FieldA] : Object | H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | -| H.cs:112:20:112:31 | object creation of type Object : Object | H.cs:112:9:112:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:112:9:112:9 | [post] access to local variable a [field FieldA] : Object | H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | +| H.cs:112:20:112:36 | call to method Source<Object> : Object | H.cs:112:9:112:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:112:20:112:36 | call to method Source<Object> : Object | H.cs:112:9:112:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:113:17:113:32 | call to method TransformWrap [field FieldB] : Object | H.cs:114:14:114:14 | access to local variable b [field FieldB] : Object | | H.cs:113:17:113:32 | call to method TransformWrap [field FieldB] : Object | H.cs:114:14:114:14 | access to local variable b [field FieldB] : Object | | H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | H.cs:102:23:102:23 | a [field FieldA] : Object | +| H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | H.cs:102:23:102:23 | a [field FieldA] : Object | +| H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | H.cs:113:17:113:32 | call to method TransformWrap [field FieldB] : Object | | H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | H.cs:113:17:113:32 | call to method TransformWrap [field FieldB] : Object | | H.cs:114:14:114:14 | access to local variable b [field FieldB] : Object | H.cs:114:14:114:21 | access to field FieldB | +| H.cs:114:14:114:14 | access to local variable b [field FieldB] : Object | H.cs:114:14:114:21 | access to field FieldB | +| H.cs:122:18:122:18 | a [field FieldA] : Object | H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | | H.cs:122:18:122:18 | a [field FieldA] : Object | H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | | H.cs:124:16:124:27 | call to method Transform [field FieldB] : Object | H.cs:124:16:124:34 | access to field FieldB : Object | +| H.cs:124:16:124:27 | call to method Transform [field FieldB] : Object | H.cs:124:16:124:34 | access to field FieldB : Object | +| H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | | H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | | H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | H.cs:124:16:124:27 | call to method Transform [field FieldB] : Object | +| H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | H.cs:124:16:124:27 | call to method Transform [field FieldB] : Object | | H.cs:130:9:130:9 | [post] access to local variable a [field FieldA] : Object | H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | -| H.cs:130:20:130:31 | object creation of type Object : Object | H.cs:130:9:130:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:130:9:130:9 | [post] access to local variable a [field FieldA] : Object | H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | +| H.cs:130:20:130:36 | call to method Source<Object> : Object | H.cs:130:9:130:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:130:20:130:36 | call to method Source<Object> : Object | H.cs:130:9:130:9 | [post] access to local variable a [field FieldA] : Object | +| H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | H.cs:122:18:122:18 | a [field FieldA] : Object | | H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | H.cs:122:18:122:18 | a [field FieldA] : Object | | H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | H.cs:131:14:131:19 | call to method Get | +| H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | H.cs:131:14:131:19 | call to method Get | +| H.cs:138:27:138:27 | o : A | H.cs:141:20:141:25 | ... as ... : A | | H.cs:138:27:138:27 | o : A | H.cs:141:20:141:25 | ... as ... : A | | H.cs:141:9:141:9 | [post] access to local variable a [field FieldA] : A | H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | +| H.cs:141:9:141:9 | [post] access to local variable a [field FieldA] : A | H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | +| H.cs:141:20:141:25 | ... as ... : A | H.cs:141:9:141:9 | [post] access to local variable a [field FieldA] : A | | H.cs:141:20:141:25 | ... as ... : A | H.cs:141:9:141:9 | [post] access to local variable a [field FieldA] : A | | H.cs:142:16:142:27 | call to method Transform [field FieldB] : A | H.cs:142:16:142:34 | access to field FieldB : A | +| H.cs:142:16:142:27 | call to method Transform [field FieldB] : A | H.cs:142:16:142:34 | access to field FieldB : A | +| H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | H.cs:33:19:33:19 | a [field FieldA] : A | | H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | H.cs:33:19:33:19 | a [field FieldA] : A | | H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | H.cs:142:16:142:27 | call to method Transform [field FieldB] : A | -| H.cs:147:17:147:32 | call to method Through : A | H.cs:148:14:148:14 | access to local variable a | -| H.cs:147:25:147:31 | object creation of type A : A | H.cs:138:27:138:27 | o : A | -| H.cs:147:25:147:31 | object creation of type A : A | H.cs:147:17:147:32 | call to method Through : A | +| H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | H.cs:142:16:142:27 | call to method Transform [field FieldB] : A | +| H.cs:147:17:147:39 | call to method Through : A | H.cs:148:14:148:14 | access to local variable a | +| H.cs:147:17:147:39 | call to method Through : A | H.cs:148:14:148:14 | access to local variable a | +| H.cs:147:25:147:38 | call to method Source<A> : A | H.cs:138:27:138:27 | o : A | +| H.cs:147:25:147:38 | call to method Source<A> : A | H.cs:138:27:138:27 | o : A | +| H.cs:147:25:147:38 | call to method Source<A> : A | H.cs:147:17:147:39 | call to method Through : A | +| H.cs:147:25:147:38 | call to method Source<A> : A | H.cs:147:17:147:39 | call to method Through : A | | H.cs:153:32:153:32 | o : Object | H.cs:156:20:156:20 | access to parameter o : Object | -| H.cs:155:17:155:23 | object creation of type B : B | H.cs:156:9:156:9 | access to local variable b : B | +| H.cs:153:32:153:32 | o : Object | H.cs:156:20:156:20 | access to parameter o : Object | +| H.cs:155:17:155:30 | call to method Source<B> : B | H.cs:156:9:156:9 | access to local variable b : B | +| H.cs:155:17:155:30 | call to method Source<B> : B | H.cs:156:9:156:9 | access to local variable b : B | +| H.cs:156:9:156:9 | [post] access to local variable b [field FieldB] : Object | H.cs:157:20:157:20 | access to local variable b [field FieldB] : Object | | H.cs:156:9:156:9 | [post] access to local variable b [field FieldB] : Object | H.cs:157:20:157:20 | access to local variable b [field FieldB] : Object | | H.cs:156:9:156:9 | access to local variable b : B | H.cs:157:20:157:20 | access to local variable b : B | +| H.cs:156:9:156:9 | access to local variable b : B | H.cs:157:20:157:20 | access to local variable b : B | +| H.cs:156:20:156:20 | access to parameter o : Object | H.cs:156:9:156:9 | [post] access to local variable b [field FieldB] : Object | | H.cs:156:20:156:20 | access to parameter o : Object | H.cs:156:9:156:9 | [post] access to local variable b [field FieldB] : Object | | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA] : B | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA] : B | +| H.cs:157:9:157:9 | [post] access to parameter a [field FieldA] : B | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA] : B | +| H.cs:157:20:157:20 | access to local variable b : B | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA] : B | | H.cs:157:20:157:20 | access to local variable b : B | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA] : B | | H.cs:157:20:157:20 | access to local variable b [field FieldB] : Object | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | -| H.cs:163:17:163:28 | object creation of type Object : Object | H.cs:164:22:164:22 | access to local variable o : Object | -| H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | H.cs:165:21:165:21 | access to local variable a [field FieldA, field FieldB] : Object | -| H.cs:164:19:164:19 | [post] access to local variable a [field FieldA] : B | H.cs:165:21:165:21 | access to local variable a [field FieldA] : B | +| H.cs:157:20:157:20 | access to local variable b [field FieldB] : Object | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | +| H.cs:163:17:163:35 | call to method Source<Object> : Object | H.cs:164:22:164:22 | access to local variable o : Object | +| H.cs:163:17:163:35 | call to method Source<Object> : Object | H.cs:164:22:164:22 | access to local variable o : Object | +| H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | H.cs:165:20:165:20 | access to local variable a [field FieldA, field FieldB] : Object | +| H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | H.cs:165:20:165:20 | access to local variable a [field FieldA, field FieldB] : Object | +| H.cs:164:19:164:19 | [post] access to local variable a [field FieldA] : B | H.cs:165:20:165:20 | access to local variable a [field FieldA] : B | +| H.cs:164:19:164:19 | [post] access to local variable a [field FieldA] : B | H.cs:165:20:165:20 | access to local variable a [field FieldA] : B | +| H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | | H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | | H.cs:164:22:164:22 | access to local variable o : Object | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | -| H.cs:165:17:165:28 | (...) ... : B | H.cs:166:14:166:14 | access to local variable b | -| H.cs:165:17:165:28 | (...) ... [field FieldB] : Object | H.cs:167:14:167:14 | access to local variable b [field FieldB] : Object | -| H.cs:165:21:165:21 | access to local variable a [field FieldA, field FieldB] : Object | H.cs:165:21:165:28 | access to field FieldA [field FieldB] : Object | -| H.cs:165:21:165:21 | access to local variable a [field FieldA] : B | H.cs:165:21:165:28 | access to field FieldA : B | -| H.cs:165:21:165:28 | access to field FieldA : B | H.cs:165:17:165:28 | (...) ... : B | -| H.cs:165:21:165:28 | access to field FieldA [field FieldB] : Object | H.cs:165:17:165:28 | (...) ... [field FieldB] : Object | +| H.cs:164:22:164:22 | access to local variable o : Object | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | +| H.cs:165:17:165:27 | (...) ... : B | H.cs:166:14:166:14 | access to local variable b | +| H.cs:165:17:165:27 | (...) ... : B | H.cs:166:14:166:14 | access to local variable b | +| H.cs:165:17:165:27 | (...) ... [field FieldB] : Object | H.cs:167:14:167:14 | access to local variable b [field FieldB] : Object | +| H.cs:165:17:165:27 | (...) ... [field FieldB] : Object | H.cs:167:14:167:14 | access to local variable b [field FieldB] : Object | +| H.cs:165:20:165:20 | access to local variable a [field FieldA, field FieldB] : Object | H.cs:165:20:165:27 | access to field FieldA [field FieldB] : Object | +| H.cs:165:20:165:20 | access to local variable a [field FieldA, field FieldB] : Object | H.cs:165:20:165:27 | access to field FieldA [field FieldB] : Object | +| H.cs:165:20:165:20 | access to local variable a [field FieldA] : B | H.cs:165:20:165:27 | access to field FieldA : B | +| H.cs:165:20:165:20 | access to local variable a [field FieldA] : B | H.cs:165:20:165:27 | access to field FieldA : B | +| H.cs:165:20:165:27 | access to field FieldA : B | H.cs:165:17:165:27 | (...) ... : B | +| H.cs:165:20:165:27 | access to field FieldA : B | H.cs:165:17:165:27 | (...) ... : B | +| H.cs:165:20:165:27 | access to field FieldA [field FieldB] : Object | H.cs:165:17:165:27 | (...) ... [field FieldB] : Object | +| H.cs:165:20:165:27 | access to field FieldA [field FieldB] : Object | H.cs:165:17:165:27 | (...) ... [field FieldB] : Object | +| H.cs:167:14:167:14 | access to local variable b [field FieldB] : Object | H.cs:167:14:167:21 | access to field FieldB | | H.cs:167:14:167:14 | access to local variable b [field FieldB] : Object | H.cs:167:14:167:21 | access to field FieldB | | I.cs:7:9:7:14 | [post] this access [field Field1] : Object | I.cs:21:13:21:19 | object creation of type I [field Field1] : Object | +| I.cs:7:9:7:14 | [post] this access [field Field1] : Object | I.cs:21:13:21:19 | object creation of type I [field Field1] : Object | | I.cs:7:9:7:14 | [post] this access [field Field1] : Object | I.cs:26:13:26:37 | [pre-initializer] object creation of type I [field Field1] : Object | -| I.cs:7:18:7:29 | object creation of type Object : Object | I.cs:7:9:7:14 | [post] this access [field Field1] : Object | -| I.cs:13:17:13:28 | object creation of type Object : Object | I.cs:15:20:15:20 | access to local variable o : Object | +| I.cs:7:9:7:14 | [post] this access [field Field1] : Object | I.cs:26:13:26:37 | [pre-initializer] object creation of type I [field Field1] : Object | +| I.cs:7:18:7:34 | call to method Source<Object> : Object | I.cs:7:9:7:14 | [post] this access [field Field1] : Object | +| I.cs:7:18:7:34 | call to method Source<Object> : Object | I.cs:7:9:7:14 | [post] this access [field Field1] : Object | +| I.cs:13:17:13:33 | call to method Source<Object> : Object | I.cs:15:20:15:20 | access to local variable o : Object | +| I.cs:13:17:13:33 | call to method Source<Object> : Object | I.cs:15:20:15:20 | access to local variable o : Object | +| I.cs:15:9:15:9 | [post] access to local variable i [field Field1] : Object | I.cs:16:9:16:9 | access to local variable i [field Field1] : Object | | I.cs:15:9:15:9 | [post] access to local variable i [field Field1] : Object | I.cs:16:9:16:9 | access to local variable i [field Field1] : Object | | I.cs:15:20:15:20 | access to local variable o : Object | I.cs:15:9:15:9 | [post] access to local variable i [field Field1] : Object | +| I.cs:15:20:15:20 | access to local variable o : Object | I.cs:15:9:15:9 | [post] access to local variable i [field Field1] : Object | +| I.cs:16:9:16:9 | access to local variable i [field Field1] : Object | I.cs:17:9:17:9 | access to local variable i [field Field1] : Object | | I.cs:16:9:16:9 | access to local variable i [field Field1] : Object | I.cs:17:9:17:9 | access to local variable i [field Field1] : Object | | I.cs:17:9:17:9 | access to local variable i [field Field1] : Object | I.cs:18:14:18:14 | access to local variable i [field Field1] : Object | +| I.cs:17:9:17:9 | access to local variable i [field Field1] : Object | I.cs:18:14:18:14 | access to local variable i [field Field1] : Object | +| I.cs:18:14:18:14 | access to local variable i [field Field1] : Object | I.cs:18:14:18:21 | access to field Field1 | | I.cs:18:14:18:14 | access to local variable i [field Field1] : Object | I.cs:18:14:18:21 | access to field Field1 | | I.cs:21:13:21:19 | object creation of type I [field Field1] : Object | I.cs:22:9:22:9 | access to local variable i [field Field1] : Object | +| I.cs:21:13:21:19 | object creation of type I [field Field1] : Object | I.cs:22:9:22:9 | access to local variable i [field Field1] : Object | +| I.cs:22:9:22:9 | access to local variable i [field Field1] : Object | I.cs:23:14:23:14 | access to local variable i [field Field1] : Object | | I.cs:22:9:22:9 | access to local variable i [field Field1] : Object | I.cs:23:14:23:14 | access to local variable i [field Field1] : Object | | I.cs:23:14:23:14 | access to local variable i [field Field1] : Object | I.cs:23:14:23:21 | access to field Field1 | +| I.cs:23:14:23:14 | access to local variable i [field Field1] : Object | I.cs:23:14:23:21 | access to field Field1 | +| I.cs:26:13:26:37 | [pre-initializer] object creation of type I [field Field1] : Object | I.cs:27:14:27:14 | access to local variable i [field Field1] : Object | | I.cs:26:13:26:37 | [pre-initializer] object creation of type I [field Field1] : Object | I.cs:27:14:27:14 | access to local variable i [field Field1] : Object | | I.cs:27:14:27:14 | access to local variable i [field Field1] : Object | I.cs:27:14:27:21 | access to field Field1 | -| I.cs:31:13:31:24 | object creation of type Object : Object | I.cs:32:20:32:20 | access to local variable o : Object | +| I.cs:27:14:27:14 | access to local variable i [field Field1] : Object | I.cs:27:14:27:21 | access to field Field1 | +| I.cs:31:13:31:29 | call to method Source<Object> : Object | I.cs:32:20:32:20 | access to local variable o : Object | +| I.cs:31:13:31:29 | call to method Source<Object> : Object | I.cs:32:20:32:20 | access to local variable o : Object | +| I.cs:32:9:32:9 | [post] access to local variable i [field Field1] : Object | I.cs:33:9:33:9 | access to local variable i [field Field1] : Object | | I.cs:32:9:32:9 | [post] access to local variable i [field Field1] : Object | I.cs:33:9:33:9 | access to local variable i [field Field1] : Object | | I.cs:32:20:32:20 | access to local variable o : Object | I.cs:32:9:32:9 | [post] access to local variable i [field Field1] : Object | +| I.cs:32:20:32:20 | access to local variable o : Object | I.cs:32:9:32:9 | [post] access to local variable i [field Field1] : Object | +| I.cs:33:9:33:9 | access to local variable i [field Field1] : Object | I.cs:34:12:34:12 | access to local variable i [field Field1] : Object | | I.cs:33:9:33:9 | access to local variable i [field Field1] : Object | I.cs:34:12:34:12 | access to local variable i [field Field1] : Object | | I.cs:34:12:34:12 | access to local variable i [field Field1] : Object | I.cs:37:23:37:23 | i [field Field1] : Object | +| I.cs:34:12:34:12 | access to local variable i [field Field1] : Object | I.cs:37:23:37:23 | i [field Field1] : Object | +| I.cs:37:23:37:23 | i [field Field1] : Object | I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | | I.cs:37:23:37:23 | i [field Field1] : Object | I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | | I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | +| I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 | -| J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:13:29:13:29 | access to local variable o : Object | -| J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:21:36:21:36 | access to local variable o : Object | +| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 | +| J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:13:29:13:29 | access to local variable o : Object | +| J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:13:29:13:29 | access to local variable o : Object | +| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | | J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | +| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | +| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 | | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 | | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 | -| J.cs:21:18:21:38 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | -| J.cs:21:36:21:36 | access to local variable o : Object | J.cs:21:18:21:38 | ... with { ... } [property Prop2] : Object | +| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 | +| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:21:36:21:52 | call to method Source<Object> : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | +| J.cs:21:36:21:52 | call to method Source<Object> : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | +| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 | | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 | | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 | +| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 | nodes -| A.cs:5:17:5:23 | object creation of type C : C | semmle.label | object creation of type C : C | +| A.cs:5:17:5:28 | call to method Source<C> : C | semmle.label | call to method Source<C> : C | +| A.cs:5:17:5:28 | call to method Source<C> : C | semmle.label | call to method Source<C> : C | +| A.cs:6:17:6:25 | call to method Make [field c] : C | semmle.label | call to method Make [field c] : C | | A.cs:6:17:6:25 | call to method Make [field c] : C | semmle.label | call to method Make [field c] : C | | A.cs:6:24:6:24 | access to local variable c : C | semmle.label | access to local variable c : C | +| A.cs:6:24:6:24 | access to local variable c : C | semmle.label | access to local variable c : C | +| A.cs:7:14:7:14 | access to local variable b [field c] : C | semmle.label | access to local variable b [field c] : C | | A.cs:7:14:7:14 | access to local variable b [field c] : C | semmle.label | access to local variable b [field c] : C | | A.cs:7:14:7:16 | access to field c | semmle.label | access to field c | +| A.cs:7:14:7:16 | access to field c | semmle.label | access to field c | | A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | semmle.label | [post] access to local variable b [field c] : C1 | -| A.cs:13:15:13:22 | object creation of type C1 : C1 | semmle.label | object creation of type C1 : C1 | +| A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | semmle.label | [post] access to local variable b [field c] : C1 | +| A.cs:13:15:13:29 | call to method Source<C1> : C1 | semmle.label | call to method Source<C1> : C1 | +| A.cs:13:15:13:29 | call to method Source<C1> : C1 | semmle.label | call to method Source<C1> : C1 | +| A.cs:14:14:14:14 | access to local variable b [field c] : C1 | semmle.label | access to local variable b [field c] : C1 | | A.cs:14:14:14:14 | access to local variable b [field c] : C1 | semmle.label | access to local variable b [field c] : C1 | | A.cs:14:14:14:20 | call to method Get | semmle.label | call to method Get | -| A.cs:15:14:15:35 | call to method Get | semmle.label | call to method Get | -| A.cs:15:15:15:28 | object creation of type B [field c] : C | semmle.label | object creation of type B [field c] : C | -| A.cs:15:21:15:27 | object creation of type C : C | semmle.label | object creation of type C : C | -| A.cs:22:14:22:33 | call to method SetOnB [field c] : C2 | semmle.label | call to method SetOnB [field c] : C2 | -| A.cs:22:25:22:32 | object creation of type C2 : C2 | semmle.label | object creation of type C2 : C2 | +| A.cs:14:14:14:20 | call to method Get | semmle.label | call to method Get | +| A.cs:15:14:15:42 | call to method Get | semmle.label | call to method Get | +| A.cs:15:14:15:42 | call to method Get | semmle.label | call to method Get | +| A.cs:15:15:15:35 | object creation of type B [field c] : C | semmle.label | object creation of type B [field c] : C | +| A.cs:15:15:15:35 | object creation of type B [field c] : C | semmle.label | object creation of type B [field c] : C | +| A.cs:15:21:15:34 | call to method Source<C> : C | semmle.label | call to method Source<C> : C | +| A.cs:15:21:15:34 | call to method Source<C> : C | semmle.label | call to method Source<C> : C | +| A.cs:22:14:22:38 | call to method SetOnB [field c] : C2 | semmle.label | call to method SetOnB [field c] : C2 | +| A.cs:22:14:22:38 | call to method SetOnB [field c] : C2 | semmle.label | call to method SetOnB [field c] : C2 | +| A.cs:22:25:22:37 | call to method Source<C2> : C2 | semmle.label | call to method Source<C2> : C2 | +| A.cs:22:25:22:37 | call to method Source<C2> : C2 | semmle.label | call to method Source<C2> : C2 | +| A.cs:24:14:24:15 | access to local variable b2 [field c] : C2 | semmle.label | access to local variable b2 [field c] : C2 | | A.cs:24:14:24:15 | access to local variable b2 [field c] : C2 | semmle.label | access to local variable b2 [field c] : C2 | | A.cs:24:14:24:17 | access to field c | semmle.label | access to field c | -| A.cs:31:14:31:37 | call to method SetOnBWrap [field c] : C2 | semmle.label | call to method SetOnBWrap [field c] : C2 | -| A.cs:31:29:31:36 | object creation of type C2 : C2 | semmle.label | object creation of type C2 : C2 | +| A.cs:24:14:24:17 | access to field c | semmle.label | access to field c | +| A.cs:31:14:31:42 | call to method SetOnBWrap [field c] : C2 | semmle.label | call to method SetOnBWrap [field c] : C2 | +| A.cs:31:14:31:42 | call to method SetOnBWrap [field c] : C2 | semmle.label | call to method SetOnBWrap [field c] : C2 | +| A.cs:31:29:31:41 | call to method Source<C2> : C2 | semmle.label | call to method Source<C2> : C2 | +| A.cs:31:29:31:41 | call to method Source<C2> : C2 | semmle.label | call to method Source<C2> : C2 | +| A.cs:33:14:33:15 | access to local variable b2 [field c] : C2 | semmle.label | access to local variable b2 [field c] : C2 | | A.cs:33:14:33:15 | access to local variable b2 [field c] : C2 | semmle.label | access to local variable b2 [field c] : C2 | | A.cs:33:14:33:17 | access to field c | semmle.label | access to field c | +| A.cs:33:14:33:17 | access to field c | semmle.label | access to field c | +| A.cs:36:33:36:33 | c : C2 | semmle.label | c : C2 | | A.cs:36:33:36:33 | c : C2 | semmle.label | c : C2 | | A.cs:38:18:38:30 | call to method SetOnB [field c] : C2 | semmle.label | call to method SetOnB [field c] : C2 | +| A.cs:38:18:38:30 | call to method SetOnB [field c] : C2 | semmle.label | call to method SetOnB [field c] : C2 | +| A.cs:38:29:38:29 | access to parameter c : C2 | semmle.label | access to parameter c : C2 | | A.cs:38:29:38:29 | access to parameter c : C2 | semmle.label | access to parameter c : C2 | | A.cs:39:16:39:28 | ... ? ... : ... [field c] : C2 | semmle.label | ... ? ... : ... [field c] : C2 | +| A.cs:39:16:39:28 | ... ? ... : ... [field c] : C2 | semmle.label | ... ? ... : ... [field c] : C2 | +| A.cs:42:29:42:29 | c : C2 | semmle.label | c : C2 | | A.cs:42:29:42:29 | c : C2 | semmle.label | c : C2 | | A.cs:47:13:47:14 | [post] access to local variable b2 [field c] : C2 | semmle.label | [post] access to local variable b2 [field c] : C2 | +| A.cs:47:13:47:14 | [post] access to local variable b2 [field c] : C2 | semmle.label | [post] access to local variable b2 [field c] : C2 | +| A.cs:47:20:47:20 | access to parameter c : C2 | semmle.label | access to parameter c : C2 | | A.cs:47:20:47:20 | access to parameter c : C2 | semmle.label | access to parameter c : C2 | | A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | semmle.label | access to local variable b2 [field c] : C2 | -| A.cs:55:17:55:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | semmle.label | access to local variable b2 [field c] : C2 | +| A.cs:55:17:55:28 | call to method Source<A> : A | semmle.label | call to method Source<A> : A | +| A.cs:55:17:55:28 | call to method Source<A> : A | semmle.label | call to method Source<A> : A | +| A.cs:57:9:57:10 | [post] access to local variable c1 [field a] : A | semmle.label | [post] access to local variable c1 [field a] : A | | A.cs:57:9:57:10 | [post] access to local variable c1 [field a] : A | semmle.label | [post] access to local variable c1 [field a] : A | | A.cs:57:16:57:16 | access to local variable a : A | semmle.label | access to local variable a : A | +| A.cs:57:16:57:16 | access to local variable a : A | semmle.label | access to local variable a : A | +| A.cs:58:12:58:13 | access to local variable c1 [field a] : A | semmle.label | access to local variable c1 [field a] : A | | A.cs:58:12:58:13 | access to local variable c1 [field a] : A | semmle.label | access to local variable c1 [field a] : A | | A.cs:60:22:60:22 | c [field a] : A | semmle.label | c [field a] : A | +| A.cs:60:22:60:22 | c [field a] : A | semmle.label | c [field a] : A | +| A.cs:64:18:64:26 | access to field a | semmle.label | access to field a | | A.cs:64:18:64:26 | access to field a | semmle.label | access to field a | | A.cs:64:19:64:23 | (...) ... [field a] : A | semmle.label | (...) ... [field a] : A | +| A.cs:64:19:64:23 | (...) ... [field a] : A | semmle.label | (...) ... [field a] : A | | A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | semmle.label | [post] access to parameter b [field c] : C | -| A.cs:83:15:83:21 | object creation of type C : C | semmle.label | object creation of type C : C | +| A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | semmle.label | [post] access to parameter b [field c] : C | +| A.cs:83:15:83:26 | call to method Source<C> : C | semmle.label | call to method Source<C> : C | +| A.cs:83:15:83:26 | call to method Source<C> : C | semmle.label | call to method Source<C> : C | +| A.cs:88:12:88:12 | [post] access to local variable b [field c] : C | semmle.label | [post] access to local variable b [field c] : C | | A.cs:88:12:88:12 | [post] access to local variable b [field c] : C | semmle.label | [post] access to local variable b [field c] : C | | A.cs:89:14:89:14 | access to local variable b [field c] : C | semmle.label | access to local variable b [field c] : C | +| A.cs:89:14:89:14 | access to local variable b [field c] : C | semmle.label | access to local variable b [field c] : C | +| A.cs:89:14:89:16 | access to field c | semmle.label | access to field c | | A.cs:89:14:89:16 | access to field c | semmle.label | access to field c | | A.cs:95:20:95:20 | b : B | semmle.label | b : B | +| A.cs:95:20:95:20 | b : B | semmle.label | b : B | +| A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | semmle.label | [post] access to parameter b [field c] : C | | A.cs:97:13:97:13 | [post] access to parameter b [field c] : C | semmle.label | [post] access to parameter b [field c] : C | | A.cs:97:13:97:13 | access to parameter b : B | semmle.label | access to parameter b : B | -| A.cs:97:19:97:25 | object creation of type C : C | semmle.label | object creation of type C : C | +| A.cs:97:13:97:13 | access to parameter b : B | semmle.label | access to parameter b : B | +| A.cs:97:19:97:32 | call to method Source<C> : C | semmle.label | call to method Source<C> : C | +| A.cs:97:19:97:32 | call to method Source<C> : C | semmle.label | call to method Source<C> : C | +| A.cs:98:13:98:16 | [post] this access [field b, field c] : C | semmle.label | [post] this access [field b, field c] : C | | A.cs:98:13:98:16 | [post] this access [field b, field c] : C | semmle.label | [post] this access [field b, field c] : C | | A.cs:98:13:98:16 | [post] this access [field b] : B | semmle.label | [post] this access [field b] : B | | A.cs:98:13:98:16 | [post] this access [field b] : B | semmle.label | [post] this access [field b] : B | -| A.cs:98:22:98:36 | ... ? ... : ... : B | semmle.label | ... ? ... : ... : B | -| A.cs:98:22:98:36 | ... ? ... : ... : B | semmle.label | ... ? ... : ... : B | -| A.cs:98:22:98:36 | ... ? ... : ... [field c] : C | semmle.label | ... ? ... : ... [field c] : C | -| A.cs:98:30:98:36 | object creation of type B : B | semmle.label | object creation of type B : B | -| A.cs:104:17:104:23 | object creation of type B : B | semmle.label | object creation of type B : B | +| A.cs:98:13:98:16 | [post] this access [field b] : B | semmle.label | [post] this access [field b] : B | +| A.cs:98:13:98:16 | [post] this access [field b] : B | semmle.label | [post] this access [field b] : B | +| A.cs:98:22:98:43 | ... ? ... : ... : B | semmle.label | ... ? ... : ... : B | +| A.cs:98:22:98:43 | ... ? ... : ... : B | semmle.label | ... ? ... : ... : B | +| A.cs:98:22:98:43 | ... ? ... : ... : B | semmle.label | ... ? ... : ... : B | +| A.cs:98:22:98:43 | ... ? ... : ... : B | semmle.label | ... ? ... : ... : B | +| A.cs:98:22:98:43 | ... ? ... : ... [field c] : C | semmle.label | ... ? ... : ... [field c] : C | +| A.cs:98:22:98:43 | ... ? ... : ... [field c] : C | semmle.label | ... ? ... : ... [field c] : C | +| A.cs:98:30:98:43 | call to method Source<B> : B | semmle.label | call to method Source<B> : B | +| A.cs:98:30:98:43 | call to method Source<B> : B | semmle.label | call to method Source<B> : B | +| A.cs:104:17:104:30 | call to method Source<B> : B | semmle.label | call to method Source<B> : B | +| A.cs:104:17:104:30 | call to method Source<B> : B | semmle.label | call to method Source<B> : B | +| A.cs:105:17:105:29 | object creation of type D [field b, field c] : C | semmle.label | object creation of type D [field b, field c] : C | | A.cs:105:17:105:29 | object creation of type D [field b, field c] : C | semmle.label | object creation of type D [field b, field c] : C | | A.cs:105:17:105:29 | object creation of type D [field b] : B | semmle.label | object creation of type D [field b] : B | +| A.cs:105:17:105:29 | object creation of type D [field b] : B | semmle.label | object creation of type D [field b] : B | +| A.cs:105:23:105:23 | [post] access to local variable b [field c] : C | semmle.label | [post] access to local variable b [field c] : C | | A.cs:105:23:105:23 | [post] access to local variable b [field c] : C | semmle.label | [post] access to local variable b [field c] : C | | A.cs:105:23:105:23 | access to local variable b : B | semmle.label | access to local variable b : B | +| A.cs:105:23:105:23 | access to local variable b : B | semmle.label | access to local variable b : B | +| A.cs:106:14:106:14 | access to local variable d [field b] : B | semmle.label | access to local variable d [field b] : B | | A.cs:106:14:106:14 | access to local variable d [field b] : B | semmle.label | access to local variable d [field b] : B | | A.cs:106:14:106:16 | access to field b | semmle.label | access to field b | +| A.cs:106:14:106:16 | access to field b | semmle.label | access to field b | +| A.cs:107:14:107:14 | access to local variable d [field b, field c] : C | semmle.label | access to local variable d [field b, field c] : C | | A.cs:107:14:107:14 | access to local variable d [field b, field c] : C | semmle.label | access to local variable d [field b, field c] : C | | A.cs:107:14:107:16 | access to field b [field c] : C | semmle.label | access to field b [field c] : C | +| A.cs:107:14:107:16 | access to field b [field c] : C | semmle.label | access to field b [field c] : C | +| A.cs:107:14:107:18 | access to field c | semmle.label | access to field c | | A.cs:107:14:107:18 | access to field c | semmle.label | access to field c | | A.cs:108:14:108:14 | access to local variable b [field c] : C | semmle.label | access to local variable b [field c] : C | +| A.cs:108:14:108:14 | access to local variable b [field c] : C | semmle.label | access to local variable b [field c] : C | | A.cs:108:14:108:16 | access to field c | semmle.label | access to field c | -| A.cs:113:17:113:23 | object creation of type B : B | semmle.label | object creation of type B : B | +| A.cs:108:14:108:16 | access to field c | semmle.label | access to field c | +| A.cs:113:17:113:29 | call to method Source<B> : B | semmle.label | call to method Source<B> : B | +| A.cs:113:17:113:29 | call to method Source<B> : B | semmle.label | call to method Source<B> : B | +| A.cs:114:18:114:54 | object creation of type MyList [field head] : B | semmle.label | object creation of type MyList [field head] : B | | A.cs:114:18:114:54 | object creation of type MyList [field head] : B | semmle.label | object creation of type MyList [field head] : B | | A.cs:114:29:114:29 | access to local variable b : B | semmle.label | access to local variable b : B | +| A.cs:114:29:114:29 | access to local variable b : B | semmle.label | access to local variable b : B | +| A.cs:115:18:115:37 | object creation of type MyList [field next, field head] : B | semmle.label | object creation of type MyList [field next, field head] : B | | A.cs:115:18:115:37 | object creation of type MyList [field next, field head] : B | semmle.label | object creation of type MyList [field next, field head] : B | | A.cs:115:35:115:36 | access to local variable l1 [field head] : B | semmle.label | access to local variable l1 [field head] : B | +| A.cs:115:35:115:36 | access to local variable l1 [field head] : B | semmle.label | access to local variable l1 [field head] : B | +| A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | semmle.label | object creation of type MyList [field next, field next, field head] : B | | A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | semmle.label | object creation of type MyList [field next, field next, field head] : B | | A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | semmle.label | access to local variable l2 [field next, field head] : B | +| A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | semmle.label | access to local variable l2 [field next, field head] : B | +| A.cs:119:14:119:15 | access to local variable l3 [field next, field next, field head] : B | semmle.label | access to local variable l3 [field next, field next, field head] : B | | A.cs:119:14:119:15 | access to local variable l3 [field next, field next, field head] : B | semmle.label | access to local variable l3 [field next, field next, field head] : B | | A.cs:119:14:119:20 | access to field next [field next, field head] : B | semmle.label | access to field next [field next, field head] : B | +| A.cs:119:14:119:20 | access to field next [field next, field head] : B | semmle.label | access to field next [field next, field head] : B | +| A.cs:119:14:119:25 | access to field next [field head] : B | semmle.label | access to field next [field head] : B | | A.cs:119:14:119:25 | access to field next [field head] : B | semmle.label | access to field next [field head] : B | | A.cs:119:14:119:30 | access to field head | semmle.label | access to field head | +| A.cs:119:14:119:30 | access to field head | semmle.label | access to field head | +| A.cs:121:41:121:41 | access to local variable l [field next, field head] : B | semmle.label | access to local variable l [field next, field head] : B | | A.cs:121:41:121:41 | access to local variable l [field next, field head] : B | semmle.label | access to local variable l [field next, field head] : B | | A.cs:121:41:121:41 | access to local variable l [field next, field next, field head] : B | semmle.label | access to local variable l [field next, field next, field head] : B | +| A.cs:121:41:121:41 | access to local variable l [field next, field next, field head] : B | semmle.label | access to local variable l [field next, field next, field head] : B | +| A.cs:121:41:121:46 | access to field next [field head] : B | semmle.label | access to field next [field head] : B | | A.cs:121:41:121:46 | access to field next [field head] : B | semmle.label | access to field next [field head] : B | | A.cs:121:41:121:46 | access to field next [field next, field head] : B | semmle.label | access to field next [field next, field head] : B | +| A.cs:121:41:121:46 | access to field next [field next, field head] : B | semmle.label | access to field next [field next, field head] : B | +| A.cs:123:18:123:18 | access to local variable l [field head] : B | semmle.label | access to local variable l [field head] : B | | A.cs:123:18:123:18 | access to local variable l [field head] : B | semmle.label | access to local variable l [field head] : B | | A.cs:123:18:123:23 | access to field head | semmle.label | access to field head | +| A.cs:123:18:123:23 | access to field head | semmle.label | access to field head | +| A.cs:141:20:141:20 | c : C | semmle.label | c : C | | A.cs:141:20:141:20 | c : C | semmle.label | c : C | | A.cs:143:13:143:16 | [post] this access [field c] : C | semmle.label | [post] this access [field c] : C | +| A.cs:143:13:143:16 | [post] this access [field c] : C | semmle.label | [post] this access [field c] : C | +| A.cs:143:22:143:22 | access to parameter c : C | semmle.label | access to parameter c : C | | A.cs:143:22:143:22 | access to parameter c : C | semmle.label | access to parameter c : C | | A.cs:145:27:145:27 | c : C | semmle.label | c : C | +| A.cs:145:27:145:27 | c : C | semmle.label | c : C | +| A.cs:145:27:145:27 | c : C1 | semmle.label | c : C1 | | A.cs:145:27:145:27 | c : C1 | semmle.label | c : C1 | | A.cs:145:27:145:27 | c : C2 | semmle.label | c : C2 | +| A.cs:145:27:145:27 | c : C2 | semmle.label | c : C2 | +| A.cs:145:32:145:35 | [post] this access [field c] : C | semmle.label | [post] this access [field c] : C | | A.cs:145:32:145:35 | [post] this access [field c] : C | semmle.label | [post] this access [field c] : C | | A.cs:145:32:145:35 | [post] this access [field c] : C1 | semmle.label | [post] this access [field c] : C1 | +| A.cs:145:32:145:35 | [post] this access [field c] : C1 | semmle.label | [post] this access [field c] : C1 | +| A.cs:145:32:145:35 | [post] this access [field c] : C2 | semmle.label | [post] this access [field c] : C2 | | A.cs:145:32:145:35 | [post] this access [field c] : C2 | semmle.label | [post] this access [field c] : C2 | | A.cs:145:41:145:41 | access to parameter c : C | semmle.label | access to parameter c : C | +| A.cs:145:41:145:41 | access to parameter c : C | semmle.label | access to parameter c : C | +| A.cs:145:41:145:41 | access to parameter c : C1 | semmle.label | access to parameter c : C1 | | A.cs:145:41:145:41 | access to parameter c : C1 | semmle.label | access to parameter c : C1 | | A.cs:145:41:145:41 | access to parameter c : C2 | semmle.label | access to parameter c : C2 | +| A.cs:145:41:145:41 | access to parameter c : C2 | semmle.label | access to parameter c : C2 | +| A.cs:146:18:146:20 | this [field c] : C | semmle.label | this [field c] : C | | A.cs:146:18:146:20 | this [field c] : C | semmle.label | this [field c] : C | | A.cs:146:18:146:20 | this [field c] : C1 | semmle.label | this [field c] : C1 | +| A.cs:146:18:146:20 | this [field c] : C1 | semmle.label | this [field c] : C1 | +| A.cs:146:33:146:36 | this access [field c] : C | semmle.label | this access [field c] : C | | A.cs:146:33:146:36 | this access [field c] : C | semmle.label | this access [field c] : C | | A.cs:146:33:146:36 | this access [field c] : C1 | semmle.label | this access [field c] : C1 | +| A.cs:146:33:146:36 | this access [field c] : C1 | semmle.label | this access [field c] : C1 | +| A.cs:146:33:146:38 | access to field c : C | semmle.label | access to field c : C | | A.cs:146:33:146:38 | access to field c : C | semmle.label | access to field c : C | | A.cs:146:33:146:38 | access to field c : C1 | semmle.label | access to field c : C1 | +| A.cs:146:33:146:38 | access to field c : C1 | semmle.label | access to field c : C1 | +| A.cs:147:32:147:32 | c : C | semmle.label | c : C | | A.cs:147:32:147:32 | c : C | semmle.label | c : C | | A.cs:149:20:149:27 | object creation of type B [field c] : C | semmle.label | object creation of type B [field c] : C | +| A.cs:149:20:149:27 | object creation of type B [field c] : C | semmle.label | object creation of type B [field c] : C | +| A.cs:149:26:149:26 | access to parameter c : C | semmle.label | access to parameter c : C | | A.cs:149:26:149:26 | access to parameter c : C | semmle.label | access to parameter c : C | | A.cs:157:25:157:28 | head : B | semmle.label | head : B | +| A.cs:157:25:157:28 | head : B | semmle.label | head : B | +| A.cs:157:38:157:41 | next [field head] : B | semmle.label | next [field head] : B | | A.cs:157:38:157:41 | next [field head] : B | semmle.label | next [field head] : B | | A.cs:157:38:157:41 | next [field next, field head] : B | semmle.label | next [field next, field head] : B | +| A.cs:157:38:157:41 | next [field next, field head] : B | semmle.label | next [field next, field head] : B | +| A.cs:159:13:159:16 | [post] this access [field head] : B | semmle.label | [post] this access [field head] : B | | A.cs:159:13:159:16 | [post] this access [field head] : B | semmle.label | [post] this access [field head] : B | | A.cs:159:25:159:28 | access to parameter head : B | semmle.label | access to parameter head : B | +| A.cs:159:25:159:28 | access to parameter head : B | semmle.label | access to parameter head : B | +| A.cs:160:13:160:16 | [post] this access [field next, field head] : B | semmle.label | [post] this access [field next, field head] : B | | A.cs:160:13:160:16 | [post] this access [field next, field head] : B | semmle.label | [post] this access [field next, field head] : B | | A.cs:160:13:160:16 | [post] this access [field next, field next, field head] : B | semmle.label | [post] this access [field next, field next, field head] : B | +| A.cs:160:13:160:16 | [post] this access [field next, field next, field head] : B | semmle.label | [post] this access [field next, field next, field head] : B | +| A.cs:160:25:160:28 | access to parameter next [field head] : B | semmle.label | access to parameter next [field head] : B | | A.cs:160:25:160:28 | access to parameter next [field head] : B | semmle.label | access to parameter next [field head] : B | | A.cs:160:25:160:28 | access to parameter next [field next, field head] : B | semmle.label | access to parameter next [field next, field head] : B | -| B.cs:5:17:5:26 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| A.cs:160:25:160:28 | access to parameter next [field next, field head] : B | semmle.label | access to parameter next [field next, field head] : B | +| B.cs:5:17:5:31 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| B.cs:5:17:5:31 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| B.cs:6:18:6:34 | object creation of type Box1 [field elem1] : Elem | semmle.label | object creation of type Box1 [field elem1] : Elem | | B.cs:6:18:6:34 | object creation of type Box1 [field elem1] : Elem | semmle.label | object creation of type Box1 [field elem1] : Elem | | B.cs:6:27:6:27 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | +| B.cs:6:27:6:27 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | +| B.cs:7:18:7:29 | object creation of type Box2 [field box1, field elem1] : Elem | semmle.label | object creation of type Box2 [field box1, field elem1] : Elem | | B.cs:7:18:7:29 | object creation of type Box2 [field box1, field elem1] : Elem | semmle.label | object creation of type Box2 [field box1, field elem1] : Elem | | B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | semmle.label | access to local variable b1 [field elem1] : Elem | +| B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | semmle.label | access to local variable b1 [field elem1] : Elem | +| B.cs:8:14:8:15 | access to local variable b2 [field box1, field elem1] : Elem | semmle.label | access to local variable b2 [field box1, field elem1] : Elem | | B.cs:8:14:8:15 | access to local variable b2 [field box1, field elem1] : Elem | semmle.label | access to local variable b2 [field box1, field elem1] : Elem | | B.cs:8:14:8:20 | access to field box1 [field elem1] : Elem | semmle.label | access to field box1 [field elem1] : Elem | +| B.cs:8:14:8:20 | access to field box1 [field elem1] : Elem | semmle.label | access to field box1 [field elem1] : Elem | | B.cs:8:14:8:26 | access to field elem1 | semmle.label | access to field elem1 | -| B.cs:14:17:14:26 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| B.cs:8:14:8:26 | access to field elem1 | semmle.label | access to field elem1 | +| B.cs:14:17:14:31 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| B.cs:14:17:14:31 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| B.cs:15:18:15:34 | object creation of type Box1 [field elem2] : Elem | semmle.label | object creation of type Box1 [field elem2] : Elem | | B.cs:15:18:15:34 | object creation of type Box1 [field elem2] : Elem | semmle.label | object creation of type Box1 [field elem2] : Elem | | B.cs:15:33:15:33 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | +| B.cs:15:33:15:33 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | +| B.cs:16:18:16:29 | object creation of type Box2 [field box1, field elem2] : Elem | semmle.label | object creation of type Box2 [field box1, field elem2] : Elem | | B.cs:16:18:16:29 | object creation of type Box2 [field box1, field elem2] : Elem | semmle.label | object creation of type Box2 [field box1, field elem2] : Elem | | B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | semmle.label | access to local variable b1 [field elem2] : Elem | +| B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | semmle.label | access to local variable b1 [field elem2] : Elem | +| B.cs:18:14:18:15 | access to local variable b2 [field box1, field elem2] : Elem | semmle.label | access to local variable b2 [field box1, field elem2] : Elem | | B.cs:18:14:18:15 | access to local variable b2 [field box1, field elem2] : Elem | semmle.label | access to local variable b2 [field box1, field elem2] : Elem | | B.cs:18:14:18:20 | access to field box1 [field elem2] : Elem | semmle.label | access to field box1 [field elem2] : Elem | +| B.cs:18:14:18:20 | access to field box1 [field elem2] : Elem | semmle.label | access to field box1 [field elem2] : Elem | +| B.cs:18:14:18:26 | access to field elem2 | semmle.label | access to field elem2 | | B.cs:18:14:18:26 | access to field elem2 | semmle.label | access to field elem2 | | B.cs:29:26:29:27 | e1 : Elem | semmle.label | e1 : Elem | +| B.cs:29:26:29:27 | e1 : Elem | semmle.label | e1 : Elem | +| B.cs:29:35:29:36 | e2 : Elem | semmle.label | e2 : Elem | | B.cs:29:35:29:36 | e2 : Elem | semmle.label | e2 : Elem | | B.cs:31:13:31:16 | [post] this access [field elem1] : Elem | semmle.label | [post] this access [field elem1] : Elem | +| B.cs:31:13:31:16 | [post] this access [field elem1] : Elem | semmle.label | [post] this access [field elem1] : Elem | +| B.cs:31:26:31:27 | access to parameter e1 : Elem | semmle.label | access to parameter e1 : Elem | | B.cs:31:26:31:27 | access to parameter e1 : Elem | semmle.label | access to parameter e1 : Elem | | B.cs:32:13:32:16 | [post] this access [field elem2] : Elem | semmle.label | [post] this access [field elem2] : Elem | +| B.cs:32:13:32:16 | [post] this access [field elem2] : Elem | semmle.label | [post] this access [field elem2] : Elem | +| B.cs:32:26:32:27 | access to parameter e2 : Elem | semmle.label | access to parameter e2 : Elem | | B.cs:32:26:32:27 | access to parameter e2 : Elem | semmle.label | access to parameter e2 : Elem | | B.cs:39:26:39:27 | b1 [field elem1] : Elem | semmle.label | b1 [field elem1] : Elem | +| B.cs:39:26:39:27 | b1 [field elem1] : Elem | semmle.label | b1 [field elem1] : Elem | +| B.cs:39:26:39:27 | b1 [field elem2] : Elem | semmle.label | b1 [field elem2] : Elem | | B.cs:39:26:39:27 | b1 [field elem2] : Elem | semmle.label | b1 [field elem2] : Elem | | B.cs:41:13:41:16 | [post] this access [field box1, field elem1] : Elem | semmle.label | [post] this access [field box1, field elem1] : Elem | +| B.cs:41:13:41:16 | [post] this access [field box1, field elem1] : Elem | semmle.label | [post] this access [field box1, field elem1] : Elem | +| B.cs:41:13:41:16 | [post] this access [field box1, field elem2] : Elem | semmle.label | [post] this access [field box1, field elem2] : Elem | | B.cs:41:13:41:16 | [post] this access [field box1, field elem2] : Elem | semmle.label | [post] this access [field box1, field elem2] : Elem | | B.cs:41:25:41:26 | access to parameter b1 [field elem1] : Elem | semmle.label | access to parameter b1 [field elem1] : Elem | +| B.cs:41:25:41:26 | access to parameter b1 [field elem1] : Elem | semmle.label | access to parameter b1 [field elem1] : Elem | +| B.cs:41:25:41:26 | access to parameter b1 [field elem2] : Elem | semmle.label | access to parameter b1 [field elem2] : Elem | | B.cs:41:25:41:26 | access to parameter b1 [field elem2] : Elem | semmle.label | access to parameter b1 [field elem2] : Elem | | C.cs:3:18:3:19 | [post] this access [field s1] : Elem | semmle.label | [post] this access [field s1] : Elem | -| C.cs:3:23:3:32 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| C.cs:3:18:3:19 | [post] this access [field s1] : Elem | semmle.label | [post] this access [field s1] : Elem | +| C.cs:3:23:3:37 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:3:23:3:37 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | | C.cs:4:27:4:28 | [post] this access [field s2] : Elem | semmle.label | [post] this access [field s2] : Elem | -| C.cs:4:32:4:41 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | -| C.cs:6:30:6:39 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| C.cs:4:27:4:28 | [post] this access [field s2] : Elem | semmle.label | [post] this access [field s2] : Elem | +| C.cs:4:32:4:46 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:4:32:4:46 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:6:30:6:44 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:6:30:6:44 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | | C.cs:7:18:7:19 | [post] this access [property s5] : Elem | semmle.label | [post] this access [property s5] : Elem | -| C.cs:7:37:7:46 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | -| C.cs:8:30:8:39 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| C.cs:7:18:7:19 | [post] this access [property s5] : Elem | semmle.label | [post] this access [property s5] : Elem | +| C.cs:7:37:7:51 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:7:37:7:51 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:8:30:8:44 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:8:30:8:44 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:12:15:12:21 | object creation of type C [field s1] : Elem | semmle.label | object creation of type C [field s1] : Elem | | C.cs:12:15:12:21 | object creation of type C [field s1] : Elem | semmle.label | object creation of type C [field s1] : Elem | | C.cs:12:15:12:21 | object creation of type C [field s2] : Elem | semmle.label | object creation of type C [field s2] : Elem | +| C.cs:12:15:12:21 | object creation of type C [field s2] : Elem | semmle.label | object creation of type C [field s2] : Elem | +| C.cs:12:15:12:21 | object creation of type C [field s3] : Elem | semmle.label | object creation of type C [field s3] : Elem | | C.cs:12:15:12:21 | object creation of type C [field s3] : Elem | semmle.label | object creation of type C [field s3] : Elem | | C.cs:12:15:12:21 | object creation of type C [property s5] : Elem | semmle.label | object creation of type C [property s5] : Elem | +| C.cs:12:15:12:21 | object creation of type C [property s5] : Elem | semmle.label | object creation of type C [property s5] : Elem | +| C.cs:13:9:13:9 | access to local variable c [field s1] : Elem | semmle.label | access to local variable c [field s1] : Elem | | C.cs:13:9:13:9 | access to local variable c [field s1] : Elem | semmle.label | access to local variable c [field s1] : Elem | | C.cs:13:9:13:9 | access to local variable c [field s2] : Elem | semmle.label | access to local variable c [field s2] : Elem | +| C.cs:13:9:13:9 | access to local variable c [field s2] : Elem | semmle.label | access to local variable c [field s2] : Elem | +| C.cs:13:9:13:9 | access to local variable c [field s3] : Elem | semmle.label | access to local variable c [field s3] : Elem | | C.cs:13:9:13:9 | access to local variable c [field s3] : Elem | semmle.label | access to local variable c [field s3] : Elem | | C.cs:13:9:13:9 | access to local variable c [property s5] : Elem | semmle.label | access to local variable c [property s5] : Elem | +| C.cs:13:9:13:9 | access to local variable c [property s5] : Elem | semmle.label | access to local variable c [property s5] : Elem | | C.cs:18:9:18:12 | [post] this access [field s3] : Elem | semmle.label | [post] this access [field s3] : Elem | -| C.cs:18:19:18:28 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| C.cs:18:9:18:12 | [post] this access [field s3] : Elem | semmle.label | [post] this access [field s3] : Elem | +| C.cs:18:19:18:33 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:18:19:18:33 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| C.cs:21:17:21:18 | this [field s1] : Elem | semmle.label | this [field s1] : Elem | | C.cs:21:17:21:18 | this [field s1] : Elem | semmle.label | this [field s1] : Elem | | C.cs:21:17:21:18 | this [field s2] : Elem | semmle.label | this [field s2] : Elem | +| C.cs:21:17:21:18 | this [field s2] : Elem | semmle.label | this [field s2] : Elem | +| C.cs:21:17:21:18 | this [field s3] : Elem | semmle.label | this [field s3] : Elem | | C.cs:21:17:21:18 | this [field s3] : Elem | semmle.label | this [field s3] : Elem | | C.cs:21:17:21:18 | this [property s5] : Elem | semmle.label | this [property s5] : Elem | +| C.cs:21:17:21:18 | this [property s5] : Elem | semmle.label | this [property s5] : Elem | +| C.cs:23:14:23:15 | access to field s1 | semmle.label | access to field s1 | | C.cs:23:14:23:15 | access to field s1 | semmle.label | access to field s1 | | C.cs:23:14:23:15 | this access [field s1] : Elem | semmle.label | this access [field s1] : Elem | +| C.cs:23:14:23:15 | this access [field s1] : Elem | semmle.label | this access [field s1] : Elem | +| C.cs:24:14:24:15 | access to field s2 | semmle.label | access to field s2 | | C.cs:24:14:24:15 | access to field s2 | semmle.label | access to field s2 | | C.cs:24:14:24:15 | this access [field s2] : Elem | semmle.label | this access [field s2] : Elem | +| C.cs:24:14:24:15 | this access [field s2] : Elem | semmle.label | this access [field s2] : Elem | +| C.cs:25:14:25:15 | access to field s3 | semmle.label | access to field s3 | | C.cs:25:14:25:15 | access to field s3 | semmle.label | access to field s3 | | C.cs:25:14:25:15 | this access [field s3] : Elem | semmle.label | this access [field s3] : Elem | +| C.cs:25:14:25:15 | this access [field s3] : Elem | semmle.label | this access [field s3] : Elem | +| C.cs:26:14:26:15 | access to field s4 | semmle.label | access to field s4 | | C.cs:26:14:26:15 | access to field s4 | semmle.label | access to field s4 | | C.cs:27:14:27:15 | access to property s5 | semmle.label | access to property s5 | +| C.cs:27:14:27:15 | access to property s5 | semmle.label | access to property s5 | +| C.cs:27:14:27:15 | this access [property s5] : Elem | semmle.label | this access [property s5] : Elem | | C.cs:27:14:27:15 | this access [property s5] : Elem | semmle.label | this access [property s5] : Elem | | C.cs:28:14:28:15 | access to property s6 | semmle.label | access to property s6 | +| C.cs:28:14:28:15 | access to property s6 | semmle.label | access to property s6 | +| D.cs:8:9:8:11 | this [field trivialPropField] : Object | semmle.label | this [field trivialPropField] : Object | | D.cs:8:9:8:11 | this [field trivialPropField] : Object | semmle.label | this [field trivialPropField] : Object | | D.cs:8:22:8:25 | this access [field trivialPropField] : Object | semmle.label | this access [field trivialPropField] : Object | +| D.cs:8:22:8:25 | this access [field trivialPropField] : Object | semmle.label | this access [field trivialPropField] : Object | +| D.cs:8:22:8:42 | access to field trivialPropField : Object | semmle.label | access to field trivialPropField : Object | | D.cs:8:22:8:42 | access to field trivialPropField : Object | semmle.label | access to field trivialPropField : Object | | D.cs:9:9:9:11 | value : Object | semmle.label | value : Object | +| D.cs:9:9:9:11 | value : Object | semmle.label | value : Object | +| D.cs:9:15:9:18 | [post] this access [field trivialPropField] : Object | semmle.label | [post] this access [field trivialPropField] : Object | | D.cs:9:15:9:18 | [post] this access [field trivialPropField] : Object | semmle.label | [post] this access [field trivialPropField] : Object | | D.cs:9:39:9:43 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:9:39:9:43 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:14:9:14:11 | this [field trivialPropField] : Object | semmle.label | this [field trivialPropField] : Object | | D.cs:14:9:14:11 | this [field trivialPropField] : Object | semmle.label | this [field trivialPropField] : Object | | D.cs:14:22:14:25 | this access [field trivialPropField] : Object | semmle.label | this access [field trivialPropField] : Object | +| D.cs:14:22:14:25 | this access [field trivialPropField] : Object | semmle.label | this access [field trivialPropField] : Object | +| D.cs:14:22:14:42 | access to field trivialPropField : Object | semmle.label | access to field trivialPropField : Object | | D.cs:14:22:14:42 | access to field trivialPropField : Object | semmle.label | access to field trivialPropField : Object | | D.cs:15:9:15:11 | value : Object | semmle.label | value : Object | +| D.cs:15:9:15:11 | value : Object | semmle.label | value : Object | +| D.cs:15:15:15:18 | [post] this access [field trivialPropField] : Object | semmle.label | [post] this access [field trivialPropField] : Object | | D.cs:15:15:15:18 | [post] this access [field trivialPropField] : Object | semmle.label | [post] this access [field trivialPropField] : Object | | D.cs:15:34:15:38 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:15:34:15:38 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:18:28:18:29 | o1 : Object | semmle.label | o1 : Object | | D.cs:18:28:18:29 | o1 : Object | semmle.label | o1 : Object | | D.cs:18:39:18:40 | o2 : Object | semmle.label | o2 : Object | +| D.cs:18:39:18:40 | o2 : Object | semmle.label | o2 : Object | +| D.cs:18:50:18:51 | o3 : Object | semmle.label | o3 : Object | | D.cs:18:50:18:51 | o3 : Object | semmle.label | o3 : Object | | D.cs:21:9:21:11 | [post] access to local variable ret [property AutoProp] : Object | semmle.label | [post] access to local variable ret [property AutoProp] : Object | +| D.cs:21:9:21:11 | [post] access to local variable ret [property AutoProp] : Object | semmle.label | [post] access to local variable ret [property AutoProp] : Object | +| D.cs:21:24:21:25 | access to parameter o1 : Object | semmle.label | access to parameter o1 : Object | | D.cs:21:24:21:25 | access to parameter o1 : Object | semmle.label | access to parameter o1 : Object | | D.cs:22:9:22:11 | [post] access to local variable ret [field trivialPropField] : Object | semmle.label | [post] access to local variable ret [field trivialPropField] : Object | +| D.cs:22:9:22:11 | [post] access to local variable ret [field trivialPropField] : Object | semmle.label | [post] access to local variable ret [field trivialPropField] : Object | +| D.cs:22:27:22:28 | access to parameter o2 : Object | semmle.label | access to parameter o2 : Object | | D.cs:22:27:22:28 | access to parameter o2 : Object | semmle.label | access to parameter o2 : Object | | D.cs:23:9:23:11 | [post] access to local variable ret [field trivialPropField] : Object | semmle.label | [post] access to local variable ret [field trivialPropField] : Object | +| D.cs:23:9:23:11 | [post] access to local variable ret [field trivialPropField] : Object | semmle.label | [post] access to local variable ret [field trivialPropField] : Object | +| D.cs:23:27:23:28 | access to parameter o3 : Object | semmle.label | access to parameter o3 : Object | | D.cs:23:27:23:28 | access to parameter o3 : Object | semmle.label | access to parameter o3 : Object | | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | semmle.label | access to local variable ret [field trivialPropField] : Object | | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | semmle.label | access to local variable ret [field trivialPropField] : Object | +| D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | semmle.label | access to local variable ret [field trivialPropField] : Object | +| D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | semmle.label | access to local variable ret [field trivialPropField] : Object | | D.cs:24:16:24:18 | access to local variable ret [property AutoProp] : Object | semmle.label | access to local variable ret [property AutoProp] : Object | -| D.cs:29:17:29:28 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| D.cs:24:16:24:18 | access to local variable ret [property AutoProp] : Object | semmle.label | access to local variable ret [property AutoProp] : Object | +| D.cs:29:17:29:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| D.cs:29:17:29:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| D.cs:31:17:31:37 | call to method Create [property AutoProp] : Object | semmle.label | call to method Create [property AutoProp] : Object | | D.cs:31:17:31:37 | call to method Create [property AutoProp] : Object | semmle.label | call to method Create [property AutoProp] : Object | | D.cs:31:24:31:24 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| D.cs:31:24:31:24 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| D.cs:32:14:32:14 | access to local variable d [property AutoProp] : Object | semmle.label | access to local variable d [property AutoProp] : Object | | D.cs:32:14:32:14 | access to local variable d [property AutoProp] : Object | semmle.label | access to local variable d [property AutoProp] : Object | | D.cs:32:14:32:23 | access to property AutoProp | semmle.label | access to property AutoProp | -| D.cs:37:13:37:33 | call to method Create [field trivialPropField] : Object | semmle.label | call to method Create [field trivialPropField] : Object | -| D.cs:37:26:37:26 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| D.cs:32:14:32:23 | access to property AutoProp | semmle.label | access to property AutoProp | +| D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | semmle.label | call to method Create [field trivialPropField] : Object | +| D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | semmle.label | call to method Create [field trivialPropField] : Object | +| D.cs:37:26:37:42 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| D.cs:37:26:37:42 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:39:14:39:26 | access to property TrivialProp | semmle.label | access to property TrivialProp | +| D.cs:39:14:39:26 | access to property TrivialProp | semmle.label | access to property TrivialProp | +| D.cs:40:14:40:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:40:14:40:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:40:14:40:31 | access to field trivialPropField | semmle.label | access to field trivialPropField | +| D.cs:40:14:40:31 | access to field trivialPropField | semmle.label | access to field trivialPropField | +| D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:41:14:41:26 | access to property ComplexProp | semmle.label | access to property ComplexProp | -| D.cs:43:13:43:33 | call to method Create [field trivialPropField] : Object | semmle.label | call to method Create [field trivialPropField] : Object | -| D.cs:43:32:43:32 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| D.cs:41:14:41:26 | access to property ComplexProp | semmle.label | access to property ComplexProp | +| D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | semmle.label | call to method Create [field trivialPropField] : Object | +| D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | semmle.label | call to method Create [field trivialPropField] : Object | +| D.cs:43:32:43:48 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| D.cs:43:32:43:48 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:45:14:45:26 | access to property TrivialProp | semmle.label | access to property TrivialProp | +| D.cs:45:14:45:26 | access to property TrivialProp | semmle.label | access to property TrivialProp | +| D.cs:46:14:46:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:46:14:46:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:46:14:46:31 | access to field trivialPropField | semmle.label | access to field trivialPropField | +| D.cs:46:14:46:31 | access to field trivialPropField | semmle.label | access to field trivialPropField | +| D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | semmle.label | access to local variable d [field trivialPropField] : Object | | D.cs:47:14:47:26 | access to property ComplexProp | semmle.label | access to property ComplexProp | +| D.cs:47:14:47:26 | access to property ComplexProp | semmle.label | access to property ComplexProp | +| E.cs:8:29:8:29 | o : Object | semmle.label | o : Object | | E.cs:8:29:8:29 | o : Object | semmle.label | o : Object | | E.cs:11:9:11:11 | [post] access to local variable ret [field Field] : Object | semmle.label | [post] access to local variable ret [field Field] : Object | +| E.cs:11:9:11:11 | [post] access to local variable ret [field Field] : Object | semmle.label | [post] access to local variable ret [field Field] : Object | +| E.cs:11:21:11:21 | access to parameter o : Object | semmle.label | access to parameter o : Object | | E.cs:11:21:11:21 | access to parameter o : Object | semmle.label | access to parameter o : Object | | E.cs:12:16:12:18 | access to local variable ret [field Field] : Object | semmle.label | access to local variable ret [field Field] : Object | -| E.cs:22:17:22:28 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| E.cs:12:16:12:18 | access to local variable ret [field Field] : Object | semmle.label | access to local variable ret [field Field] : Object | +| E.cs:22:17:22:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| E.cs:22:17:22:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| E.cs:23:17:23:26 | call to method CreateS [field Field] : Object | semmle.label | call to method CreateS [field Field] : Object | | E.cs:23:17:23:26 | call to method CreateS [field Field] : Object | semmle.label | call to method CreateS [field Field] : Object | | E.cs:23:25:23:25 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| E.cs:23:25:23:25 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| E.cs:24:14:24:14 | access to local variable s [field Field] : Object | semmle.label | access to local variable s [field Field] : Object | | E.cs:24:14:24:14 | access to local variable s [field Field] : Object | semmle.label | access to local variable s [field Field] : Object | | E.cs:24:14:24:20 | access to field Field | semmle.label | access to field Field | +| E.cs:24:14:24:20 | access to field Field | semmle.label | access to field Field | +| F.cs:6:28:6:29 | o1 : Object | semmle.label | o1 : Object | | F.cs:6:28:6:29 | o1 : Object | semmle.label | o1 : Object | | F.cs:6:39:6:40 | o2 : Object | semmle.label | o2 : Object | +| F.cs:6:39:6:40 | o2 : Object | semmle.label | o2 : Object | +| F.cs:6:46:6:81 | object creation of type F [field Field1] : Object | semmle.label | object creation of type F [field Field1] : Object | | F.cs:6:46:6:81 | object creation of type F [field Field1] : Object | semmle.label | object creation of type F [field Field1] : Object | | F.cs:6:46:6:81 | object creation of type F [field Field2] : Object | semmle.label | object creation of type F [field Field2] : Object | +| F.cs:6:46:6:81 | object creation of type F [field Field2] : Object | semmle.label | object creation of type F [field Field2] : Object | +| F.cs:6:54:6:81 | { ..., ... } [field Field1] : Object | semmle.label | { ..., ... } [field Field1] : Object | | F.cs:6:54:6:81 | { ..., ... } [field Field1] : Object | semmle.label | { ..., ... } [field Field1] : Object | | F.cs:6:54:6:81 | { ..., ... } [field Field2] : Object | semmle.label | { ..., ... } [field Field2] : Object | +| F.cs:6:54:6:81 | { ..., ... } [field Field2] : Object | semmle.label | { ..., ... } [field Field2] : Object | +| F.cs:6:65:6:66 | access to parameter o1 : Object | semmle.label | access to parameter o1 : Object | | F.cs:6:65:6:66 | access to parameter o1 : Object | semmle.label | access to parameter o1 : Object | | F.cs:6:78:6:79 | access to parameter o2 : Object | semmle.label | access to parameter o2 : Object | -| F.cs:10:17:10:28 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| F.cs:6:78:6:79 | access to parameter o2 : Object | semmle.label | access to parameter o2 : Object | +| F.cs:10:17:10:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| F.cs:10:17:10:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| F.cs:11:17:11:31 | call to method Create [field Field1] : Object | semmle.label | call to method Create [field Field1] : Object | | F.cs:11:17:11:31 | call to method Create [field Field1] : Object | semmle.label | call to method Create [field Field1] : Object | | F.cs:11:24:11:24 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:11:24:11:24 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:12:14:12:14 | access to local variable f [field Field1] : Object | semmle.label | access to local variable f [field Field1] : Object | | F.cs:12:14:12:14 | access to local variable f [field Field1] : Object | semmle.label | access to local variable f [field Field1] : Object | | F.cs:12:14:12:21 | access to field Field1 | semmle.label | access to field Field1 | -| F.cs:15:13:15:27 | call to method Create [field Field2] : Object | semmle.label | call to method Create [field Field2] : Object | -| F.cs:15:26:15:26 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:12:14:12:21 | access to field Field1 | semmle.label | access to field Field1 | +| F.cs:15:13:15:43 | call to method Create [field Field2] : Object | semmle.label | call to method Create [field Field2] : Object | +| F.cs:15:13:15:43 | call to method Create [field Field2] : Object | semmle.label | call to method Create [field Field2] : Object | +| F.cs:15:26:15:42 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| F.cs:15:26:15:42 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| F.cs:17:14:17:14 | access to local variable f [field Field2] : Object | semmle.label | access to local variable f [field Field2] : Object | | F.cs:17:14:17:14 | access to local variable f [field Field2] : Object | semmle.label | access to local variable f [field Field2] : Object | | F.cs:17:14:17:21 | access to field Field2 | semmle.label | access to field Field2 | -| F.cs:19:21:19:34 | { ..., ... } [field Field1] : Object | semmle.label | { ..., ... } [field Field1] : Object | -| F.cs:19:32:19:32 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:17:14:17:21 | access to field Field2 | semmle.label | access to field Field2 | +| F.cs:19:21:19:50 | { ..., ... } [field Field1] : Object | semmle.label | { ..., ... } [field Field1] : Object | +| F.cs:19:21:19:50 | { ..., ... } [field Field1] : Object | semmle.label | { ..., ... } [field Field1] : Object | +| F.cs:19:32:19:48 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| F.cs:19:32:19:48 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| F.cs:20:14:20:14 | access to local variable f [field Field1] : Object | semmle.label | access to local variable f [field Field1] : Object | | F.cs:20:14:20:14 | access to local variable f [field Field1] : Object | semmle.label | access to local variable f [field Field1] : Object | | F.cs:20:14:20:21 | access to field Field1 | semmle.label | access to field Field1 | -| F.cs:23:21:23:34 | { ..., ... } [field Field2] : Object | semmle.label | { ..., ... } [field Field2] : Object | -| F.cs:23:32:23:32 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:20:14:20:21 | access to field Field1 | semmle.label | access to field Field1 | +| F.cs:23:21:23:50 | { ..., ... } [field Field2] : Object | semmle.label | { ..., ... } [field Field2] : Object | +| F.cs:23:21:23:50 | { ..., ... } [field Field2] : Object | semmle.label | { ..., ... } [field Field2] : Object | +| F.cs:23:32:23:48 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| F.cs:23:32:23:48 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | semmle.label | access to local variable f [field Field2] : Object | | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | semmle.label | access to local variable f [field Field2] : Object | | F.cs:25:14:25:21 | access to field Field2 | semmle.label | access to field Field2 | -| G.cs:7:18:7:27 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| F.cs:25:14:25:21 | access to field Field2 | semmle.label | access to field Field2 | +| G.cs:7:18:7:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:7:18:7:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | | G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | | G.cs:9:9:9:14 | [post] access to field Box1 [field Elem] : Elem | semmle.label | [post] access to field Box1 [field Elem] : Elem | +| G.cs:9:9:9:14 | [post] access to field Box1 [field Elem] : Elem | semmle.label | [post] access to field Box1 [field Elem] : Elem | +| G.cs:9:23:9:23 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | | G.cs:9:23:9:23 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | | G.cs:10:18:10:18 | access to local variable b [field Box1, field Elem] : Elem | semmle.label | access to local variable b [field Box1, field Elem] : Elem | -| G.cs:15:18:15:27 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| G.cs:10:18:10:18 | access to local variable b [field Box1, field Elem] : Elem | semmle.label | access to local variable b [field Box1, field Elem] : Elem | +| G.cs:15:18:15:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:15:18:15:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:17:9:17:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | | G.cs:17:9:17:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | | G.cs:17:9:17:14 | [post] access to field Box1 [field Elem] : Elem | semmle.label | [post] access to field Box1 [field Elem] : Elem | +| G.cs:17:9:17:14 | [post] access to field Box1 [field Elem] : Elem | semmle.label | [post] access to field Box1 [field Elem] : Elem | +| G.cs:17:24:17:24 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | | G.cs:17:24:17:24 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | | G.cs:18:18:18:18 | access to local variable b [field Box1, field Elem] : Elem | semmle.label | access to local variable b [field Box1, field Elem] : Elem | -| G.cs:23:18:23:27 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| G.cs:18:18:18:18 | access to local variable b [field Box1, field Elem] : Elem | semmle.label | access to local variable b [field Box1, field Elem] : Elem | +| G.cs:23:18:23:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:23:18:23:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:25:9:25:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | | G.cs:25:9:25:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | | G.cs:25:9:25:19 | [post] call to method GetBox1 [field Elem] : Elem | semmle.label | [post] call to method GetBox1 [field Elem] : Elem | +| G.cs:25:9:25:19 | [post] call to method GetBox1 [field Elem] : Elem | semmle.label | [post] call to method GetBox1 [field Elem] : Elem | +| G.cs:25:28:25:28 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | | G.cs:25:28:25:28 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | | G.cs:26:18:26:18 | access to local variable b [field Box1, field Elem] : Elem | semmle.label | access to local variable b [field Box1, field Elem] : Elem | -| G.cs:31:18:31:27 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| G.cs:26:18:26:18 | access to local variable b [field Box1, field Elem] : Elem | semmle.label | access to local variable b [field Box1, field Elem] : Elem | +| G.cs:31:18:31:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:31:18:31:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:33:9:33:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | | G.cs:33:9:33:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | | G.cs:33:9:33:19 | [post] call to method GetBox1 [field Elem] : Elem | semmle.label | [post] call to method GetBox1 [field Elem] : Elem | +| G.cs:33:9:33:19 | [post] call to method GetBox1 [field Elem] : Elem | semmle.label | [post] call to method GetBox1 [field Elem] : Elem | +| G.cs:33:29:33:29 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | | G.cs:33:29:33:29 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | | G.cs:34:18:34:18 | access to local variable b [field Box1, field Elem] : Elem | semmle.label | access to local variable b [field Box1, field Elem] : Elem | +| G.cs:34:18:34:18 | access to local variable b [field Box1, field Elem] : Elem | semmle.label | access to local variable b [field Box1, field Elem] : Elem | +| G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | semmle.label | b2 [field Box1, field Elem] : Elem | | G.cs:37:38:37:39 | b2 [field Box1, field Elem] : Elem | semmle.label | b2 [field Box1, field Elem] : Elem | | G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | semmle.label | access to parameter b2 [field Box1, field Elem] : Elem | +| G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | semmle.label | access to parameter b2 [field Box1, field Elem] : Elem | +| G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | semmle.label | call to method GetBox1 [field Elem] : Elem | | G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | semmle.label | call to method GetBox1 [field Elem] : Elem | | G.cs:39:14:39:35 | call to method GetElem | semmle.label | call to method GetElem | -| G.cs:44:18:44:27 | object creation of type Elem : Elem | semmle.label | object creation of type Elem : Elem | +| G.cs:39:14:39:35 | call to method GetElem | semmle.label | call to method GetElem | +| G.cs:44:18:44:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:44:18:44:32 | call to method Source<Elem> : Elem | semmle.label | call to method Source<Elem> : Elem | +| G.cs:46:9:46:16 | [post] access to field boxfield [field Box1, field Elem] : Elem | semmle.label | [post] access to field boxfield [field Box1, field Elem] : Elem | | G.cs:46:9:46:16 | [post] access to field boxfield [field Box1, field Elem] : Elem | semmle.label | [post] access to field boxfield [field Box1, field Elem] : Elem | | G.cs:46:9:46:16 | [post] this access [field boxfield, field Box1, field Elem] : Elem | semmle.label | [post] this access [field boxfield, field Box1, field Elem] : Elem | +| G.cs:46:9:46:16 | [post] this access [field boxfield, field Box1, field Elem] : Elem | semmle.label | [post] this access [field boxfield, field Box1, field Elem] : Elem | +| G.cs:46:9:46:21 | [post] access to field Box1 [field Elem] : Elem | semmle.label | [post] access to field Box1 [field Elem] : Elem | | G.cs:46:9:46:21 | [post] access to field Box1 [field Elem] : Elem | semmle.label | [post] access to field Box1 [field Elem] : Elem | | G.cs:46:30:46:30 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | +| G.cs:46:30:46:30 | access to local variable e : Elem | semmle.label | access to local variable e : Elem | +| G.cs:47:9:47:13 | this access [field boxfield, field Box1, field Elem] : Elem | semmle.label | this access [field boxfield, field Box1, field Elem] : Elem | | G.cs:47:9:47:13 | this access [field boxfield, field Box1, field Elem] : Elem | semmle.label | this access [field boxfield, field Box1, field Elem] : Elem | | G.cs:50:18:50:20 | this [field boxfield, field Box1, field Elem] : Elem | semmle.label | this [field boxfield, field Box1, field Elem] : Elem | +| G.cs:50:18:50:20 | this [field boxfield, field Box1, field Elem] : Elem | semmle.label | this [field boxfield, field Box1, field Elem] : Elem | +| G.cs:52:14:52:21 | access to field boxfield [field Box1, field Elem] : Elem | semmle.label | access to field boxfield [field Box1, field Elem] : Elem | | G.cs:52:14:52:21 | access to field boxfield [field Box1, field Elem] : Elem | semmle.label | access to field boxfield [field Box1, field Elem] : Elem | | G.cs:52:14:52:21 | this access [field boxfield, field Box1, field Elem] : Elem | semmle.label | this access [field boxfield, field Box1, field Elem] : Elem | +| G.cs:52:14:52:21 | this access [field boxfield, field Box1, field Elem] : Elem | semmle.label | this access [field boxfield, field Box1, field Elem] : Elem | +| G.cs:52:14:52:26 | access to field Box1 [field Elem] : Elem | semmle.label | access to field Box1 [field Elem] : Elem | | G.cs:52:14:52:26 | access to field Box1 [field Elem] : Elem | semmle.label | access to field Box1 [field Elem] : Elem | | G.cs:52:14:52:31 | access to field Elem | semmle.label | access to field Elem | +| G.cs:52:14:52:31 | access to field Elem | semmle.label | access to field Elem | +| G.cs:63:21:63:27 | this [field Elem] : Elem | semmle.label | this [field Elem] : Elem | | G.cs:63:21:63:27 | this [field Elem] : Elem | semmle.label | this [field Elem] : Elem | | G.cs:63:34:63:37 | access to field Elem : Elem | semmle.label | access to field Elem : Elem | +| G.cs:63:34:63:37 | access to field Elem : Elem | semmle.label | access to field Elem : Elem | +| G.cs:63:34:63:37 | this access [field Elem] : Elem | semmle.label | this access [field Elem] : Elem | | G.cs:63:34:63:37 | this access [field Elem] : Elem | semmle.label | this access [field Elem] : Elem | | G.cs:64:34:64:34 | e : Elem | semmle.label | e : Elem | +| G.cs:64:34:64:34 | e : Elem | semmle.label | e : Elem | +| G.cs:64:39:64:42 | [post] this access [field Elem] : Elem | semmle.label | [post] this access [field Elem] : Elem | | G.cs:64:39:64:42 | [post] this access [field Elem] : Elem | semmle.label | [post] this access [field Elem] : Elem | | G.cs:64:46:64:46 | access to parameter e : Elem | semmle.label | access to parameter e : Elem | +| G.cs:64:46:64:46 | access to parameter e : Elem | semmle.label | access to parameter e : Elem | +| G.cs:71:21:71:27 | this [field Box1, field Elem] : Elem | semmle.label | this [field Box1, field Elem] : Elem | | G.cs:71:21:71:27 | this [field Box1, field Elem] : Elem | semmle.label | this [field Box1, field Elem] : Elem | | G.cs:71:34:71:37 | access to field Box1 [field Elem] : Elem | semmle.label | access to field Box1 [field Elem] : Elem | +| G.cs:71:34:71:37 | access to field Box1 [field Elem] : Elem | semmle.label | access to field Box1 [field Elem] : Elem | +| G.cs:71:34:71:37 | this access [field Box1, field Elem] : Elem | semmle.label | this access [field Box1, field Elem] : Elem | | G.cs:71:34:71:37 | this access [field Box1, field Elem] : Elem | semmle.label | this access [field Box1, field Elem] : Elem | | H.cs:13:15:13:15 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | +| H.cs:13:15:13:15 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | +| H.cs:16:9:16:11 | [post] access to local variable ret [field FieldA] : Object | semmle.label | [post] access to local variable ret [field FieldA] : Object | | H.cs:16:9:16:11 | [post] access to local variable ret [field FieldA] : Object | semmle.label | [post] access to local variable ret [field FieldA] : Object | | H.cs:16:22:16:22 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | +| H.cs:16:22:16:22 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | +| H.cs:16:22:16:29 | access to field FieldA : Object | semmle.label | access to field FieldA : Object | | H.cs:16:22:16:29 | access to field FieldA : Object | semmle.label | access to field FieldA : Object | | H.cs:17:16:17:18 | access to local variable ret [field FieldA] : Object | semmle.label | access to local variable ret [field FieldA] : Object | +| H.cs:17:16:17:18 | access to local variable ret [field FieldA] : Object | semmle.label | access to local variable ret [field FieldA] : Object | | H.cs:23:9:23:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | -| H.cs:23:20:23:31 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| H.cs:23:9:23:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | +| H.cs:23:20:23:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:23:20:23:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:24:21:24:28 | call to method Clone [field FieldA] : Object | semmle.label | call to method Clone [field FieldA] : Object | | H.cs:24:21:24:28 | call to method Clone [field FieldA] : Object | semmle.label | call to method Clone [field FieldA] : Object | | H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | +| H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | +| H.cs:25:14:25:18 | access to local variable clone [field FieldA] : Object | semmle.label | access to local variable clone [field FieldA] : Object | | H.cs:25:14:25:18 | access to local variable clone [field FieldA] : Object | semmle.label | access to local variable clone [field FieldA] : Object | | H.cs:25:14:25:25 | access to field FieldA | semmle.label | access to field FieldA | +| H.cs:25:14:25:25 | access to field FieldA | semmle.label | access to field FieldA | +| H.cs:33:19:33:19 | a [field FieldA] : A | semmle.label | a [field FieldA] : A | | H.cs:33:19:33:19 | a [field FieldA] : A | semmle.label | a [field FieldA] : A | | H.cs:33:19:33:19 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | +| H.cs:33:19:33:19 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | +| H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : A | semmle.label | [post] access to local variable b [field FieldB] : A | | H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : A | semmle.label | [post] access to local variable b [field FieldB] : A | | H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : Object | semmle.label | [post] access to local variable b [field FieldB] : Object | +| H.cs:36:9:36:9 | [post] access to local variable b [field FieldB] : Object | semmle.label | [post] access to local variable b [field FieldB] : Object | +| H.cs:36:20:36:20 | access to parameter a [field FieldA] : A | semmle.label | access to parameter a [field FieldA] : A | | H.cs:36:20:36:20 | access to parameter a [field FieldA] : A | semmle.label | access to parameter a [field FieldA] : A | | H.cs:36:20:36:20 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | +| H.cs:36:20:36:20 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | +| H.cs:36:20:36:27 | access to field FieldA : A | semmle.label | access to field FieldA : A | | H.cs:36:20:36:27 | access to field FieldA : A | semmle.label | access to field FieldA : A | | H.cs:36:20:36:27 | access to field FieldA : Object | semmle.label | access to field FieldA : Object | +| H.cs:36:20:36:27 | access to field FieldA : Object | semmle.label | access to field FieldA : Object | +| H.cs:37:16:37:16 | access to local variable b [field FieldB] : A | semmle.label | access to local variable b [field FieldB] : A | | H.cs:37:16:37:16 | access to local variable b [field FieldB] : A | semmle.label | access to local variable b [field FieldB] : A | | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | +| H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | | H.cs:43:9:43:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | -| H.cs:43:20:43:31 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| H.cs:43:9:43:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | +| H.cs:43:20:43:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:43:20:43:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:44:17:44:28 | call to method Transform [field FieldB] : Object | semmle.label | call to method Transform [field FieldB] : Object | | H.cs:44:17:44:28 | call to method Transform [field FieldB] : Object | semmle.label | call to method Transform [field FieldB] : Object | | H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | +| H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | +| H.cs:45:14:45:14 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | | H.cs:45:14:45:14 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | | H.cs:45:14:45:21 | access to field FieldB | semmle.label | access to field FieldB | +| H.cs:45:14:45:21 | access to field FieldB | semmle.label | access to field FieldB | +| H.cs:53:25:53:25 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | | H.cs:53:25:53:25 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | | H.cs:55:9:55:10 | [post] access to parameter b1 [field FieldB] : Object | semmle.label | [post] access to parameter b1 [field FieldB] : Object | +| H.cs:55:9:55:10 | [post] access to parameter b1 [field FieldB] : Object | semmle.label | [post] access to parameter b1 [field FieldB] : Object | +| H.cs:55:21:55:21 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | | H.cs:55:21:55:21 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | | H.cs:55:21:55:28 | access to field FieldA : Object | semmle.label | access to field FieldA : Object | +| H.cs:55:21:55:28 | access to field FieldA : Object | semmle.label | access to field FieldA : Object | | H.cs:63:9:63:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | -| H.cs:63:20:63:31 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| H.cs:63:9:63:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | +| H.cs:63:20:63:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:63:20:63:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | | H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | | H.cs:64:25:64:26 | [post] access to local variable b1 [field FieldB] : Object | semmle.label | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:64:25:64:26 | [post] access to local variable b1 [field FieldB] : Object | semmle.label | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:65:14:65:15 | access to local variable b1 [field FieldB] : Object | semmle.label | access to local variable b1 [field FieldB] : Object | | H.cs:65:14:65:15 | access to local variable b1 [field FieldB] : Object | semmle.label | access to local variable b1 [field FieldB] : Object | | H.cs:65:14:65:22 | access to field FieldB | semmle.label | access to field FieldB | +| H.cs:65:14:65:22 | access to field FieldB | semmle.label | access to field FieldB | +| H.cs:77:30:77:30 | o : Object | semmle.label | o : Object | | H.cs:77:30:77:30 | o : Object | semmle.label | o : Object | | H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | semmle.label | [post] access to parameter a [field FieldA] : Object | +| H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | semmle.label | [post] access to parameter a [field FieldA] : Object | +| H.cs:79:20:79:20 | access to parameter o : Object | semmle.label | access to parameter o : Object | | H.cs:79:20:79:20 | access to parameter o : Object | semmle.label | access to parameter o : Object | | H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | +| H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | +| H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | semmle.label | [post] access to parameter b1 [field FieldB] : Object | | H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | semmle.label | [post] access to parameter b1 [field FieldB] : Object | | H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | -| H.cs:88:20:88:31 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | -| H.cs:88:34:88:35 | [post] access to local variable b1 [field FieldB] : Object | semmle.label | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:88:39:88:40 | [post] access to local variable b1 [field FieldB] : Object | semmle.label | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:88:39:88:40 | [post] access to local variable b1 [field FieldB] : Object | semmle.label | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:89:14:89:14 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | | H.cs:89:14:89:14 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | | H.cs:89:14:89:21 | access to field FieldA | semmle.label | access to field FieldA | +| H.cs:89:14:89:21 | access to field FieldA | semmle.label | access to field FieldA | +| H.cs:90:14:90:15 | access to local variable b1 [field FieldB] : Object | semmle.label | access to local variable b1 [field FieldB] : Object | | H.cs:90:14:90:15 | access to local variable b1 [field FieldB] : Object | semmle.label | access to local variable b1 [field FieldB] : Object | | H.cs:90:14:90:22 | access to field FieldB | semmle.label | access to field FieldB | +| H.cs:90:14:90:22 | access to field FieldB | semmle.label | access to field FieldB | +| H.cs:102:23:102:23 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | | H.cs:102:23:102:23 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | | H.cs:105:9:105:12 | [post] access to local variable temp [field FieldB, field FieldA] : Object | semmle.label | [post] access to local variable temp [field FieldB, field FieldA] : Object | +| H.cs:105:9:105:12 | [post] access to local variable temp [field FieldB, field FieldA] : Object | semmle.label | [post] access to local variable temp [field FieldB, field FieldA] : Object | +| H.cs:105:23:105:23 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | | H.cs:105:23:105:23 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | | H.cs:106:16:106:40 | call to method Transform [field FieldB] : Object | semmle.label | call to method Transform [field FieldB] : Object | +| H.cs:106:16:106:40 | call to method Transform [field FieldB] : Object | semmle.label | call to method Transform [field FieldB] : Object | +| H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | semmle.label | (...) ... [field FieldA] : Object | | H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | semmle.label | (...) ... [field FieldA] : Object | | H.cs:106:29:106:32 | access to local variable temp [field FieldB, field FieldA] : Object | semmle.label | access to local variable temp [field FieldB, field FieldA] : Object | +| H.cs:106:29:106:32 | access to local variable temp [field FieldB, field FieldA] : Object | semmle.label | access to local variable temp [field FieldB, field FieldA] : Object | +| H.cs:106:29:106:39 | access to field FieldB [field FieldA] : Object | semmle.label | access to field FieldB [field FieldA] : Object | | H.cs:106:29:106:39 | access to field FieldB [field FieldA] : Object | semmle.label | access to field FieldB [field FieldA] : Object | | H.cs:112:9:112:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | -| H.cs:112:20:112:31 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| H.cs:112:9:112:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | +| H.cs:112:20:112:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:112:20:112:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:113:17:113:32 | call to method TransformWrap [field FieldB] : Object | semmle.label | call to method TransformWrap [field FieldB] : Object | | H.cs:113:17:113:32 | call to method TransformWrap [field FieldB] : Object | semmle.label | call to method TransformWrap [field FieldB] : Object | | H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | +| H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | +| H.cs:114:14:114:14 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | | H.cs:114:14:114:14 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | | H.cs:114:14:114:21 | access to field FieldB | semmle.label | access to field FieldB | +| H.cs:114:14:114:21 | access to field FieldB | semmle.label | access to field FieldB | +| H.cs:122:18:122:18 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | | H.cs:122:18:122:18 | a [field FieldA] : Object | semmle.label | a [field FieldA] : Object | | H.cs:124:16:124:27 | call to method Transform [field FieldB] : Object | semmle.label | call to method Transform [field FieldB] : Object | +| H.cs:124:16:124:27 | call to method Transform [field FieldB] : Object | semmle.label | call to method Transform [field FieldB] : Object | +| H.cs:124:16:124:34 | access to field FieldB : Object | semmle.label | access to field FieldB : Object | | H.cs:124:16:124:34 | access to field FieldB : Object | semmle.label | access to field FieldB : Object | | H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | +| H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | semmle.label | access to parameter a [field FieldA] : Object | | H.cs:130:9:130:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | -| H.cs:130:20:130:31 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| H.cs:130:9:130:9 | [post] access to local variable a [field FieldA] : Object | semmle.label | [post] access to local variable a [field FieldA] : Object | +| H.cs:130:20:130:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:130:20:130:36 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:131:14:131:19 | call to method Get | semmle.label | call to method Get | | H.cs:131:14:131:19 | call to method Get | semmle.label | call to method Get | | H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | +| H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | semmle.label | access to local variable a [field FieldA] : Object | +| H.cs:138:27:138:27 | o : A | semmle.label | o : A | | H.cs:138:27:138:27 | o : A | semmle.label | o : A | | H.cs:141:9:141:9 | [post] access to local variable a [field FieldA] : A | semmle.label | [post] access to local variable a [field FieldA] : A | +| H.cs:141:9:141:9 | [post] access to local variable a [field FieldA] : A | semmle.label | [post] access to local variable a [field FieldA] : A | +| H.cs:141:20:141:25 | ... as ... : A | semmle.label | ... as ... : A | | H.cs:141:20:141:25 | ... as ... : A | semmle.label | ... as ... : A | | H.cs:142:16:142:27 | call to method Transform [field FieldB] : A | semmle.label | call to method Transform [field FieldB] : A | +| H.cs:142:16:142:27 | call to method Transform [field FieldB] : A | semmle.label | call to method Transform [field FieldB] : A | +| H.cs:142:16:142:34 | access to field FieldB : A | semmle.label | access to field FieldB : A | | H.cs:142:16:142:34 | access to field FieldB : A | semmle.label | access to field FieldB : A | | H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | semmle.label | access to local variable a [field FieldA] : A | -| H.cs:147:17:147:32 | call to method Through : A | semmle.label | call to method Through : A | -| H.cs:147:25:147:31 | object creation of type A : A | semmle.label | object creation of type A : A | +| H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | semmle.label | access to local variable a [field FieldA] : A | +| H.cs:147:17:147:39 | call to method Through : A | semmle.label | call to method Through : A | +| H.cs:147:17:147:39 | call to method Through : A | semmle.label | call to method Through : A | +| H.cs:147:25:147:38 | call to method Source<A> : A | semmle.label | call to method Source<A> : A | +| H.cs:147:25:147:38 | call to method Source<A> : A | semmle.label | call to method Source<A> : A | +| H.cs:148:14:148:14 | access to local variable a | semmle.label | access to local variable a | | H.cs:148:14:148:14 | access to local variable a | semmle.label | access to local variable a | | H.cs:153:32:153:32 | o : Object | semmle.label | o : Object | -| H.cs:155:17:155:23 | object creation of type B : B | semmle.label | object creation of type B : B | +| H.cs:153:32:153:32 | o : Object | semmle.label | o : Object | +| H.cs:155:17:155:30 | call to method Source<B> : B | semmle.label | call to method Source<B> : B | +| H.cs:155:17:155:30 | call to method Source<B> : B | semmle.label | call to method Source<B> : B | +| H.cs:156:9:156:9 | [post] access to local variable b [field FieldB] : Object | semmle.label | [post] access to local variable b [field FieldB] : Object | | H.cs:156:9:156:9 | [post] access to local variable b [field FieldB] : Object | semmle.label | [post] access to local variable b [field FieldB] : Object | | H.cs:156:9:156:9 | access to local variable b : B | semmle.label | access to local variable b : B | +| H.cs:156:9:156:9 | access to local variable b : B | semmle.label | access to local variable b : B | +| H.cs:156:20:156:20 | access to parameter o : Object | semmle.label | access to parameter o : Object | | H.cs:156:20:156:20 | access to parameter o : Object | semmle.label | access to parameter o : Object | | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | semmle.label | [post] access to parameter a [field FieldA, field FieldB] : Object | +| H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | semmle.label | [post] access to parameter a [field FieldA, field FieldB] : Object | +| H.cs:157:9:157:9 | [post] access to parameter a [field FieldA] : B | semmle.label | [post] access to parameter a [field FieldA] : B | | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA] : B | semmle.label | [post] access to parameter a [field FieldA] : B | | H.cs:157:20:157:20 | access to local variable b : B | semmle.label | access to local variable b : B | +| H.cs:157:20:157:20 | access to local variable b : B | semmle.label | access to local variable b : B | | H.cs:157:20:157:20 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | -| H.cs:163:17:163:28 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| H.cs:157:20:157:20 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | +| H.cs:163:17:163:35 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:163:17:163:35 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | semmle.label | [post] access to local variable a [field FieldA, field FieldB] : Object | | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | semmle.label | [post] access to local variable a [field FieldA, field FieldB] : Object | | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA] : B | semmle.label | [post] access to local variable a [field FieldA] : B | +| H.cs:164:19:164:19 | [post] access to local variable a [field FieldA] : B | semmle.label | [post] access to local variable a [field FieldA] : B | | H.cs:164:22:164:22 | access to local variable o : Object | semmle.label | access to local variable o : Object | -| H.cs:165:17:165:28 | (...) ... : B | semmle.label | (...) ... : B | -| H.cs:165:17:165:28 | (...) ... [field FieldB] : Object | semmle.label | (...) ... [field FieldB] : Object | -| H.cs:165:21:165:21 | access to local variable a [field FieldA, field FieldB] : Object | semmle.label | access to local variable a [field FieldA, field FieldB] : Object | -| H.cs:165:21:165:21 | access to local variable a [field FieldA] : B | semmle.label | access to local variable a [field FieldA] : B | -| H.cs:165:21:165:28 | access to field FieldA : B | semmle.label | access to field FieldA : B | -| H.cs:165:21:165:28 | access to field FieldA [field FieldB] : Object | semmle.label | access to field FieldA [field FieldB] : Object | +| H.cs:164:22:164:22 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| H.cs:165:17:165:27 | (...) ... : B | semmle.label | (...) ... : B | +| H.cs:165:17:165:27 | (...) ... : B | semmle.label | (...) ... : B | +| H.cs:165:17:165:27 | (...) ... [field FieldB] : Object | semmle.label | (...) ... [field FieldB] : Object | +| H.cs:165:17:165:27 | (...) ... [field FieldB] : Object | semmle.label | (...) ... [field FieldB] : Object | +| H.cs:165:20:165:20 | access to local variable a [field FieldA, field FieldB] : Object | semmle.label | access to local variable a [field FieldA, field FieldB] : Object | +| H.cs:165:20:165:20 | access to local variable a [field FieldA, field FieldB] : Object | semmle.label | access to local variable a [field FieldA, field FieldB] : Object | +| H.cs:165:20:165:20 | access to local variable a [field FieldA] : B | semmle.label | access to local variable a [field FieldA] : B | +| H.cs:165:20:165:20 | access to local variable a [field FieldA] : B | semmle.label | access to local variable a [field FieldA] : B | +| H.cs:165:20:165:27 | access to field FieldA : B | semmle.label | access to field FieldA : B | +| H.cs:165:20:165:27 | access to field FieldA : B | semmle.label | access to field FieldA : B | +| H.cs:165:20:165:27 | access to field FieldA [field FieldB] : Object | semmle.label | access to field FieldA [field FieldB] : Object | +| H.cs:165:20:165:27 | access to field FieldA [field FieldB] : Object | semmle.label | access to field FieldA [field FieldB] : Object | +| H.cs:166:14:166:14 | access to local variable b | semmle.label | access to local variable b | | H.cs:166:14:166:14 | access to local variable b | semmle.label | access to local variable b | | H.cs:167:14:167:14 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | +| H.cs:167:14:167:14 | access to local variable b [field FieldB] : Object | semmle.label | access to local variable b [field FieldB] : Object | +| H.cs:167:14:167:21 | access to field FieldB | semmle.label | access to field FieldB | | H.cs:167:14:167:21 | access to field FieldB | semmle.label | access to field FieldB | | I.cs:7:9:7:14 | [post] this access [field Field1] : Object | semmle.label | [post] this access [field Field1] : Object | -| I.cs:7:18:7:29 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | -| I.cs:13:17:13:28 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| I.cs:7:9:7:14 | [post] this access [field Field1] : Object | semmle.label | [post] this access [field Field1] : Object | +| I.cs:7:18:7:34 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| I.cs:7:18:7:34 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| I.cs:13:17:13:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| I.cs:13:17:13:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| I.cs:15:9:15:9 | [post] access to local variable i [field Field1] : Object | semmle.label | [post] access to local variable i [field Field1] : Object | | I.cs:15:9:15:9 | [post] access to local variable i [field Field1] : Object | semmle.label | [post] access to local variable i [field Field1] : Object | | I.cs:15:20:15:20 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| I.cs:15:20:15:20 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| I.cs:16:9:16:9 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:16:9:16:9 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:17:9:17:9 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | +| I.cs:17:9:17:9 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | +| I.cs:18:14:18:14 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:18:14:18:14 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:18:14:18:21 | access to field Field1 | semmle.label | access to field Field1 | +| I.cs:18:14:18:21 | access to field Field1 | semmle.label | access to field Field1 | +| I.cs:21:13:21:19 | object creation of type I [field Field1] : Object | semmle.label | object creation of type I [field Field1] : Object | | I.cs:21:13:21:19 | object creation of type I [field Field1] : Object | semmle.label | object creation of type I [field Field1] : Object | | I.cs:22:9:22:9 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | +| I.cs:22:9:22:9 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | +| I.cs:23:14:23:14 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:23:14:23:14 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:23:14:23:21 | access to field Field1 | semmle.label | access to field Field1 | +| I.cs:23:14:23:21 | access to field Field1 | semmle.label | access to field Field1 | +| I.cs:26:13:26:37 | [pre-initializer] object creation of type I [field Field1] : Object | semmle.label | [pre-initializer] object creation of type I [field Field1] : Object | | I.cs:26:13:26:37 | [pre-initializer] object creation of type I [field Field1] : Object | semmle.label | [pre-initializer] object creation of type I [field Field1] : Object | | I.cs:27:14:27:14 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | +| I.cs:27:14:27:14 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:27:14:27:21 | access to field Field1 | semmle.label | access to field Field1 | -| I.cs:31:13:31:24 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| I.cs:27:14:27:21 | access to field Field1 | semmle.label | access to field Field1 | +| I.cs:31:13:31:29 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| I.cs:31:13:31:29 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| I.cs:32:9:32:9 | [post] access to local variable i [field Field1] : Object | semmle.label | [post] access to local variable i [field Field1] : Object | | I.cs:32:9:32:9 | [post] access to local variable i [field Field1] : Object | semmle.label | [post] access to local variable i [field Field1] : Object | | I.cs:32:20:32:20 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| I.cs:32:20:32:20 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| I.cs:33:9:33:9 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:33:9:33:9 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | | I.cs:34:12:34:12 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | +| I.cs:34:12:34:12 | access to local variable i [field Field1] : Object | semmle.label | access to local variable i [field Field1] : Object | +| I.cs:37:23:37:23 | i [field Field1] : Object | semmle.label | i [field Field1] : Object | | I.cs:37:23:37:23 | i [field Field1] : Object | semmle.label | i [field Field1] : Object | | I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | semmle.label | access to parameter i [field Field1] : Object | +| I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | semmle.label | access to parameter i [field Field1] : Object | +| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | semmle.label | access to parameter i [field Field1] : Object | | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | semmle.label | access to parameter i [field Field1] : Object | | I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 | -| J.cs:12:17:12:28 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 | +| J.cs:12:17:12:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| J.cs:12:17:12:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object | | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object | | J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | | J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | | J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:21:18:21:38 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | -| J.cs:21:36:21:36 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:21:36:21:52 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| J.cs:21:36:21:52 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object | +| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | | J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 | | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 | | J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 | subpaths | A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C | -| A.cs:13:15:13:22 | object creation of type C1 : C1 | A.cs:145:27:145:27 | c : C1 | A.cs:145:32:145:35 | [post] this access [field c] : C1 | A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | +| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C | +| A.cs:13:15:13:29 | call to method Source<C1> : C1 | A.cs:145:27:145:27 | c : C1 | A.cs:145:32:145:35 | [post] this access [field c] : C1 | A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | +| A.cs:13:15:13:29 | call to method Source<C1> : C1 | A.cs:145:27:145:27 | c : C1 | A.cs:145:32:145:35 | [post] this access [field c] : C1 | A.cs:13:9:13:9 | [post] access to local variable b [field c] : C1 | | A.cs:14:14:14:14 | access to local variable b [field c] : C1 | A.cs:146:18:146:20 | this [field c] : C1 | A.cs:146:33:146:38 | access to field c : C1 | A.cs:14:14:14:20 | call to method Get : C1 | -| A.cs:15:15:15:28 | object creation of type B [field c] : C | A.cs:146:18:146:20 | this [field c] : C | A.cs:146:33:146:38 | access to field c : C | A.cs:15:14:15:35 | call to method Get : C | -| A.cs:15:21:15:27 | object creation of type C : C | A.cs:141:20:141:20 | c : C | A.cs:143:13:143:16 | [post] this access [field c] : C | A.cs:15:15:15:28 | object creation of type B [field c] : C | -| A.cs:22:25:22:32 | object creation of type C2 : C2 | A.cs:42:29:42:29 | c : C2 | A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | A.cs:22:14:22:33 | call to method SetOnB [field c] : C2 | -| A.cs:31:29:31:36 | object creation of type C2 : C2 | A.cs:36:33:36:33 | c : C2 | A.cs:39:16:39:28 | ... ? ... : ... [field c] : C2 | A.cs:31:14:31:37 | call to method SetOnBWrap [field c] : C2 | +| A.cs:14:14:14:14 | access to local variable b [field c] : C1 | A.cs:146:18:146:20 | this [field c] : C1 | A.cs:146:33:146:38 | access to field c : C1 | A.cs:14:14:14:20 | call to method Get : C1 | +| A.cs:15:15:15:35 | object creation of type B [field c] : C | A.cs:146:18:146:20 | this [field c] : C | A.cs:146:33:146:38 | access to field c : C | A.cs:15:14:15:42 | call to method Get : C | +| A.cs:15:15:15:35 | object creation of type B [field c] : C | A.cs:146:18:146:20 | this [field c] : C | A.cs:146:33:146:38 | access to field c : C | A.cs:15:14:15:42 | call to method Get : C | +| A.cs:15:21:15:34 | call to method Source<C> : C | A.cs:141:20:141:20 | c : C | A.cs:143:13:143:16 | [post] this access [field c] : C | A.cs:15:15:15:35 | object creation of type B [field c] : C | +| A.cs:15:21:15:34 | call to method Source<C> : C | A.cs:141:20:141:20 | c : C | A.cs:143:13:143:16 | [post] this access [field c] : C | A.cs:15:15:15:35 | object creation of type B [field c] : C | +| A.cs:22:25:22:37 | call to method Source<C2> : C2 | A.cs:42:29:42:29 | c : C2 | A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | A.cs:22:14:22:38 | call to method SetOnB [field c] : C2 | +| A.cs:22:25:22:37 | call to method Source<C2> : C2 | A.cs:42:29:42:29 | c : C2 | A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | A.cs:22:14:22:38 | call to method SetOnB [field c] : C2 | +| A.cs:31:29:31:41 | call to method Source<C2> : C2 | A.cs:36:33:36:33 | c : C2 | A.cs:39:16:39:28 | ... ? ... : ... [field c] : C2 | A.cs:31:14:31:42 | call to method SetOnBWrap [field c] : C2 | +| A.cs:31:29:31:41 | call to method Source<C2> : C2 | A.cs:36:33:36:33 | c : C2 | A.cs:39:16:39:28 | ... ? ... : ... [field c] : C2 | A.cs:31:14:31:42 | call to method SetOnBWrap [field c] : C2 | +| A.cs:38:29:38:29 | access to parameter c : C2 | A.cs:42:29:42:29 | c : C2 | A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | A.cs:38:18:38:30 | call to method SetOnB [field c] : C2 | | A.cs:38:29:38:29 | access to parameter c : C2 | A.cs:42:29:42:29 | c : C2 | A.cs:48:20:48:21 | access to local variable b2 [field c] : C2 | A.cs:38:18:38:30 | call to method SetOnB [field c] : C2 | | A.cs:47:20:47:20 | access to parameter c : C2 | A.cs:145:27:145:27 | c : C2 | A.cs:145:32:145:35 | [post] this access [field c] : C2 | A.cs:47:13:47:14 | [post] access to local variable b2 [field c] : C2 | -| A.cs:83:15:83:21 | object creation of type C : C | A.cs:145:27:145:27 | c : C | A.cs:145:32:145:35 | [post] this access [field c] : C | A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | +| A.cs:47:20:47:20 | access to parameter c : C2 | A.cs:145:27:145:27 | c : C2 | A.cs:145:32:145:35 | [post] this access [field c] : C2 | A.cs:47:13:47:14 | [post] access to local variable b2 [field c] : C2 | +| A.cs:83:15:83:26 | call to method Source<C> : C | A.cs:145:27:145:27 | c : C | A.cs:145:32:145:35 | [post] this access [field c] : C | A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | +| A.cs:83:15:83:26 | call to method Source<C> : C | A.cs:145:27:145:27 | c : C | A.cs:145:32:145:35 | [post] this access [field c] : C | A.cs:83:9:83:9 | [post] access to parameter b [field c] : C | +| A.cs:105:23:105:23 | access to local variable b : B | A.cs:95:20:95:20 | b : B | A.cs:98:13:98:16 | [post] this access [field b] : B | A.cs:105:17:105:29 | object creation of type D [field b] : B | | A.cs:105:23:105:23 | access to local variable b : B | A.cs:95:20:95:20 | b : B | A.cs:98:13:98:16 | [post] this access [field b] : B | A.cs:105:17:105:29 | object creation of type D [field b] : B | | A.cs:114:29:114:29 | access to local variable b : B | A.cs:157:25:157:28 | head : B | A.cs:159:13:159:16 | [post] this access [field head] : B | A.cs:114:18:114:54 | object creation of type MyList [field head] : B | +| A.cs:114:29:114:29 | access to local variable b : B | A.cs:157:25:157:28 | head : B | A.cs:159:13:159:16 | [post] this access [field head] : B | A.cs:114:18:114:54 | object creation of type MyList [field head] : B | +| A.cs:115:35:115:36 | access to local variable l1 [field head] : B | A.cs:157:38:157:41 | next [field head] : B | A.cs:160:13:160:16 | [post] this access [field next, field head] : B | A.cs:115:18:115:37 | object creation of type MyList [field next, field head] : B | | A.cs:115:35:115:36 | access to local variable l1 [field head] : B | A.cs:157:38:157:41 | next [field head] : B | A.cs:160:13:160:16 | [post] this access [field next, field head] : B | A.cs:115:18:115:37 | object creation of type MyList [field next, field head] : B | | A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | A.cs:157:38:157:41 | next [field next, field head] : B | A.cs:160:13:160:16 | [post] this access [field next, field next, field head] : B | A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | +| A.cs:116:35:116:36 | access to local variable l2 [field next, field head] : B | A.cs:157:38:157:41 | next [field next, field head] : B | A.cs:160:13:160:16 | [post] this access [field next, field next, field head] : B | A.cs:116:18:116:37 | object creation of type MyList [field next, field next, field head] : B | +| A.cs:149:26:149:26 | access to parameter c : C | A.cs:141:20:141:20 | c : C | A.cs:143:13:143:16 | [post] this access [field c] : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | | A.cs:149:26:149:26 | access to parameter c : C | A.cs:141:20:141:20 | c : C | A.cs:143:13:143:16 | [post] this access [field c] : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | | B.cs:6:27:6:27 | access to local variable e : Elem | B.cs:29:26:29:27 | e1 : Elem | B.cs:31:13:31:16 | [post] this access [field elem1] : Elem | B.cs:6:18:6:34 | object creation of type Box1 [field elem1] : Elem | +| B.cs:6:27:6:27 | access to local variable e : Elem | B.cs:29:26:29:27 | e1 : Elem | B.cs:31:13:31:16 | [post] this access [field elem1] : Elem | B.cs:6:18:6:34 | object creation of type Box1 [field elem1] : Elem | +| B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | B.cs:39:26:39:27 | b1 [field elem1] : Elem | B.cs:41:13:41:16 | [post] this access [field box1, field elem1] : Elem | B.cs:7:18:7:29 | object creation of type Box2 [field box1, field elem1] : Elem | | B.cs:7:27:7:28 | access to local variable b1 [field elem1] : Elem | B.cs:39:26:39:27 | b1 [field elem1] : Elem | B.cs:41:13:41:16 | [post] this access [field box1, field elem1] : Elem | B.cs:7:18:7:29 | object creation of type Box2 [field box1, field elem1] : Elem | | B.cs:15:33:15:33 | access to local variable e : Elem | B.cs:29:35:29:36 | e2 : Elem | B.cs:32:13:32:16 | [post] this access [field elem2] : Elem | B.cs:15:18:15:34 | object creation of type Box1 [field elem2] : Elem | +| B.cs:15:33:15:33 | access to local variable e : Elem | B.cs:29:35:29:36 | e2 : Elem | B.cs:32:13:32:16 | [post] this access [field elem2] : Elem | B.cs:15:18:15:34 | object creation of type Box1 [field elem2] : Elem | +| B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | B.cs:39:26:39:27 | b1 [field elem2] : Elem | B.cs:41:13:41:16 | [post] this access [field box1, field elem2] : Elem | B.cs:16:18:16:29 | object creation of type Box2 [field box1, field elem2] : Elem | | B.cs:16:27:16:28 | access to local variable b1 [field elem2] : Elem | B.cs:39:26:39:27 | b1 [field elem2] : Elem | B.cs:41:13:41:16 | [post] this access [field box1, field elem2] : Elem | B.cs:16:18:16:29 | object creation of type Box2 [field box1, field elem2] : Elem | | D.cs:15:34:15:38 | access to parameter value : Object | D.cs:9:9:9:11 | value : Object | D.cs:9:15:9:18 | [post] this access [field trivialPropField] : Object | D.cs:15:15:15:18 | [post] this access [field trivialPropField] : Object | +| D.cs:15:34:15:38 | access to parameter value : Object | D.cs:9:9:9:11 | value : Object | D.cs:9:15:9:18 | [post] this access [field trivialPropField] : Object | D.cs:15:15:15:18 | [post] this access [field trivialPropField] : Object | +| D.cs:22:27:22:28 | access to parameter o2 : Object | D.cs:9:9:9:11 | value : Object | D.cs:9:15:9:18 | [post] this access [field trivialPropField] : Object | D.cs:22:9:22:11 | [post] access to local variable ret [field trivialPropField] : Object | | D.cs:22:27:22:28 | access to parameter o2 : Object | D.cs:9:9:9:11 | value : Object | D.cs:9:15:9:18 | [post] this access [field trivialPropField] : Object | D.cs:22:9:22:11 | [post] access to local variable ret [field trivialPropField] : Object | | D.cs:23:27:23:28 | access to parameter o3 : Object | D.cs:15:9:15:11 | value : Object | D.cs:15:15:15:18 | [post] this access [field trivialPropField] : Object | D.cs:23:9:23:11 | [post] access to local variable ret [field trivialPropField] : Object | +| D.cs:23:27:23:28 | access to parameter o3 : Object | D.cs:15:9:15:11 | value : Object | D.cs:15:15:15:18 | [post] this access [field trivialPropField] : Object | D.cs:23:9:23:11 | [post] access to local variable ret [field trivialPropField] : Object | | D.cs:31:24:31:24 | access to local variable o : Object | D.cs:18:28:18:29 | o1 : Object | D.cs:24:16:24:18 | access to local variable ret [property AutoProp] : Object | D.cs:31:17:31:37 | call to method Create [property AutoProp] : Object | -| D.cs:37:26:37:26 | access to local variable o : Object | D.cs:18:39:18:40 | o2 : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | D.cs:37:13:37:33 | call to method Create [field trivialPropField] : Object | +| D.cs:31:24:31:24 | access to local variable o : Object | D.cs:18:28:18:29 | o1 : Object | D.cs:24:16:24:18 | access to local variable ret [property AutoProp] : Object | D.cs:31:17:31:37 | call to method Create [property AutoProp] : Object | +| D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:18:39:18:40 | o2 : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | +| D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:18:39:18:40 | o2 : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | D.cs:37:13:37:49 | call to method Create [field trivialPropField] : Object | +| D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | D.cs:8:9:8:11 | this [field trivialPropField] : Object | D.cs:8:22:8:42 | access to field trivialPropField : Object | D.cs:39:14:39:26 | access to property TrivialProp : Object | | D.cs:39:14:39:14 | access to local variable d [field trivialPropField] : Object | D.cs:8:9:8:11 | this [field trivialPropField] : Object | D.cs:8:22:8:42 | access to field trivialPropField : Object | D.cs:39:14:39:26 | access to property TrivialProp : Object | | D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | D.cs:14:9:14:11 | this [field trivialPropField] : Object | D.cs:14:22:14:42 | access to field trivialPropField : Object | D.cs:41:14:41:26 | access to property ComplexProp : Object | -| D.cs:43:32:43:32 | access to local variable o : Object | D.cs:18:50:18:51 | o3 : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | D.cs:43:13:43:33 | call to method Create [field trivialPropField] : Object | +| D.cs:41:14:41:14 | access to local variable d [field trivialPropField] : Object | D.cs:14:9:14:11 | this [field trivialPropField] : Object | D.cs:14:22:14:42 | access to field trivialPropField : Object | D.cs:41:14:41:26 | access to property ComplexProp : Object | +| D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:18:50:18:51 | o3 : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | +| D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:18:50:18:51 | o3 : Object | D.cs:24:16:24:18 | access to local variable ret [field trivialPropField] : Object | D.cs:43:13:43:49 | call to method Create [field trivialPropField] : Object | +| D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | D.cs:8:9:8:11 | this [field trivialPropField] : Object | D.cs:8:22:8:42 | access to field trivialPropField : Object | D.cs:45:14:45:26 | access to property TrivialProp : Object | | D.cs:45:14:45:14 | access to local variable d [field trivialPropField] : Object | D.cs:8:9:8:11 | this [field trivialPropField] : Object | D.cs:8:22:8:42 | access to field trivialPropField : Object | D.cs:45:14:45:26 | access to property TrivialProp : Object | | D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | D.cs:14:9:14:11 | this [field trivialPropField] : Object | D.cs:14:22:14:42 | access to field trivialPropField : Object | D.cs:47:14:47:26 | access to property ComplexProp : Object | +| D.cs:47:14:47:14 | access to local variable d [field trivialPropField] : Object | D.cs:14:9:14:11 | this [field trivialPropField] : Object | D.cs:14:22:14:42 | access to field trivialPropField : Object | D.cs:47:14:47:26 | access to property ComplexProp : Object | +| E.cs:23:25:23:25 | access to local variable o : Object | E.cs:8:29:8:29 | o : Object | E.cs:12:16:12:18 | access to local variable ret [field Field] : Object | E.cs:23:17:23:26 | call to method CreateS [field Field] : Object | | E.cs:23:25:23:25 | access to local variable o : Object | E.cs:8:29:8:29 | o : Object | E.cs:12:16:12:18 | access to local variable ret [field Field] : Object | E.cs:23:17:23:26 | call to method CreateS [field Field] : Object | | F.cs:11:24:11:24 | access to local variable o : Object | F.cs:6:28:6:29 | o1 : Object | F.cs:6:46:6:81 | object creation of type F [field Field1] : Object | F.cs:11:17:11:31 | call to method Create [field Field1] : Object | -| F.cs:15:26:15:26 | access to local variable o : Object | F.cs:6:39:6:40 | o2 : Object | F.cs:6:46:6:81 | object creation of type F [field Field2] : Object | F.cs:15:13:15:27 | call to method Create [field Field2] : Object | +| F.cs:11:24:11:24 | access to local variable o : Object | F.cs:6:28:6:29 | o1 : Object | F.cs:6:46:6:81 | object creation of type F [field Field1] : Object | F.cs:11:17:11:31 | call to method Create [field Field1] : Object | +| F.cs:15:26:15:42 | call to method Source<Object> : Object | F.cs:6:39:6:40 | o2 : Object | F.cs:6:46:6:81 | object creation of type F [field Field2] : Object | F.cs:15:13:15:43 | call to method Create [field Field2] : Object | +| F.cs:15:26:15:42 | call to method Source<Object> : Object | F.cs:6:39:6:40 | o2 : Object | F.cs:6:46:6:81 | object creation of type F [field Field2] : Object | F.cs:15:13:15:43 | call to method Create [field Field2] : Object | +| G.cs:17:24:17:24 | access to local variable e : Elem | G.cs:64:34:64:34 | e : Elem | G.cs:64:39:64:42 | [post] this access [field Elem] : Elem | G.cs:17:9:17:14 | [post] access to field Box1 [field Elem] : Elem | | G.cs:17:24:17:24 | access to local variable e : Elem | G.cs:64:34:64:34 | e : Elem | G.cs:64:39:64:42 | [post] this access [field Elem] : Elem | G.cs:17:9:17:14 | [post] access to field Box1 [field Elem] : Elem | | G.cs:33:29:33:29 | access to local variable e : Elem | G.cs:64:34:64:34 | e : Elem | G.cs:64:39:64:42 | [post] this access [field Elem] : Elem | G.cs:33:9:33:19 | [post] call to method GetBox1 [field Elem] : Elem | +| G.cs:33:29:33:29 | access to local variable e : Elem | G.cs:64:34:64:34 | e : Elem | G.cs:64:39:64:42 | [post] this access [field Elem] : Elem | G.cs:33:9:33:19 | [post] call to method GetBox1 [field Elem] : Elem | +| G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | G.cs:71:21:71:27 | this [field Box1, field Elem] : Elem | G.cs:71:34:71:37 | access to field Box1 [field Elem] : Elem | G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | | G.cs:39:14:39:15 | access to parameter b2 [field Box1, field Elem] : Elem | G.cs:71:21:71:27 | this [field Box1, field Elem] : Elem | G.cs:71:34:71:37 | access to field Box1 [field Elem] : Elem | G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | | G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | G.cs:63:21:63:27 | this [field Elem] : Elem | G.cs:63:34:63:37 | access to field Elem : Elem | G.cs:39:14:39:35 | call to method GetElem : Elem | +| G.cs:39:14:39:25 | call to method GetBox1 [field Elem] : Elem | G.cs:63:21:63:27 | this [field Elem] : Elem | G.cs:63:34:63:37 | access to field Elem : Elem | G.cs:39:14:39:35 | call to method GetElem : Elem | +| H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | H.cs:13:15:13:15 | a [field FieldA] : Object | H.cs:17:16:17:18 | access to local variable ret [field FieldA] : Object | H.cs:24:21:24:28 | call to method Clone [field FieldA] : Object | | H.cs:24:27:24:27 | access to local variable a [field FieldA] : Object | H.cs:13:15:13:15 | a [field FieldA] : Object | H.cs:17:16:17:18 | access to local variable ret [field FieldA] : Object | H.cs:24:21:24:28 | call to method Clone [field FieldA] : Object | | H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | H.cs:44:17:44:28 | call to method Transform [field FieldB] : Object | +| H.cs:44:27:44:27 | access to local variable a [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | H.cs:44:17:44:28 | call to method Transform [field FieldB] : Object | +| H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | H.cs:53:25:53:25 | a [field FieldA] : Object | H.cs:55:9:55:10 | [post] access to parameter b1 [field FieldB] : Object | H.cs:64:25:64:26 | [post] access to local variable b1 [field FieldB] : Object | | H.cs:64:22:64:22 | access to local variable a [field FieldA] : Object | H.cs:53:25:53:25 | a [field FieldA] : Object | H.cs:55:9:55:10 | [post] access to parameter b1 [field FieldB] : Object | H.cs:64:25:64:26 | [post] access to local variable b1 [field FieldB] : Object | | H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | H.cs:53:25:53:25 | a [field FieldA] : Object | H.cs:55:9:55:10 | [post] access to parameter b1 [field FieldB] : Object | H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | -| H.cs:88:20:88:31 | object creation of type Object : Object | H.cs:77:30:77:30 | o : Object | H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | -| H.cs:88:20:88:31 | object creation of type Object : Object | H.cs:77:30:77:30 | o : Object | H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | H.cs:88:34:88:35 | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:80:22:80:22 | access to parameter a [field FieldA] : Object | H.cs:53:25:53:25 | a [field FieldA] : Object | H.cs:55:9:55:10 | [post] access to parameter b1 [field FieldB] : Object | H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:77:30:77:30 | o : Object | H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:77:30:77:30 | o : Object | H.cs:79:9:79:9 | [post] access to parameter a [field FieldA] : Object | H.cs:88:17:88:17 | [post] access to local variable a [field FieldA] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:77:30:77:30 | o : Object | H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | H.cs:88:39:88:40 | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:77:30:77:30 | o : Object | H.cs:80:25:80:26 | [post] access to parameter b1 [field FieldB] : Object | H.cs:88:39:88:40 | [post] access to local variable b1 [field FieldB] : Object | +| H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | H.cs:106:16:106:40 | call to method Transform [field FieldB] : Object | | H.cs:106:26:106:39 | (...) ... [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | H.cs:106:16:106:40 | call to method Transform [field FieldB] : Object | | H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | H.cs:102:23:102:23 | a [field FieldA] : Object | H.cs:106:16:106:40 | call to method Transform [field FieldB] : Object | H.cs:113:17:113:32 | call to method TransformWrap [field FieldB] : Object | +| H.cs:113:31:113:31 | access to local variable a [field FieldA] : Object | H.cs:102:23:102:23 | a [field FieldA] : Object | H.cs:106:16:106:40 | call to method Transform [field FieldB] : Object | H.cs:113:17:113:32 | call to method TransformWrap [field FieldB] : Object | +| H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | H.cs:124:16:124:27 | call to method Transform [field FieldB] : Object | | H.cs:124:26:124:26 | access to parameter a [field FieldA] : Object | H.cs:33:19:33:19 | a [field FieldA] : Object | H.cs:37:16:37:16 | access to local variable b [field FieldB] : Object | H.cs:124:16:124:27 | call to method Transform [field FieldB] : Object | | H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | H.cs:122:18:122:18 | a [field FieldA] : Object | H.cs:124:16:124:34 | access to field FieldB : Object | H.cs:131:14:131:19 | call to method Get : Object | +| H.cs:131:18:131:18 | access to local variable a [field FieldA] : Object | H.cs:122:18:122:18 | a [field FieldA] : Object | H.cs:124:16:124:34 | access to field FieldB : Object | H.cs:131:14:131:19 | call to method Get : Object | | H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | H.cs:33:19:33:19 | a [field FieldA] : A | H.cs:37:16:37:16 | access to local variable b [field FieldB] : A | H.cs:142:16:142:27 | call to method Transform [field FieldB] : A | -| H.cs:147:25:147:31 | object creation of type A : A | H.cs:138:27:138:27 | o : A | H.cs:142:16:142:34 | access to field FieldB : A | H.cs:147:17:147:32 | call to method Through : A | +| H.cs:142:26:142:26 | access to local variable a [field FieldA] : A | H.cs:33:19:33:19 | a [field FieldA] : A | H.cs:37:16:37:16 | access to local variable b [field FieldB] : A | H.cs:142:16:142:27 | call to method Transform [field FieldB] : A | +| H.cs:147:25:147:38 | call to method Source<A> : A | H.cs:138:27:138:27 | o : A | H.cs:142:16:142:34 | access to field FieldB : A | H.cs:147:17:147:39 | call to method Through : A | +| H.cs:147:25:147:38 | call to method Source<A> : A | H.cs:138:27:138:27 | o : A | H.cs:142:16:142:34 | access to field FieldB : A | H.cs:147:17:147:39 | call to method Through : A | +| H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | | H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | #select -| A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:23 | object creation of type C : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:23 | object creation of type C : C | object creation of type C : C | -| A.cs:14:14:14:20 | call to method Get | A.cs:13:15:13:22 | object creation of type C1 : C1 | A.cs:14:14:14:20 | call to method Get | $@ | A.cs:13:15:13:22 | object creation of type C1 : C1 | object creation of type C1 : C1 | -| A.cs:15:14:15:35 | call to method Get | A.cs:15:21:15:27 | object creation of type C : C | A.cs:15:14:15:35 | call to method Get | $@ | A.cs:15:21:15:27 | object creation of type C : C | object creation of type C : C | -| A.cs:24:14:24:17 | access to field c | A.cs:22:25:22:32 | object creation of type C2 : C2 | A.cs:24:14:24:17 | access to field c | $@ | A.cs:22:25:22:32 | object creation of type C2 : C2 | object creation of type C2 : C2 | -| A.cs:33:14:33:17 | access to field c | A.cs:31:29:31:36 | object creation of type C2 : C2 | A.cs:33:14:33:17 | access to field c | $@ | A.cs:31:29:31:36 | object creation of type C2 : C2 | object creation of type C2 : C2 | -| A.cs:64:18:64:26 | access to field a | A.cs:55:17:55:23 | object creation of type A : A | A.cs:64:18:64:26 | access to field a | $@ | A.cs:55:17:55:23 | object creation of type A : A | object creation of type A : A | -| A.cs:89:14:89:16 | access to field c | A.cs:83:15:83:21 | object creation of type C : C | A.cs:89:14:89:16 | access to field c | $@ | A.cs:83:15:83:21 | object creation of type C : C | object creation of type C : C | -| A.cs:106:14:106:16 | access to field b | A.cs:98:30:98:36 | object creation of type B : B | A.cs:106:14:106:16 | access to field b | $@ | A.cs:98:30:98:36 | object creation of type B : B | object creation of type B : B | -| A.cs:106:14:106:16 | access to field b | A.cs:104:17:104:23 | object creation of type B : B | A.cs:106:14:106:16 | access to field b | $@ | A.cs:104:17:104:23 | object creation of type B : B | object creation of type B : B | -| A.cs:107:14:107:18 | access to field c | A.cs:97:19:97:25 | object creation of type C : C | A.cs:107:14:107:18 | access to field c | $@ | A.cs:97:19:97:25 | object creation of type C : C | object creation of type C : C | -| A.cs:108:14:108:16 | access to field c | A.cs:97:19:97:25 | object creation of type C : C | A.cs:108:14:108:16 | access to field c | $@ | A.cs:97:19:97:25 | object creation of type C : C | object creation of type C : C | -| A.cs:119:14:119:30 | access to field head | A.cs:113:17:113:23 | object creation of type B : B | A.cs:119:14:119:30 | access to field head | $@ | A.cs:113:17:113:23 | object creation of type B : B | object creation of type B : B | -| A.cs:123:18:123:23 | access to field head | A.cs:113:17:113:23 | object creation of type B : B | A.cs:123:18:123:23 | access to field head | $@ | A.cs:113:17:113:23 | object creation of type B : B | object creation of type B : B | -| B.cs:8:14:8:26 | access to field elem1 | B.cs:5:17:5:26 | object creation of type Elem : Elem | B.cs:8:14:8:26 | access to field elem1 | $@ | B.cs:5:17:5:26 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| B.cs:18:14:18:26 | access to field elem2 | B.cs:14:17:14:26 | object creation of type Elem : Elem | B.cs:18:14:18:26 | access to field elem2 | $@ | B.cs:14:17:14:26 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| C.cs:23:14:23:15 | access to field s1 | C.cs:3:23:3:32 | object creation of type Elem : Elem | C.cs:23:14:23:15 | access to field s1 | $@ | C.cs:3:23:3:32 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| C.cs:24:14:24:15 | access to field s2 | C.cs:4:32:4:41 | object creation of type Elem : Elem | C.cs:24:14:24:15 | access to field s2 | $@ | C.cs:4:32:4:41 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| C.cs:25:14:25:15 | access to field s3 | C.cs:18:19:18:28 | object creation of type Elem : Elem | C.cs:25:14:25:15 | access to field s3 | $@ | C.cs:18:19:18:28 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| C.cs:26:14:26:15 | access to field s4 | C.cs:6:30:6:39 | object creation of type Elem : Elem | C.cs:26:14:26:15 | access to field s4 | $@ | C.cs:6:30:6:39 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| C.cs:27:14:27:15 | access to property s5 | C.cs:7:37:7:46 | object creation of type Elem : Elem | C.cs:27:14:27:15 | access to property s5 | $@ | C.cs:7:37:7:46 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| C.cs:28:14:28:15 | access to property s6 | C.cs:8:30:8:39 | object creation of type Elem : Elem | C.cs:28:14:28:15 | access to property s6 | $@ | C.cs:8:30:8:39 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| D.cs:32:14:32:23 | access to property AutoProp | D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:32:14:32:23 | access to property AutoProp | $@ | D.cs:29:17:29:28 | object creation of type Object : Object | object creation of type Object : Object | -| D.cs:39:14:39:26 | access to property TrivialProp | D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:39:14:39:26 | access to property TrivialProp | $@ | D.cs:29:17:29:28 | object creation of type Object : Object | object creation of type Object : Object | -| D.cs:40:14:40:31 | access to field trivialPropField | D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:40:14:40:31 | access to field trivialPropField | $@ | D.cs:29:17:29:28 | object creation of type Object : Object | object creation of type Object : Object | -| D.cs:41:14:41:26 | access to property ComplexProp | D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:41:14:41:26 | access to property ComplexProp | $@ | D.cs:29:17:29:28 | object creation of type Object : Object | object creation of type Object : Object | -| D.cs:45:14:45:26 | access to property TrivialProp | D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:45:14:45:26 | access to property TrivialProp | $@ | D.cs:29:17:29:28 | object creation of type Object : Object | object creation of type Object : Object | -| D.cs:46:14:46:31 | access to field trivialPropField | D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:46:14:46:31 | access to field trivialPropField | $@ | D.cs:29:17:29:28 | object creation of type Object : Object | object creation of type Object : Object | -| D.cs:47:14:47:26 | access to property ComplexProp | D.cs:29:17:29:28 | object creation of type Object : Object | D.cs:47:14:47:26 | access to property ComplexProp | $@ | D.cs:29:17:29:28 | object creation of type Object : Object | object creation of type Object : Object | -| E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:28 | object creation of type Object : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:28 | object creation of type Object : Object | object creation of type Object : Object | -| F.cs:12:14:12:21 | access to field Field1 | F.cs:10:17:10:28 | object creation of type Object : Object | F.cs:12:14:12:21 | access to field Field1 | $@ | F.cs:10:17:10:28 | object creation of type Object : Object | object creation of type Object : Object | -| F.cs:17:14:17:21 | access to field Field2 | F.cs:10:17:10:28 | object creation of type Object : Object | F.cs:17:14:17:21 | access to field Field2 | $@ | F.cs:10:17:10:28 | object creation of type Object : Object | object creation of type Object : Object | -| F.cs:20:14:20:21 | access to field Field1 | F.cs:10:17:10:28 | object creation of type Object : Object | F.cs:20:14:20:21 | access to field Field1 | $@ | F.cs:10:17:10:28 | object creation of type Object : Object | object creation of type Object : Object | -| F.cs:25:14:25:21 | access to field Field2 | F.cs:10:17:10:28 | object creation of type Object : Object | F.cs:25:14:25:21 | access to field Field2 | $@ | F.cs:10:17:10:28 | object creation of type Object : Object | object creation of type Object : Object | -| G.cs:39:14:39:35 | call to method GetElem | G.cs:7:18:7:27 | object creation of type Elem : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:7:18:7:27 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| G.cs:39:14:39:35 | call to method GetElem | G.cs:15:18:15:27 | object creation of type Elem : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:15:18:15:27 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| G.cs:39:14:39:35 | call to method GetElem | G.cs:23:18:23:27 | object creation of type Elem : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:23:18:23:27 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| G.cs:39:14:39:35 | call to method GetElem | G.cs:31:18:31:27 | object creation of type Elem : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:31:18:31:27 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| G.cs:52:14:52:31 | access to field Elem | G.cs:44:18:44:27 | object creation of type Elem : Elem | G.cs:52:14:52:31 | access to field Elem | $@ | G.cs:44:18:44:27 | object creation of type Elem : Elem | object creation of type Elem : Elem | -| H.cs:25:14:25:25 | access to field FieldA | H.cs:23:20:23:31 | object creation of type Object : Object | H.cs:25:14:25:25 | access to field FieldA | $@ | H.cs:23:20:23:31 | object creation of type Object : Object | object creation of type Object : Object | -| H.cs:45:14:45:21 | access to field FieldB | H.cs:43:20:43:31 | object creation of type Object : Object | H.cs:45:14:45:21 | access to field FieldB | $@ | H.cs:43:20:43:31 | object creation of type Object : Object | object creation of type Object : Object | -| H.cs:65:14:65:22 | access to field FieldB | H.cs:63:20:63:31 | object creation of type Object : Object | H.cs:65:14:65:22 | access to field FieldB | $@ | H.cs:63:20:63:31 | object creation of type Object : Object | object creation of type Object : Object | -| H.cs:89:14:89:21 | access to field FieldA | H.cs:88:20:88:31 | object creation of type Object : Object | H.cs:89:14:89:21 | access to field FieldA | $@ | H.cs:88:20:88:31 | object creation of type Object : Object | object creation of type Object : Object | -| H.cs:90:14:90:22 | access to field FieldB | H.cs:88:20:88:31 | object creation of type Object : Object | H.cs:90:14:90:22 | access to field FieldB | $@ | H.cs:88:20:88:31 | object creation of type Object : Object | object creation of type Object : Object | -| H.cs:114:14:114:21 | access to field FieldB | H.cs:112:20:112:31 | object creation of type Object : Object | H.cs:114:14:114:21 | access to field FieldB | $@ | H.cs:112:20:112:31 | object creation of type Object : Object | object creation of type Object : Object | -| H.cs:131:14:131:19 | call to method Get | H.cs:130:20:130:31 | object creation of type Object : Object | H.cs:131:14:131:19 | call to method Get | $@ | H.cs:130:20:130:31 | object creation of type Object : Object | object creation of type Object : Object | -| H.cs:148:14:148:14 | access to local variable a | H.cs:147:25:147:31 | object creation of type A : A | H.cs:148:14:148:14 | access to local variable a | $@ | H.cs:147:25:147:31 | object creation of type A : A | object creation of type A : A | -| H.cs:166:14:166:14 | access to local variable b | H.cs:155:17:155:23 | object creation of type B : B | H.cs:166:14:166:14 | access to local variable b | $@ | H.cs:155:17:155:23 | object creation of type B : B | object creation of type B : B | -| H.cs:167:14:167:21 | access to field FieldB | H.cs:163:17:163:28 | object creation of type Object : Object | H.cs:167:14:167:21 | access to field FieldB | $@ | H.cs:163:17:163:28 | object creation of type Object : Object | object creation of type Object : Object | -| I.cs:18:14:18:21 | access to field Field1 | I.cs:13:17:13:28 | object creation of type Object : Object | I.cs:18:14:18:21 | access to field Field1 | $@ | I.cs:13:17:13:28 | object creation of type Object : Object | object creation of type Object : Object | -| I.cs:23:14:23:21 | access to field Field1 | I.cs:7:18:7:29 | object creation of type Object : Object | I.cs:23:14:23:21 | access to field Field1 | $@ | I.cs:7:18:7:29 | object creation of type Object : Object | object creation of type Object : Object | -| I.cs:27:14:27:21 | access to field Field1 | I.cs:7:18:7:29 | object creation of type Object : Object | I.cs:27:14:27:21 | access to field Field1 | $@ | I.cs:7:18:7:29 | object creation of type Object : Object | object creation of type Object : Object | -| I.cs:40:14:40:21 | access to field Field1 | I.cs:31:13:31:24 | object creation of type Object : Object | I.cs:40:14:40:21 | access to field Field1 | $@ | I.cs:31:13:31:24 | object creation of type Object : Object | object creation of type Object : Object | -| J.cs:14:14:14:21 | access to property Prop1 | J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:14:14:14:21 | access to property Prop1 | $@ | J.cs:12:17:12:28 | object creation of type Object : Object | object creation of type Object : Object | -| J.cs:18:14:18:21 | access to property Prop1 | J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:18:14:18:21 | access to property Prop1 | $@ | J.cs:12:17:12:28 | object creation of type Object : Object | object creation of type Object : Object | -| J.cs:22:14:22:21 | access to property Prop1 | J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:22:14:22:21 | access to property Prop1 | $@ | J.cs:12:17:12:28 | object creation of type Object : Object | object creation of type Object : Object | -| J.cs:23:14:23:21 | access to property Prop2 | J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:23:14:23:21 | access to property Prop2 | $@ | J.cs:12:17:12:28 | object creation of type Object : Object | object creation of type Object : Object | +| A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:28 | call to method Source<C> : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:28 | call to method Source<C> : C | call to method Source<C> : C | +| A.cs:14:14:14:20 | call to method Get | A.cs:13:15:13:29 | call to method Source<C1> : C1 | A.cs:14:14:14:20 | call to method Get | $@ | A.cs:13:15:13:29 | call to method Source<C1> : C1 | call to method Source<C1> : C1 | +| A.cs:15:14:15:42 | call to method Get | A.cs:15:21:15:34 | call to method Source<C> : C | A.cs:15:14:15:42 | call to method Get | $@ | A.cs:15:21:15:34 | call to method Source<C> : C | call to method Source<C> : C | +| A.cs:24:14:24:17 | access to field c | A.cs:22:25:22:37 | call to method Source<C2> : C2 | A.cs:24:14:24:17 | access to field c | $@ | A.cs:22:25:22:37 | call to method Source<C2> : C2 | call to method Source<C2> : C2 | +| A.cs:33:14:33:17 | access to field c | A.cs:31:29:31:41 | call to method Source<C2> : C2 | A.cs:33:14:33:17 | access to field c | $@ | A.cs:31:29:31:41 | call to method Source<C2> : C2 | call to method Source<C2> : C2 | +| A.cs:64:18:64:26 | access to field a | A.cs:55:17:55:28 | call to method Source<A> : A | A.cs:64:18:64:26 | access to field a | $@ | A.cs:55:17:55:28 | call to method Source<A> : A | call to method Source<A> : A | +| A.cs:89:14:89:16 | access to field c | A.cs:83:15:83:26 | call to method Source<C> : C | A.cs:89:14:89:16 | access to field c | $@ | A.cs:83:15:83:26 | call to method Source<C> : C | call to method Source<C> : C | +| A.cs:106:14:106:16 | access to field b | A.cs:98:30:98:43 | call to method Source<B> : B | A.cs:106:14:106:16 | access to field b | $@ | A.cs:98:30:98:43 | call to method Source<B> : B | call to method Source<B> : B | +| A.cs:106:14:106:16 | access to field b | A.cs:104:17:104:30 | call to method Source<B> : B | A.cs:106:14:106:16 | access to field b | $@ | A.cs:104:17:104:30 | call to method Source<B> : B | call to method Source<B> : B | +| A.cs:107:14:107:18 | access to field c | A.cs:97:19:97:32 | call to method Source<C> : C | A.cs:107:14:107:18 | access to field c | $@ | A.cs:97:19:97:32 | call to method Source<C> : C | call to method Source<C> : C | +| A.cs:108:14:108:16 | access to field c | A.cs:97:19:97:32 | call to method Source<C> : C | A.cs:108:14:108:16 | access to field c | $@ | A.cs:97:19:97:32 | call to method Source<C> : C | call to method Source<C> : C | +| A.cs:119:14:119:30 | access to field head | A.cs:113:17:113:29 | call to method Source<B> : B | A.cs:119:14:119:30 | access to field head | $@ | A.cs:113:17:113:29 | call to method Source<B> : B | call to method Source<B> : B | +| A.cs:123:18:123:23 | access to field head | A.cs:113:17:113:29 | call to method Source<B> : B | A.cs:123:18:123:23 | access to field head | $@ | A.cs:113:17:113:29 | call to method Source<B> : B | call to method Source<B> : B | +| B.cs:8:14:8:26 | access to field elem1 | B.cs:5:17:5:31 | call to method Source<Elem> : Elem | B.cs:8:14:8:26 | access to field elem1 | $@ | B.cs:5:17:5:31 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| B.cs:18:14:18:26 | access to field elem2 | B.cs:14:17:14:31 | call to method Source<Elem> : Elem | B.cs:18:14:18:26 | access to field elem2 | $@ | B.cs:14:17:14:31 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| C.cs:23:14:23:15 | access to field s1 | C.cs:3:23:3:37 | call to method Source<Elem> : Elem | C.cs:23:14:23:15 | access to field s1 | $@ | C.cs:3:23:3:37 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| C.cs:24:14:24:15 | access to field s2 | C.cs:4:32:4:46 | call to method Source<Elem> : Elem | C.cs:24:14:24:15 | access to field s2 | $@ | C.cs:4:32:4:46 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| C.cs:25:14:25:15 | access to field s3 | C.cs:18:19:18:33 | call to method Source<Elem> : Elem | C.cs:25:14:25:15 | access to field s3 | $@ | C.cs:18:19:18:33 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| C.cs:26:14:26:15 | access to field s4 | C.cs:6:30:6:44 | call to method Source<Elem> : Elem | C.cs:26:14:26:15 | access to field s4 | $@ | C.cs:6:30:6:44 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| C.cs:27:14:27:15 | access to property s5 | C.cs:7:37:7:51 | call to method Source<Elem> : Elem | C.cs:27:14:27:15 | access to property s5 | $@ | C.cs:7:37:7:51 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| C.cs:28:14:28:15 | access to property s6 | C.cs:8:30:8:44 | call to method Source<Elem> : Elem | C.cs:28:14:28:15 | access to property s6 | $@ | C.cs:8:30:8:44 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| D.cs:32:14:32:23 | access to property AutoProp | D.cs:29:17:29:33 | call to method Source<Object> : Object | D.cs:32:14:32:23 | access to property AutoProp | $@ | D.cs:29:17:29:33 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| D.cs:39:14:39:26 | access to property TrivialProp | D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:39:14:39:26 | access to property TrivialProp | $@ | D.cs:37:26:37:42 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| D.cs:40:14:40:31 | access to field trivialPropField | D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:40:14:40:31 | access to field trivialPropField | $@ | D.cs:37:26:37:42 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| D.cs:41:14:41:26 | access to property ComplexProp | D.cs:37:26:37:42 | call to method Source<Object> : Object | D.cs:41:14:41:26 | access to property ComplexProp | $@ | D.cs:37:26:37:42 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| D.cs:45:14:45:26 | access to property TrivialProp | D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:45:14:45:26 | access to property TrivialProp | $@ | D.cs:43:32:43:48 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| D.cs:46:14:46:31 | access to field trivialPropField | D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:46:14:46:31 | access to field trivialPropField | $@ | D.cs:43:32:43:48 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| D.cs:47:14:47:26 | access to property ComplexProp | D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:47:14:47:26 | access to property ComplexProp | $@ | D.cs:43:32:43:48 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source<Object> : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| F.cs:12:14:12:21 | access to field Field1 | F.cs:10:17:10:33 | call to method Source<Object> : Object | F.cs:12:14:12:21 | access to field Field1 | $@ | F.cs:10:17:10:33 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| F.cs:17:14:17:21 | access to field Field2 | F.cs:15:26:15:42 | call to method Source<Object> : Object | F.cs:17:14:17:21 | access to field Field2 | $@ | F.cs:15:26:15:42 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| F.cs:20:14:20:21 | access to field Field1 | F.cs:19:32:19:48 | call to method Source<Object> : Object | F.cs:20:14:20:21 | access to field Field1 | $@ | F.cs:19:32:19:48 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| F.cs:25:14:25:21 | access to field Field2 | F.cs:23:32:23:48 | call to method Source<Object> : Object | F.cs:25:14:25:21 | access to field Field2 | $@ | F.cs:23:32:23:48 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| G.cs:39:14:39:35 | call to method GetElem | G.cs:7:18:7:32 | call to method Source<Elem> : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:7:18:7:32 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| G.cs:39:14:39:35 | call to method GetElem | G.cs:15:18:15:32 | call to method Source<Elem> : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:15:18:15:32 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| G.cs:39:14:39:35 | call to method GetElem | G.cs:23:18:23:32 | call to method Source<Elem> : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:23:18:23:32 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| G.cs:39:14:39:35 | call to method GetElem | G.cs:31:18:31:32 | call to method Source<Elem> : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:31:18:31:32 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| G.cs:52:14:52:31 | access to field Elem | G.cs:44:18:44:32 | call to method Source<Elem> : Elem | G.cs:52:14:52:31 | access to field Elem | $@ | G.cs:44:18:44:32 | call to method Source<Elem> : Elem | call to method Source<Elem> : Elem | +| H.cs:25:14:25:25 | access to field FieldA | H.cs:23:20:23:36 | call to method Source<Object> : Object | H.cs:25:14:25:25 | access to field FieldA | $@ | H.cs:23:20:23:36 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| H.cs:45:14:45:21 | access to field FieldB | H.cs:43:20:43:36 | call to method Source<Object> : Object | H.cs:45:14:45:21 | access to field FieldB | $@ | H.cs:43:20:43:36 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| H.cs:65:14:65:22 | access to field FieldB | H.cs:63:20:63:36 | call to method Source<Object> : Object | H.cs:65:14:65:22 | access to field FieldB | $@ | H.cs:63:20:63:36 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| H.cs:89:14:89:21 | access to field FieldA | H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:89:14:89:21 | access to field FieldA | $@ | H.cs:88:20:88:36 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| H.cs:90:14:90:22 | access to field FieldB | H.cs:88:20:88:36 | call to method Source<Object> : Object | H.cs:90:14:90:22 | access to field FieldB | $@ | H.cs:88:20:88:36 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| H.cs:114:14:114:21 | access to field FieldB | H.cs:112:20:112:36 | call to method Source<Object> : Object | H.cs:114:14:114:21 | access to field FieldB | $@ | H.cs:112:20:112:36 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| H.cs:131:14:131:19 | call to method Get | H.cs:130:20:130:36 | call to method Source<Object> : Object | H.cs:131:14:131:19 | call to method Get | $@ | H.cs:130:20:130:36 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| H.cs:148:14:148:14 | access to local variable a | H.cs:147:25:147:38 | call to method Source<A> : A | H.cs:148:14:148:14 | access to local variable a | $@ | H.cs:147:25:147:38 | call to method Source<A> : A | call to method Source<A> : A | +| H.cs:166:14:166:14 | access to local variable b | H.cs:155:17:155:30 | call to method Source<B> : B | H.cs:166:14:166:14 | access to local variable b | $@ | H.cs:155:17:155:30 | call to method Source<B> : B | call to method Source<B> : B | +| H.cs:167:14:167:21 | access to field FieldB | H.cs:163:17:163:35 | call to method Source<Object> : Object | H.cs:167:14:167:21 | access to field FieldB | $@ | H.cs:163:17:163:35 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| I.cs:18:14:18:21 | access to field Field1 | I.cs:13:17:13:33 | call to method Source<Object> : Object | I.cs:18:14:18:21 | access to field Field1 | $@ | I.cs:13:17:13:33 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| I.cs:23:14:23:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source<Object> : Object | I.cs:23:14:23:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| I.cs:27:14:27:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source<Object> : Object | I.cs:27:14:27:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| I.cs:40:14:40:21 | access to field Field1 | I.cs:31:13:31:29 | call to method Source<Object> : Object | I.cs:40:14:40:21 | access to field Field1 | $@ | I.cs:31:13:31:29 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| J.cs:14:14:14:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:14:14:14:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| J.cs:18:14:18:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:18:14:18:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| J.cs:22:14:22:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:22:14:22:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source<Object> : Object | call to method Source<Object> : Object | +| J.cs:23:14:23:21 | access to property Prop2 | J.cs:21:36:21:52 | call to method Source<Object> : Object | J.cs:23:14:23:21 | access to property Prop2 | $@ | J.cs:21:36:21:52 | call to method Source<Object> : Object | call to method Source<Object> : Object | diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.ql b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.ql index 9d1a7f807fd..55578cf970c 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.ql +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.ql @@ -4,20 +4,8 @@ import csharp import DataFlow::PathGraph +import TestUtilities.InlineFlowTest -class Conf extends DataFlow::Configuration { - Conf() { this = "FieldFlowConf" } - - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc | - mc.getTarget().hasName("Sink") and - mc.getAnArgument() = sink.asExpr() - ) - } -} - -from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf +from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf where conf.hasFlowPath(source, sink) select sink, source, sink, "$@", source, source.toString() diff --git a/csharp/ql/test/library-tests/dataflow/fields/G.cs b/csharp/ql/test/library-tests/dataflow/fields/G.cs index 5f35ae57293..4a11c67c225 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/G.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/G.cs @@ -4,7 +4,7 @@ public class G public void M1() { - Elem e = new Elem(); + Elem e = Source<Elem>(1); Box2 b = new Box2(new Box1(null)); b.Box1.Elem = e; SinkWrap(b); @@ -12,7 +12,7 @@ public class G public void M2() { - Elem e = new Elem(); + Elem e = Source<Elem>(2); Box2 b = new Box2(new Box1(null)); b.Box1.SetElem(e); SinkWrap(b); @@ -20,7 +20,7 @@ public class G public void M3() { - Elem e = new Elem(); + Elem e = Source<Elem>(3); Box2 b = new Box2(new Box1(null)); b.GetBox1().Elem = e; SinkWrap(b); @@ -28,7 +28,7 @@ public class G public void M4() { - Elem e = new Elem(); + Elem e = Source<Elem>(4); Box2 b = new Box2(new Box1(null)); b.GetBox1().SetElem(e); SinkWrap(b); @@ -36,12 +36,12 @@ public class G public static void SinkWrap(Box2 b2) { - Sink(b2.GetBox1().GetElem()); + Sink(b2.GetBox1().GetElem()); // $ hasValueFlow=1 $ hasValueFlow=2 $ hasValueFlow=3 $ hasValueFlow=4 } public void M5a() { - Elem e = new Elem(); + Elem e = Source<Elem>(5); boxfield = new Box2(new Box1(null)); boxfield.Box1.Elem = e; M5b(); @@ -49,7 +49,7 @@ public class G private void M5b() { - Sink(boxfield.Box1.Elem); + Sink(boxfield.Box1.Elem); // $ hasValueFlow=5 } public static void Sink(object o) { } @@ -71,4 +71,6 @@ public class G public Box1 GetBox1() => Box1; public void SetBox1(Box1 b) { Box1 = b; } } + + static T Source<T>(object source) => throw null; } \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/fields/H.cs b/csharp/ql/test/library-tests/dataflow/fields/H.cs index 1d214fc89da..079ca2295e8 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/H.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/H.cs @@ -20,10 +20,10 @@ public class H void M1(object o) { var a = new A(); - a.FieldA = new object(); + a.FieldA = Source<object>(1); var clone = Clone(a); - Sink(clone.FieldA); // flow - + Sink(clone.FieldA); // $ hasValueFlow=1 + a = new A(); a.FieldA = o; clone = Clone(a); @@ -40,9 +40,9 @@ public class H void M2(object o) { var a = new A(); - a.FieldA = new object(); + a.FieldA = Source<object>(2); var b = Transform(a); - Sink(b.FieldB); // flow + Sink(b.FieldB); // $ hasValueFlow=2 a = new A(); a.FieldA = o; @@ -60,9 +60,9 @@ public class H var a = new A(); var b1 = new B(); var b2 = new B(); - a.FieldA = new object(); + a.FieldA = Source<object>(3); TransformArg(a, b1, b2); - Sink(b1.FieldB); // flow + Sink(b1.FieldB); // $ hasValueFlow=3 Sink(b2.FieldB); // no flow a = new A(); @@ -85,9 +85,9 @@ public class H var a = new A(); var b1 = new B(); var b2 = new B(); - SetArgs(a, new object(), b1, b2); - Sink(a.FieldA); // flow - Sink(b1.FieldB); // flow + SetArgs(a, Source<object>(4), b1, b2); + Sink(a.FieldA); // $ hasValueFlow=4 + Sink(b1.FieldB); // $ hasValueFlow=4 Sink(b2.FieldB); // no flow a = new A(); @@ -109,9 +109,9 @@ public class H void M5(object o) { var a = new A(); - a.FieldA = new object(); + a.FieldA = Source<object>(5); var b = TransformWrap(a); - Sink(b.FieldB); // flow + Sink(b.FieldB); // $ hasValueFlow=5 a = new A(); a.FieldA = o; @@ -127,8 +127,8 @@ public class H void M6(object o) { var a = new A(); - a.FieldA = new object(); - Sink(Get(a)); // flow + a.FieldA = Source<object>(6); + Sink(Get(a)); // $ hasValueFlow=6 a = new A(); a.FieldA = o; @@ -144,15 +144,15 @@ public class H void M7() { - var a = Through(new A()); - Sink(a); // flow - var b = Through(new B()); + var a = Through(Source<A>(7.1)); + Sink(a); // $ hasValueFlow=7.1 + var b = Through(Source<B>(7.2)); Sink(b); // no flow } void SetNested(A a, object o) { - var b = new B(); + var b = Source<B>(8.1); b.FieldB = o; a.FieldA = b; } @@ -160,12 +160,14 @@ public class H void M8() { var a = new A(); - var o = new object(); + var o = Source<object>(8.2); SetNested(a, o); - var b = (B) a.FieldA; - Sink(b); // flow (from `new B()` inside `SetNested`) - Sink(b.FieldB); // flow + var b = (B)a.FieldA; + Sink(b); // $ hasValueFlow=8.1 + Sink(b.FieldB); // $ hasValueFlow=8.2 } public static void Sink(object o) { } + + static T Source<T>(object source) => throw null; } \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/fields/I.cs b/csharp/ql/test/library-tests/dataflow/fields/I.cs index 99aed3b0df7..41ae9cd364c 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/I.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/I.cs @@ -4,31 +4,31 @@ public class I object Field2; public I() { - Field1 = new object(); - Field2 = new object(); + Field1 = Source<object>(1); + Field2 = Source<object>(2); } private void M() { - var o = new object(); + var o = Source<object>(3); var i = new I(); i.Field1 = o; i.Field2 = o; i.Field2 = null; - Sink(i.Field1); // flow + Sink(i.Field1); // $ hasValueFlow=3 Sink(i.Field2); // no flow i = new I(); i.Field2 = null; - Sink(i.Field1); // flow + Sink(i.Field1); // $ hasValueFlow=1 Sink(i.Field2); // no flow i = new I() { Field2 = null }; - Sink(i.Field1); // flow + Sink(i.Field1); // $ hasValueFlow=1 Sink(i.Field2); // no flow i = new I(); - o = new object(); + o = Source<object>(4); i.Field1 = o; i.Field2 = o; M2(i); @@ -37,10 +37,12 @@ public class I private void M2(I i) { i.Field2 = null; - Sink(i.Field1); // flow + Sink(i.Field1); // $ hasValueFlow=4 Sink(i.Field2); // no flow } public static void Sink(object o) { } + + static T Source<T>(object source) => throw null; } diff --git a/csharp/ql/test/library-tests/dataflow/fields/J.cs b/csharp/ql/test/library-tests/dataflow/fields/J.cs index 4244a514281..b53cdb2e97e 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/J.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs @@ -9,18 +9,18 @@ public class J { private void M1() { - var o = new object(); + var o = Source<object>(1); var r1 = new Record(o, null); - Sink(r1.Prop1); // flow + Sink(r1.Prop1); // $ hasValueFlow=1 Sink(r1.Prop2); // no flow var r2 = r1 with { }; - Sink(r2.Prop1); // flow + Sink(r2.Prop1); // $ hasValueFlow=1 Sink(r2.Prop2); // no flow - var r3 = r1 with { Prop2 = o }; - Sink(r3.Prop1); // flow - Sink(r3.Prop2); // flow + var r3 = r1 with { Prop2 = Source<object>(2) }; + Sink(r3.Prop1); // $ hasValueFlow=1 + Sink(r3.Prop2); // $ hasValueFlow=2 var r4 = r1 with { Prop1 = null }; Sink(r4.Prop1); // no flow @@ -28,4 +28,6 @@ public class J } public static void Sink(object o) { } + + static T Source<T>(object source) => throw null; } From 3983587682b983e097fd288d86fdc94d34c4544d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 13 Oct 2021 16:11:59 +0100 Subject: [PATCH 283/361] C#: Set literals. --- csharp/ql/lib/semmle/code/csharp/Modifier.qll | 7 +- .../code/csharp/commons/Collections.qll | 103 +++------ .../semmle/code/csharp/frameworks/JsonNET.qll | 24 +- .../code/csharp/frameworks/NHibernate.qll | 10 +- .../code/csharp/security/PrivateData.qll | 36 ++- .../flowsinks/ExternalLocationSink.qll | 7 +- .../security/dataflow/flowsources/Remote.qll | 10 +- .../Magic Constants/MagicConstants.qll | 207 +++--------------- .../Naming Conventions/DefaultControlNames.ql | 15 +- .../VariableNameTooShort.ql | 11 +- csharp/ql/src/Dead Code/DeadStoreOfLocal.ql | 27 +-- csharp/ql/src/Stubs/Stubs.qll | 89 +------- .../assemblies/CompareVersions.ql | 12 +- .../library-tests/assemblies/ValidVersions.ql | 10 +- 14 files changed, 108 insertions(+), 460 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/Modifier.qll b/csharp/ql/lib/semmle/code/csharp/Modifier.qll index 542598d204e..0cf9b883430 100644 --- a/csharp/ql/lib/semmle/code/csharp/Modifier.qll +++ b/csharp/ql/lib/semmle/code/csharp/Modifier.qll @@ -19,10 +19,5 @@ class Modifier extends Element, @modifier { * An access modifier: `public`, `private`, `internal` or `protected`. */ class AccessModifier extends Modifier { - AccessModifier() { - hasName("public") or - hasName("private") or - hasName("internal") or - hasName("protected") - } + AccessModifier() { hasName(["public", "private", "internal", "protected"]) } } diff --git a/csharp/ql/lib/semmle/code/csharp/commons/Collections.qll b/csharp/ql/lib/semmle/code/csharp/commons/Collections.qll index cee7b647fe7..0121ef13f8c 100644 --- a/csharp/ql/lib/semmle/code/csharp/commons/Collections.qll +++ b/csharp/ql/lib/semmle/code/csharp/commons/Collections.qll @@ -3,23 +3,12 @@ import csharp private string modifyMethodName() { - result = "Add" or - result = "AddFirst" or - result = "AddLast" or - result = "Clear" or - result = "Enqueue" or - result = "ExceptWith" or - result = "Insert" or - result = "IntersectWith" or - result = "Push" or - result = "Remove" or - result = "RemoveAt" or - result = "RemoveFirst" or - result = "RemoveLast" or - result = "Set" or - result = "SetAll" or - result = "SymmetricExceptWith" or - result = "UnionWith" + result = + [ + "Add", "AddFirst", "AddLast", "Clear", "Enqueue", "ExceptWith", "Insert", "IntersectWith", + "Push", "Remove", "RemoveAt", "RemoveFirst", "RemoveLast", "Set", "SetAll", + "SymmetricExceptWith", "UnionWith" + ] } /** A method call that modifies a collection. */ @@ -39,45 +28,27 @@ class CollectionModificationAccess extends Access { } private string collectionTypeName() { - result = "ArrayList" or - result = "BitArray" or - result = "Hashtable" or - result = "ICollection" or - result = "IDictionary" or - result = "IList" or - result = "Queue" or - result = "ReadOnlyCollectionBase" or - result = "SortedList" or - result = "Stack" + result = + [ + "ArrayList", "BitArray", "Hashtable", "ICollection", "IDictionary", "IList", "Queue", + "ReadOnlyCollectionBase", "SortedList", "Stack" + ] } -private string collectionNamespaceName() { - result = "Mono.Collections" or - result = "System.Collections" -} +private string collectionNamespaceName() { result = ["Mono.Collections", "System.Collections"] } private string genericCollectionNamespaceName() { - result = "Mono.Collections.Generic" or - result = "System.Collections.Generic" + result = ["Mono.Collections.Generic", "System.Collections.Generic"] } private string genericCollectionTypeName() { - result = "Dictionary<,>" or - result = "HashSet<>" or - result = "ICollection<>" or - result = "IDictionary<,>" or - result = "IList<>" or - result = "ISet<>" or - result = "LinkedList<>" or - result = "List<>" or - result = "Queue<>" or - result = "SortedDictionary<,>" or - result = "SortedList<,>" or - result = "SortedSet<>" or - result = "Stack<>" or - result = "SynchronizedCollection<>" or - result = "SynchronizedKeyedCollection<>" or - result = "SynchronizedReadOnlyCollection<>" + result = + [ + "Dictionary<,>", "HashSet<>", "ICollection<>", "IDictionary<,>", "IList<>", "ISet<>", + "LinkedList<>", "List<>", "Queue<>", "SortedDictionary<,>", "SortedList<,>", "SortedSet<>", + "Stack<>", "SynchronizedCollection<>", "SynchronizedKeyedCollection<>", + "SynchronizedReadOnlyCollection<>" + ] } /** A collection type. */ @@ -105,36 +76,18 @@ class EmptyCollectionCreation extends ObjectCreation { } private string readonlyMethodName() { - result = "BinarySearch" or - result = "Clone" or - result = "Contains" or - result = "ContainsKey" or - result = "ContainsValue" or - result = "CopyTo" or - result = "Equals" or - result = "FixedArray" or - result = "FixedSize" or - result = "Get" or - result = "GetEnumerator" or - result = "GetHashCode" or - result = "GetRange" or - result = "IndexOf" or - result = "IsProperSubsetOf" or - result = "IsProperSupersetOf" or - result = "IsSubsetOf" or - result = "IsSupersetOf" or - result = "LastIndexOf" or - result = "MemberwiseClone" or - result = "Peek" or - result = "ToArray" or - result = "ToString" or - result = "TryGetValue" + result = + [ + "BinarySearch", "Clone", "Contains", "ContainsKey", "ContainsValue", "CopyTo", "Equals", + "FixedArray", "FixedSize", "Get", "GetEnumerator", "GetHashCode", "GetRange", "IndexOf", + "IsProperSubsetOf", "IsProperSupersetOf", "IsSubsetOf", "IsSupersetOf", "LastIndexOf", + "MemberwiseClone", "Peek", "ToArray", "ToString", "TryGetValue" + ] } private string noAddMethodName() { result = readonlyMethodName() or - result = "Dequeue" or - result = "Pop" + result = ["Dequeue", "Pop"] } /** Holds if `a` is an access that does not modify a collection. */ diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/JsonNET.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/JsonNET.qll index abd820bdfe4..841bf94dd9a 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/JsonNET.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/JsonNET.qll @@ -120,21 +120,13 @@ module JsonNET { SerializedMember() { // This member has a Json attribute exists(Class attribute | attribute = this.getAnAttribute().getType() | - attribute.hasName("JsonPropertyAttribute") - or - attribute.hasName("JsonDictionaryAttribute") - or - attribute.hasName("JsonRequiredAttribute") - or - attribute.hasName("JsonArrayAttribute") - or - attribute.hasName("JsonConverterAttribute") - or - attribute.hasName("JsonExtensionDataAttribute") - or - attribute.hasName("SerializableAttribute") // System.SerializableAttribute - or - attribute.hasName("DataMemberAttribute") // System.DataMemberAttribute + attribute + .hasName([ + "JsonPropertyAttribute", "JsonDictionaryAttribute", "JsonRequiredAttribute", + "JsonArrayAttribute", "JsonConverterAttribute", "JsonExtensionDataAttribute", + "SerializableAttribute", // System.SerializableAttribute + "DataMemberAttribute" // System.DataMemberAttribute + ]) ) or // This field is a member of an explicitly serialized type @@ -175,7 +167,7 @@ module JsonNET { /** Any attribute class that marks a member to not be serialized. */ private class NotSerializedAttributeClass extends JsonClass { NotSerializedAttributeClass() { - this.hasName("JsonIgnoreAttribute") or this.hasName("NonSerializedAttribute") + this.hasName(["JsonIgnoreAttribute", "NonSerializedAttribute"]) } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/NHibernate.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/NHibernate.qll index ddf7fd410bf..6ce6efb815f 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/NHibernate.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/NHibernate.qll @@ -28,15 +28,7 @@ module NHibernate { /** Gets a type parameter that specifies a mapped class. */ TypeParameter getAMappedObjectTp() { - exists(string methodName | - methodName = "Load<>" - or - methodName = "Merge<>" - or - methodName = "Get<>" - or - methodName = "Query<>" - | + exists(string methodName | methodName = ["Load<>", "Merge<>", "Get<>", "Query<>"] | result = this.getAMethod(methodName).(UnboundGenericMethod).getTypeParameter(0) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/security/PrivateData.qll b/csharp/ql/lib/semmle/code/csharp/security/PrivateData.qll index 10bb06679b7..3ca81e614ad 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/PrivateData.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/PrivateData.qll @@ -14,26 +14,22 @@ import semmle.code.csharp.frameworks.system.windows.Forms /** A string for `match` that identifies strings that look like they represent private data. */ private string privateNames() { - // Inspired by the list on https://cwe.mitre.org/data/definitions/359.html - // Government identifiers, such as Social Security Numbers - result = "%social%security%number%" or - // Contact information, such as home addresses and telephone numbers - result = "%postcode%" or - result = "%zipcode%" or - result = "%telephone%" or - // Geographic location - where the user is (or was) - result = "%latitude%" or - result = "%longitude%" or - // Financial data - such as credit card numbers, salary, bank accounts, and debts - result = "%creditcard%" or - result = "%salary%" or - result = "%bankaccount%" or - // Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc. - result = "%email%" or - result = "%mobile%" or - result = "%employer%" or - // Health - medical conditions, insurance status, prescription records - result = "%medical%" + result = + [ + // Inspired by the list on https://cwe.mitre.org/data/definitions/359.html + // Government identifiers, such as Social Security Numbers + "%social%security%number%", + // Contact information, such as home addresses and telephone numbers + "%postcode%", "%zipcode%", "%telephone%", + // Geographic location - where the user is (or was) + "%latitude%", "%longitude%", + // Financial data - such as credit card numbers, salary, bank accounts, and debts + "%creditcard%", "%salary%", "%bankaccount%", + // Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc. + "%email%", "%mobile%", "%employer%", + // Health - medical conditions, insurance status, prescription records + "%medical%" + ] } /** An expression that might contain private data. */ diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll index 673473eb49b..30736bdabf6 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll @@ -38,12 +38,7 @@ class TraceMessageSink extends ExternalLocationSink { trace.hasQualifiedName("System.Diagnostics", "TraceSource") | this.getExpr() = trace.getAMethod().getACall().getArgumentForName(parameterName) and - ( - parameterName = "format" or - parameterName = "args" or - parameterName = "message" or - parameterName = "category" - ) + parameterName = ["format", "args", "message", "category"] ) } } diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll index 25647e50f2e..fb452e36308 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll @@ -43,15 +43,7 @@ class AspNetQueryStringMember extends Member { * request. */ private string getHttpRequestFlowPropertyNames() { - result = "QueryString" or - result = "Headers" or - result = "RawUrl" or - result = "Url" or - result = "Cookies" or - result = "Form" or - result = "Params" or - result = "Path" or - result = "PathInfo" + result = ["QueryString", "Headers", "RawUrl", "Url", "Cookies", "Form", "Params", "Path", "PathInfo"] } /** A data flow source of remote user input (ASP.NET query string). */ diff --git a/csharp/ql/src/Bad Practices/Magic Constants/MagicConstants.qll b/csharp/ql/src/Bad Practices/Magic Constants/MagicConstants.qll index d604dfaeefe..b65cdcd1961 100644 --- a/csharp/ql/src/Bad Practices/Magic Constants/MagicConstants.qll +++ b/csharp/ql/src/Bad Practices/Magic Constants/MagicConstants.qll @@ -7,179 +7,30 @@ import semmle.code.csharp.frameworks.System */ private predicate trivialPositiveIntValue(string s) { - s = "0" or - s = "1" or - s = "2" or - s = "3" or - s = "4" or - s = "5" or - s = "6" or - s = "7" or - s = "8" or - s = "9" or - s = "10" or - s = "11" or - s = "12" or - s = "13" or - s = "14" or - s = "15" or - s = "16" or - s = "17" or - s = "18" or - s = "19" or - s = "20" or - s = "16" or - s = "32" or - s = "64" or - s = "128" or - s = "256" or - s = "512" or - s = "1024" or - s = "2048" or - s = "4096" or - s = "16384" or - s = "32768" or - s = "65536" or - s = "1048576" or - s = "2147483648" or - s = "4294967296" or - s = "15" or - s = "31" or - s = "63" or - s = "127" or - s = "255" or - s = "511" or - s = "1023" or - s = "2047" or - s = "4095" or - s = "16383" or - s = "32767" or - s = "65535" or - s = "1048577" or - s = "2147483647" or - s = "4294967295" or - s = "0x00000001" or - s = "0x00000002" or - s = "0x00000004" or - s = "0x00000008" or - s = "0x00000010" or - s = "0x00000020" or - s = "0x00000040" or - s = "0x00000080" or - s = "0x00000100" or - s = "0x00000200" or - s = "0x00000400" or - s = "0x00000800" or - s = "0x00001000" or - s = "0x00002000" or - s = "0x00004000" or - s = "0x00008000" or - s = "0x00010000" or - s = "0x00020000" or - s = "0x00040000" or - s = "0x00080000" or - s = "0x00100000" or - s = "0x00200000" or - s = "0x00400000" or - s = "0x00800000" or - s = "0x01000000" or - s = "0x02000000" or - s = "0x04000000" or - s = "0x08000000" or - s = "0x10000000" or - s = "0x20000000" or - s = "0x40000000" or - s = "0x80000000" or - s = "0x00000001" or - s = "0x00000003" or - s = "0x00000007" or - s = "0x0000000f" or - s = "0x0000001f" or - s = "0x0000003f" or - s = "0x0000007f" or - s = "0x000000ff" or - s = "0x000001ff" or - s = "0x000003ff" or - s = "0x000007ff" or - s = "0x00000fff" or - s = "0x00001fff" or - s = "0x00003fff" or - s = "0x00007fff" or - s = "0x0000ffff" or - s = "0x0001ffff" or - s = "0x0003ffff" or - s = "0x0007ffff" or - s = "0x000fffff" or - s = "0x001fffff" or - s = "0x003fffff" or - s = "0x007fffff" or - s = "0x00ffffff" or - s = "0x01ffffff" or - s = "0x03ffffff" or - s = "0x07ffffff" or - s = "0x0fffffff" or - s = "0x1fffffff" or - s = "0x3fffffff" or - s = "0x7fffffff" or - s = "0xffffffff" or - s = "0x0001" or - s = "0x0002" or - s = "0x0004" or - s = "0x0008" or - s = "0x0010" or - s = "0x0020" or - s = "0x0040" or - s = "0x0080" or - s = "0x0100" or - s = "0x0200" or - s = "0x0400" or - s = "0x0800" or - s = "0x1000" or - s = "0x2000" or - s = "0x4000" or - s = "0x8000" or - s = "0x0001" or - s = "0x0003" or - s = "0x0007" or - s = "0x000f" or - s = "0x001f" or - s = "0x003f" or - s = "0x007f" or - s = "0x00ff" or - s = "0x01ff" or - s = "0x03ff" or - s = "0x07ff" or - s = "0x0fff" or - s = "0x1fff" or - s = "0x3fff" or - s = "0x7fff" or - s = "0xffff" or - s = "0x01" or - s = "0x02" or - s = "0x04" or - s = "0x08" or - s = "0x10" or - s = "0x20" or - s = "0x40" or - s = "0x80" or - s = "0x01" or - s = "0x03" or - s = "0x07" or - s = "0x0f" or - s = "0x1f" or - s = "0x3f" or - s = "0x7f" or - s = "0xff" or - s = "0x00" or - s = "10" or - s = "100" or - s = "1000" or - s = "10000" or - s = "100000" or - s = "1000000" or - s = "10000000" or - s = "100000000" or - s = "1000000000" + s = + [ + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", + "17", "18", "19", "20", "16", "32", "64", "128", "256", "512", "1024", "2048", "4096", + "16384", "32768", "65536", "1048576", "2147483648", "4294967296", "15", "31", "63", "127", + "255", "511", "1023", "2047", "4095", "16383", "32767", "65535", "1048577", "2147483647", + "4294967295", "0x00000001", "0x00000002", "0x00000004", "0x00000008", "0x00000010", + "0x00000020", "0x00000040", "0x00000080", "0x00000100", "0x00000200", "0x00000400", + "0x00000800", "0x00001000", "0x00002000", "0x00004000", "0x00008000", "0x00010000", + "0x00020000", "0x00040000", "0x00080000", "0x00100000", "0x00200000", "0x00400000", + "0x00800000", "0x01000000", "0x02000000", "0x04000000", "0x08000000", "0x10000000", + "0x20000000", "0x40000000", "0x80000000", "0x00000001", "0x00000003", "0x00000007", + "0x0000000f", "0x0000001f", "0x0000003f", "0x0000007f", "0x000000ff", "0x000001ff", + "0x000003ff", "0x000007ff", "0x00000fff", "0x00001fff", "0x00003fff", "0x00007fff", + "0x0000ffff", "0x0001ffff", "0x0003ffff", "0x0007ffff", "0x000fffff", "0x001fffff", + "0x003fffff", "0x007fffff", "0x00ffffff", "0x01ffffff", "0x03ffffff", "0x07ffffff", + "0x0fffffff", "0x1fffffff", "0x3fffffff", "0x7fffffff", "0xffffffff", "0x0001", "0x0002", + "0x0004", "0x0008", "0x0010", "0x0020", "0x0040", "0x0080", "0x0100", "0x0200", "0x0400", + "0x0800", "0x1000", "0x2000", "0x4000", "0x8000", "0x0001", "0x0003", "0x0007", "0x000f", + "0x001f", "0x003f", "0x007f", "0x00ff", "0x01ff", "0x03ff", "0x07ff", "0x0fff", "0x1fff", + "0x3fff", "0x7fff", "0xffff", "0x01", "0x02", "0x04", "0x08", "0x10", "0x20", "0x40", "0x80", + "0x01", "0x03", "0x07", "0x0f", "0x1f", "0x3f", "0x7f", "0xff", "0x00", "10", "100", "1000", + "10000", "100000", "1000000", "10000000", "100000000", "1000000000" + ] } private predicate trivialIntValue(string s) { @@ -193,15 +44,7 @@ private predicate intTrivial(Literal lit) { } private predicate powerOfTen(float f) { - f = 10 or - f = 100 or - f = 1000 or - f = 10000 or - f = 100000 or - f = 1000000 or - f = 10000000 or - f = 100000000 or - f = 1000000000 + f = [10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000] } private predicate floatTrivial(Literal lit) { diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql b/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql index be381328582..2bf51653d99 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql @@ -13,16 +13,11 @@ import csharp predicate controlName(string prefix) { - prefix = "[Ll]abel" or - prefix = "[Bb]utton" or - prefix = "[Pp]anel" or - prefix = "[Rr]adio[Bb]utton" or - prefix = "[Pp]rop" or - prefix = "[Ss]atus[Ss]trip" or - prefix = "[Tt]able[Ll]ayout[Dd]esigner" or - prefix = "[Tt]ext[Bb]ox" or - prefix = "[Tt]ool[Ss]trip" or - prefix = "[Pp]icture[Bb]ox" + prefix = + [ + "[Ll]abel", "[Bb]utton", "[Pp]anel", "[Rr]adio[Bb]utton", "[Pp]rop", "[Ss]atus[Ss]trip", + "[Tt]able[Ll]ayout[Dd]esigner", "[Tt]ext[Bb]ox", "[Tt]ool[Ss]trip", "[Pp]icture[Bb]ox" + ] } predicate usedInHumanWrittenCode(Field f) { diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql b/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql index f161edda6c4..cb778465df8 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql @@ -34,16 +34,7 @@ select variable, "Variable name '" + name + "' is too short." // Adjustable: acceptable short names // predicate allowedName(string name) { - name = "url" or - name = "cmd" or - name = "UK" or - name = "uri" or - name = "top" or - name = "row" or - name = "pin" or - name = "log" or - name = "key" or - name = "_" + name = ["url", "cmd", "UK", "uri", "top", "row", "pin", "log", "key", "_"] } // diff --git a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql index 19766a550ec..4612091743f 100644 --- a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql +++ b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql @@ -37,21 +37,11 @@ Expr getADelegateExpr(Callable c) { */ predicate nonEscapingCall(Call c) { exists(string name | c.getTarget().hasName(name) | - name = "ForEach" or - name = "Count" or - name = "Any" or - name = "All" or - name = "Average" or - name = "Aggregate" or - name = "First" or - name = "Last" or - name = "FirstOrDefault" or - name = "LastOrDefault" or - name = "LongCount" or - name = "Max" or - name = "Single" or - name = "SingleOrDefault" or - name = "Sum" + name = + [ + "ForEach", "Count", "Any", "All", "Average", "Aggregate", "First", "Last", "FirstOrDefault", + "LastOrDefault", "LongCount", "Max", "Single", "SingleOrDefault", "Sum" + ] ) } @@ -116,12 +106,7 @@ class RelevantDefinition extends AssignableDefinition { private predicate isDefaultLikeInitializer() { this.isInitializer() and exists(Expr e | e = this.getSource().stripCasts() | - exists(string val | val = e.getValue() | - val = "0" or - val = "-1" or - val = "" or - val = "false" - ) + e.getValue() = ["0", "-1", "", "false"] or e instanceof NullLiteral or diff --git a/csharp/ql/src/Stubs/Stubs.qll b/csharp/ql/src/Stubs/Stubs.qll index 6f92fb12f55..93402a39648 100644 --- a/csharp/ql/src/Stubs/Stubs.qll +++ b/csharp/ql/src/Stubs/Stubs.qll @@ -612,83 +612,18 @@ private string stubImplementation(Virtualizable c) { } private predicate isKeyword(string s) { - s = "abstract" or - s = "as" or - s = "base" or - s = "bool" or - s = "break" or - s = "byte" or - s = "case" or - s = "catch" or - s = "char" or - s = "checked" or - s = "class" or - s = "const" or - s = "continue" or - s = "decimal" or - s = "default" or - s = "delegate" or - s = "do" or - s = "double" or - s = "else" or - s = "enum" or - s = "event" or - s = "explicit" or - s = "extern" or - s = "false" or - s = "finally" or - s = "fixed" or - s = "float" or - s = "for" or - s = "foreach" or - s = "goto" or - s = "if" or - s = "implicit" or - s = "in" or - s = "int" or - s = "interface" or - s = "internal" or - s = "is" or - s = "lock" or - s = "long" or - s = "namespace" or - s = "new" or - s = "null" or - s = "object" or - s = "operator" or - s = "out" or - s = "override" or - s = "params" or - s = "private" or - s = "protected" or - s = "public" or - s = "readonly" or - s = "ref" or - s = "return" or - s = "sbyte" or - s = "sealed" or - s = "short" or - s = "sizeof" or - s = "stackalloc" or - s = "static" or - s = "string" or - s = "struct" or - s = "switch" or - s = "this" or - s = "throw" or - s = "true" or - s = "try" or - s = "typeof" or - s = "uint" or - s = "ulong" or - s = "unchecked" or - s = "unsafe" or - s = "ushort" or - s = "using" or - s = "virtual" or - s = "void" or - s = "volatile" or - s = "while" + s = + [ + "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", + "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", + "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", + "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", + "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", + "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", + "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", + "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", + "volatile", "while" + ] } bindingset[s] diff --git a/csharp/ql/test/library-tests/assemblies/CompareVersions.ql b/csharp/ql/test/library-tests/assemblies/CompareVersions.ql index cb4b6745258..ec1b13dcbe6 100644 --- a/csharp/ql/test/library-tests/assemblies/CompareVersions.ql +++ b/csharp/ql/test/library-tests/assemblies/CompareVersions.ql @@ -1,16 +1,8 @@ import csharp Version getAVersion() { - result = "1.2" or - result = "1.2.0" or - result = "1.2.0.0" or - result = "1.3" or - result = "1.3.1" or - result = "1.3.1.2" or - result = "1.3.1.3" or - result = "1.3.2" or - result = "1.4" or - result = "2.3.1" + result = + ["1.2", "1.2.0", "1.2.0.0", "1.3", "1.3.1", "1.3.1.2", "1.3.1.3", "1.3.2", "1.4", "2.3.1"] } from Version v1, Version v2 diff --git a/csharp/ql/test/library-tests/assemblies/ValidVersions.ql b/csharp/ql/test/library-tests/assemblies/ValidVersions.ql index da5b749200c..3e66e165461 100644 --- a/csharp/ql/test/library-tests/assemblies/ValidVersions.ql +++ b/csharp/ql/test/library-tests/assemblies/ValidVersions.ql @@ -1,14 +1,6 @@ import csharp from Version version -where - version = "1.2.3.4" or - version = "2.3.24" or - version = "1.2" or - version = "xxx" or - version = "1.x" or - version = "1" or - version = "" or - version = "1234.56" +where version = ["1.2.3.4", "2.3.24", "1.2", "xxx", "1.x", "1", "", "1234.56"] select version, version.getMajor(), version.getMajorRevision(), version.getMinor(), version.getMinorRevision() From a82c76d2f954308016670d27171bf21ca01457ef Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 13 Oct 2021 16:26:28 +0100 Subject: [PATCH 284/361] Java: Set literals. --- java/ql/lib/semmle/code/java/UnitTests.qll | 11 +- .../ExcludeDebuggingProfilingLogging.qll | 15 +- .../lib/semmle/code/java/frameworks/JaxWS.qll | 25 +- .../semmle/code/java/frameworks/Protobuf.qll | 8 +- .../code/java/metrics/MetricRefType.qll | 6 +- .../code/java/security/RelativePaths.qll | 47 +- .../src/Compatibility/JDK9/JdkInternals.qll | 1506 ++++++----------- .../Magic Constants/MagicConstants.qll | 197 +-- 8 files changed, 530 insertions(+), 1285 deletions(-) diff --git a/java/ql/lib/semmle/code/java/UnitTests.qll b/java/ql/lib/semmle/code/java/UnitTests.qll index 1adc88d35f7..6dd6aa61fe6 100644 --- a/java/ql/lib/semmle/code/java/UnitTests.qll +++ b/java/ql/lib/semmle/code/java/UnitTests.qll @@ -38,11 +38,12 @@ class TearDownMethod extends Method { private class TestRelatedAnnotation extends Annotation { TestRelatedAnnotation() { - this.getType().getPackage().hasName("org.testng.annotations") or - this.getType().getPackage().hasName("org.junit") or - this.getType().getPackage().hasName("org.junit.runner") or - this.getType().getPackage().hasName("org.junit.jupiter.api") or - this.getType().getPackage().hasName("org.junit.jupiter.params") + this.getType() + .getPackage() + .hasName([ + "org.testng.annotations", "org.junit", "org.junit.runner", "org.junit.jupiter.api", + "org.junit.jupiter.params" + ]) } } diff --git a/java/ql/lib/semmle/code/java/controlflow/unreachableblocks/ExcludeDebuggingProfilingLogging.qll b/java/ql/lib/semmle/code/java/controlflow/unreachableblocks/ExcludeDebuggingProfilingLogging.qll index a9f75924c55..3494e813c74 100644 --- a/java/ql/lib/semmle/code/java/controlflow/unreachableblocks/ExcludeDebuggingProfilingLogging.qll +++ b/java/ql/lib/semmle/code/java/controlflow/unreachableblocks/ExcludeDebuggingProfilingLogging.qll @@ -17,16 +17,11 @@ import semmle.code.java.controlflow.UnreachableBlocks class ExcludeDebuggingProfilingLogging extends ExcludedConstantField { ExcludeDebuggingProfilingLogging() { exists(string validFieldName | - validFieldName = "debug" or - validFieldName = "profiling" or - validFieldName = "profile" or - validFieldName = "time" or - validFieldName = "verbose" or - validFieldName = "report" or - validFieldName = "dbg" or - validFieldName = "timing" or - validFieldName = "assert" or - validFieldName = "log" + validFieldName = + [ + "debug", "profiling", "profile", "time", "verbose", "report", "dbg", "timing", "assert", + "log" + ] | getName().regexpMatch(".*(?i)" + validFieldName + ".*") ) and diff --git a/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll b/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll index c3bd9531376..71bbf381fd0 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll @@ -25,9 +25,7 @@ string getAJaxRsPackage(string subpackage) { result = getAJaxRsPackage() + "." + class JaxWsEndpoint extends Class { JaxWsEndpoint() { exists(AnnotationType a | a = this.getAnAnnotation().getType() | - a.hasName("WebService") or - a.hasName("WebServiceProvider") or - a.hasName("WebServiceClient") + a.hasName(["WebService", "WebServiceProvider", "WebServiceClient"]) ) } @@ -35,8 +33,7 @@ class JaxWsEndpoint extends Class { Callable getARemoteMethod() { result = this.getACallable() and exists(AnnotationType a | a = result.getAnAnnotation().getType() | - a.hasName("WebMethod") or - a.hasName("WebEndpoint") + a.hasName(["WebMethod", "WebEndpoint"]) ) } } @@ -62,12 +59,7 @@ class JaxRsResourceMethod extends Method { a = this.getAnAnnotation().getType() and a.getPackage().getName() = getAJaxRsPackage() | - a.hasName("GET") or - a.hasName("POST") or - a.hasName("DELETE") or - a.hasName("PUT") or - a.hasName("OPTIONS") or - a.hasName("HEAD") + a.hasName(["GET", "POST", "DELETE", "PUT", "OPTIONS", "HEAD"]) ) or // A JaxRS resource method can also inherit these annotations from a supertype, but only if @@ -201,13 +193,10 @@ class JaxRsInjectionAnnotation extends JaxRSAnnotation { a = this.getType() and a.getPackage().getName() = getAJaxRsPackage() | - a.hasName("BeanParam") or - a.hasName("CookieParam") or - a.hasName("FormParam") or - a.hasName("HeaderParam") or - a.hasName("MatrixParam") or - a.hasName("PathParam") or - a.hasName("QueryParam") + a.hasName([ + "BeanParam", "CookieParam", "FormParam", "HeaderParam", "MatrixParam", "PathParam", + "QueryParam" + ]) ) or this.getType().hasQualifiedName(getAJaxRsPackage("core"), "Context") diff --git a/java/ql/lib/semmle/code/java/frameworks/Protobuf.qll b/java/ql/lib/semmle/code/java/frameworks/Protobuf.qll index 7382294f6f9..0a0dccbca3b 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Protobuf.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Protobuf.qll @@ -40,13 +40,7 @@ class ProtobufMessageLite extends Interface { */ Method getAGetterMethod() { exists(RefType decl | decl = result.getDeclaringType() and decl = this.getASubtype+() | - exists(string name, string suffix | - suffix = "" or - suffix = "list" or - suffix = "map" or - suffix = "ordefault" or - suffix = "orthrow" - | + exists(string name, string suffix | suffix = ["", "list", "map", "ordefault", "orthrow"] | exists(Field f | f.getDeclaringType() = decl | f.getName().toLowerCase().replaceAll("_", "") = name ) and diff --git a/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll b/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll index 79c65dd1bef..53643ff7082 100755 --- a/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll +++ b/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll @@ -264,11 +264,7 @@ class MetricRefType extends RefType, MetricElement { * for use with the specialization index metric. */ predicate ignoreOverride(Method c) { - c.hasStringSignature("equals(Object)") or - c.hasStringSignature("hashCode()") or - c.hasStringSignature("toString()") or - c.hasStringSignature("finalize()") or - c.hasStringSignature("clone()") + c.hasStringSignature(["equals(Object)", "hashCode()", "toString()", "finalize()", "clone()"]) } /** Gets a method that overrides a non-abstract method in a super type. */ diff --git a/java/ql/lib/semmle/code/java/security/RelativePaths.qll b/java/ql/lib/semmle/code/java/security/RelativePaths.qll index 34ffcc5bb04..22bcf7b7d87 100644 --- a/java/ql/lib/semmle/code/java/security/RelativePaths.qll +++ b/java/ql/lib/semmle/code/java/security/RelativePaths.qll @@ -7,10 +7,7 @@ import java predicate relativePath(Element tree, string command) { exists(StringLiteral lit, string text | tree = lit and text = lit.getRepresentedString() | text != "" and - ( - text.regexpMatch("[^/\\\\ \t]*") or - text.regexpMatch("[^/\\\\ \t]*[ \t].*") - ) and + text.regexpMatch(["[^/\\\\ \t]*", "[^/\\\\ \t]*[ \t].*"]) and command = text.replaceAll("\t", " ").splitAt(" ", 0).replaceAll("\"", "") ) or @@ -35,39 +32,11 @@ predicate arrayStartingWithRelative(Element tree, string command) { * because they do not correspond to files in the filesystem. */ predicate shellBuiltin(string command) { - command = "." or - command = "[" or - command = "[[" or - command = "alias" or - command = "builtin" or - command = "case" or - command = "command" or - command = "compgen" or - command = "complete" or - command = "compopt" or - command = "echo" or - command = "eval" or - command = "exec" or - command = "false" or - command = "fc" or - command = "for" or - command = "getopts" or - command = "help" or - command = "history" or - command = "if" or - command = "kill" or - command = "printf" or - command = "pwd" or - command = "select" or - command = "source" or - command = "test" or - command = "time" or - command = "times" or - command = "trap" or - command = "true" or - command = "type" or - command = "typeset" or - command = "ulimit" or - command = "until" or - command = "while" + command = + [ + ".", "[", "[[", "alias", "builtin", "case", "command", "compgen", "complete", "compopt", + "echo", "eval", "exec", "false", "fc", "for", "getopts", "help", "history", "if", "kill", + "printf", "pwd", "select", "source", "test", "time", "times", "trap", "true", "type", + "typeset", "ulimit", "until", "while" + ] } diff --git a/java/ql/src/Compatibility/JDK9/JdkInternals.qll b/java/ql/src/Compatibility/JDK9/JdkInternals.qll index 4cdda13a6a7..b74acd6f5e6 100644 --- a/java/ql/src/Compatibility/JDK9/JdkInternals.qll +++ b/java/ql/src/Compatibility/JDK9/JdkInternals.qll @@ -8,1032 +8,482 @@ * https://hg.openjdk.java.net/jdk9/jdk9/langtools/file/6ba2130e87bd/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdk8_internals.txt */ predicate jdkInternalApi(string p) { - p = "apple.applescript" or - p = "apple.laf" or - p = "apple.launcher" or - p = "apple.security" or - p = "com.apple.concurrent" or - p = "com.apple.eawt" or - p = "com.apple.eawt.event" or - p = "com.apple.eio" or - p = "com.apple.laf" or - p = "com.apple.laf.resources" or - p = "com.oracle.jrockit.jfr" or - p = "com.oracle.jrockit.jfr.client" or - p = "com.oracle.jrockit.jfr.management" or - p = "com.oracle.security.ucrypto" or - p = "com.oracle.util" or - p = "com.oracle.webservices.internal.api" or - p = "com.oracle.webservices.internal.api.databinding" or - p = "com.oracle.webservices.internal.api.message" or - p = "com.oracle.webservices.internal.impl.encoding" or - p = "com.oracle.webservices.internal.impl.internalspi.encoding" or - p = "com.oracle.xmlns.internal.webservices.jaxws_databinding" or - p = "com.sun.accessibility.internal.resources" or - p = "com.sun.activation.registries" or - p = "com.sun.awt" or - p = "com.sun.beans" or - p = "com.sun.beans.decoder" or - p = "com.sun.beans.editors" or - p = "com.sun.beans.finder" or - p = "com.sun.beans.infos" or - p = "com.sun.beans.util" or - p = "com.sun.codemodel.internal" or - p = "com.sun.codemodel.internal.fmt" or - p = "com.sun.codemodel.internal.util" or - p = "com.sun.codemodel.internal.writer" or - p = "com.sun.corba.se.impl.activation" or - p = "com.sun.corba.se.impl.copyobject" or - p = "com.sun.corba.se.impl.corba" or - p = "com.sun.corba.se.impl.dynamicany" or - p = "com.sun.corba.se.impl.encoding" or - p = "com.sun.corba.se.impl.interceptors" or - p = "com.sun.corba.se.impl.io" or - p = "com.sun.corba.se.impl.ior" or - p = "com.sun.corba.se.impl.ior.iiop" or - p = "com.sun.corba.se.impl.javax.rmi" or - p = "com.sun.corba.se.impl.javax.rmi.CORBA" or - p = "com.sun.corba.se.impl.legacy.connection" or - p = "com.sun.corba.se.impl.logging" or - p = "com.sun.corba.se.impl.monitoring" or - p = "com.sun.corba.se.impl.naming.cosnaming" or - p = "com.sun.corba.se.impl.naming.namingutil" or - p = "com.sun.corba.se.impl.naming.pcosnaming" or - p = "com.sun.corba.se.impl.oa" or - p = "com.sun.corba.se.impl.oa.poa" or - p = "com.sun.corba.se.impl.oa.toa" or - p = "com.sun.corba.se.impl.orb" or - p = "com.sun.corba.se.impl.orbutil" or - p = "com.sun.corba.se.impl.orbutil.closure" or - p = "com.sun.corba.se.impl.orbutil.concurrent" or - p = "com.sun.corba.se.impl.orbutil.fsm" or - p = "com.sun.corba.se.impl.orbutil.graph" or - p = "com.sun.corba.se.impl.orbutil.threadpool" or - p = "com.sun.corba.se.impl.presentation.rmi" or - p = "com.sun.corba.se.impl.protocol" or - p = "com.sun.corba.se.impl.protocol.giopmsgheaders" or - p = "com.sun.corba.se.impl.resolver" or - p = "com.sun.corba.se.impl.transport" or - p = "com.sun.corba.se.impl.util" or - p = "com.sun.corba.se.internal.CosNaming" or - p = "com.sun.corba.se.internal.Interceptors" or - p = "com.sun.corba.se.internal.POA" or - p = "com.sun.corba.se.internal.corba" or - p = "com.sun.corba.se.internal.iiop" or - p = "com.sun.corba.se.org.omg.CORBA" or - p = "com.sun.corba.se.pept.broker" or - p = "com.sun.corba.se.pept.encoding" or - p = "com.sun.corba.se.pept.protocol" or - p = "com.sun.corba.se.pept.transport" or - p = "com.sun.corba.se.spi.activation" or - p = "com.sun.corba.se.spi.activation.InitialNameServicePackage" or - p = "com.sun.corba.se.spi.activation.LocatorPackage" or - p = "com.sun.corba.se.spi.activation.RepositoryPackage" or - p = "com.sun.corba.se.spi.copyobject" or - p = "com.sun.corba.se.spi.encoding" or - p = "com.sun.corba.se.spi.extension" or - p = "com.sun.corba.se.spi.ior" or - p = "com.sun.corba.se.spi.ior.iiop" or - p = "com.sun.corba.se.spi.legacy.connection" or - p = "com.sun.corba.se.spi.legacy.interceptor" or - p = "com.sun.corba.se.spi.logging" or - p = "com.sun.corba.se.spi.monitoring" or - p = "com.sun.corba.se.spi.oa" or - p = "com.sun.corba.se.spi.orb" or - p = "com.sun.corba.se.spi.orbutil.closure" or - p = "com.sun.corba.se.spi.orbutil.fsm" or - p = "com.sun.corba.se.spi.orbutil.proxy" or - p = "com.sun.corba.se.spi.orbutil.threadpool" or - p = "com.sun.corba.se.spi.presentation.rmi" or - p = "com.sun.corba.se.spi.protocol" or - p = "com.sun.corba.se.spi.resolver" or - p = "com.sun.corba.se.spi.servicecontext" or - p = "com.sun.corba.se.spi.transport" or - p = "com.sun.crypto.provider" or - p = "com.sun.demo.jvmti.hprof" or - p = "com.sun.deploy.uitoolkit.impl.fx" or - p = "com.sun.deploy.uitoolkit.impl.fx.ui" or - p = "com.sun.deploy.uitoolkit.impl.fx.ui.resources" or - p = "com.sun.glass.events" or - p = "com.sun.glass.events.mac" or - p = "com.sun.glass.ui" or - p = "com.sun.glass.ui.delegate" or - p = "com.sun.glass.ui.gtk" or - p = "com.sun.glass.ui.mac" or - p = "com.sun.glass.ui.win" or - p = "com.sun.glass.utils" or - p = "com.sun.image.codec.jpeg" or - p = "com.sun.imageio.plugins.bmp" or - p = "com.sun.imageio.plugins.common" or - p = "com.sun.imageio.plugins.gif" or - p = "com.sun.imageio.plugins.jpeg" or - p = "com.sun.imageio.plugins.png" or - p = "com.sun.imageio.plugins.wbmp" or - p = "com.sun.imageio.spi" or - p = "com.sun.imageio.stream" or - p = "com.sun.istack.internal" or - p = "com.sun.istack.internal.localization" or - p = "com.sun.istack.internal.logging" or - p = "com.sun.istack.internal.tools" or - p = "com.sun.java.accessibility" or - p = "com.sun.java.accessibility.util.java.awt" or - p = "com.sun.java.browser.dom" or - p = "com.sun.java.browser.net" or - p = "com.sun.java.swing" or - p = "com.sun.java.swing.plaf.gtk" or - p = "com.sun.java.swing.plaf.gtk.resources" or - p = "com.sun.java.swing.plaf.motif" or - p = "com.sun.java.swing.plaf.motif.resources" or - p = "com.sun.java.swing.plaf.nimbus" or - p = "com.sun.java.swing.plaf.windows" or - p = "com.sun.java.swing.plaf.windows.resources" or - p = "com.sun.java.util.jar.pack" or - p = "com.sun.java_cup.internal.runtime" or - p = "com.sun.javafx" or - p = "com.sun.javafx.animation" or - p = "com.sun.javafx.applet" or - p = "com.sun.javafx.application" or - p = "com.sun.javafx.beans" or - p = "com.sun.javafx.beans.event" or - p = "com.sun.javafx.binding" or - p = "com.sun.javafx.charts" or - p = "com.sun.javafx.collections" or - p = "com.sun.javafx.css" or - p = "com.sun.javafx.css.converters" or - p = "com.sun.javafx.css.parser" or - p = "com.sun.javafx.cursor" or - p = "com.sun.javafx.effect" or - p = "com.sun.javafx.embed" or - p = "com.sun.javafx.event" or - p = "com.sun.javafx.font" or - p = "com.sun.javafx.font.coretext" or - p = "com.sun.javafx.font.directwrite" or - p = "com.sun.javafx.font.freetype" or - p = "com.sun.javafx.font.t2k" or - p = "com.sun.javafx.fxml" or - p = "com.sun.javafx.fxml.builder" or - p = "com.sun.javafx.fxml.expression" or - p = "com.sun.javafx.geom" or - p = "com.sun.javafx.geom.transform" or - p = "com.sun.javafx.geometry" or - p = "com.sun.javafx.iio" or - p = "com.sun.javafx.iio.bmp" or - p = "com.sun.javafx.iio.common" or - p = "com.sun.javafx.iio.gif" or - p = "com.sun.javafx.iio.ios" or - p = "com.sun.javafx.iio.jpeg" or - p = "com.sun.javafx.iio.png" or - p = "com.sun.javafx.image" or - p = "com.sun.javafx.image.impl" or - p = "com.sun.javafx.jmx" or - p = "com.sun.javafx.logging" or - p = "com.sun.javafx.media" or - p = "com.sun.javafx.menu" or - p = "com.sun.javafx.perf" or - p = "com.sun.javafx.print" or - p = "com.sun.javafx.property" or - p = "com.sun.javafx.property.adapter" or - p = "com.sun.javafx.robot" or - p = "com.sun.javafx.robot.impl" or - p = "com.sun.javafx.runtime" or - p = "com.sun.javafx.runtime.async" or - p = "com.sun.javafx.runtime.eula" or - p = "com.sun.javafx.scene" or - p = "com.sun.javafx.scene.control" or - p = "com.sun.javafx.scene.control.behavior" or - p = "com.sun.javafx.scene.control.skin" or - p = "com.sun.javafx.scene.control.skin.resources" or - p = "com.sun.javafx.scene.input" or - p = "com.sun.javafx.scene.layout.region" or - p = "com.sun.javafx.scene.paint" or - p = "com.sun.javafx.scene.shape" or - p = "com.sun.javafx.scene.text" or - p = "com.sun.javafx.scene.transform" or - p = "com.sun.javafx.scene.traversal" or - p = "com.sun.javafx.scene.web" or - p = "com.sun.javafx.scene.web.behavior" or - p = "com.sun.javafx.scene.web.skin" or - p = "com.sun.javafx.sg.prism" or - p = "com.sun.javafx.sg.prism.web" or - p = "com.sun.javafx.stage" or - p = "com.sun.javafx.text" or - p = "com.sun.javafx.tk" or - p = "com.sun.javafx.tk.quantum" or - p = "com.sun.javafx.util" or - p = "com.sun.javafx.webkit" or - p = "com.sun.javafx.webkit.drt" or - p = "com.sun.javafx.webkit.prism" or - p = "com.sun.javafx.webkit.prism.theme" or - p = "com.sun.javafx.webkit.theme" or - p = "com.sun.jmx.defaults" or - p = "com.sun.jmx.interceptor" or - p = "com.sun.jmx.mbeanserver" or - p = "com.sun.jmx.remote.internal" or - p = "com.sun.jmx.remote.protocol.iiop" or - p = "com.sun.jmx.remote.protocol.rmi" or - p = "com.sun.jmx.remote.security" or - p = "com.sun.jmx.remote.util" or - p = "com.sun.jmx.snmp" or - p = "com.sun.jmx.snmp.IPAcl" or - p = "com.sun.jmx.snmp.agent" or - p = "com.sun.jmx.snmp.daemon" or - p = "com.sun.jmx.snmp.defaults" or - p = "com.sun.jmx.snmp.internal" or - p = "com.sun.jmx.snmp.mpm" or - p = "com.sun.jmx.snmp.tasks" or - p = "com.sun.jndi.cosnaming" or - p = "com.sun.jndi.dns" or - p = "com.sun.jndi.ldap" or - p = "com.sun.jndi.ldap.ext" or - p = "com.sun.jndi.ldap.pool" or - p = "com.sun.jndi.ldap.sasl" or - p = "com.sun.jndi.rmi.registry" or - p = "com.sun.jndi.toolkit.corba" or - p = "com.sun.jndi.toolkit.ctx" or - p = "com.sun.jndi.toolkit.dir" or - p = "com.sun.jndi.toolkit.url" or - p = "com.sun.jndi.url.corbaname" or - p = "com.sun.jndi.url.dns" or - p = "com.sun.jndi.url.iiop" or - p = "com.sun.jndi.url.iiopname" or - p = "com.sun.jndi.url.ldap" or - p = "com.sun.jndi.url.ldaps" or - p = "com.sun.jndi.url.rmi" or - p = "com.sun.management.jmx" or - p = "com.sun.media.jfxmedia" or - p = "com.sun.media.jfxmedia.control" or - p = "com.sun.media.jfxmedia.effects" or - p = "com.sun.media.jfxmedia.events" or - p = "com.sun.media.jfxmedia.locator" or - p = "com.sun.media.jfxmedia.logging" or - p = "com.sun.media.jfxmedia.track" or - p = "com.sun.media.jfxmediaimpl" or - p = "com.sun.media.jfxmediaimpl.platform" or - p = "com.sun.media.jfxmediaimpl.platform.gstreamer" or - p = "com.sun.media.jfxmediaimpl.platform.ios" or - p = "com.sun.media.jfxmediaimpl.platform.java" or - p = "com.sun.media.jfxmediaimpl.platform.osx" or - p = "com.sun.media.sound" or - p = "com.sun.naming.internal" or - p = "com.sun.net.ssl" or - p = "com.sun.net.ssl.internal.ssl" or - p = "com.sun.net.ssl.internal.www.protocol.https" or - p = "com.sun.nio.file" or - p = "com.sun.nio.zipfs" or - p = "com.sun.openpisces" or - p = "com.sun.org.apache.bcel.internal" or - p = "com.sun.org.apache.bcel.internal.classfile" or - p = "com.sun.org.apache.bcel.internal.generic" or - p = "com.sun.org.apache.bcel.internal.util" or - p = "com.sun.org.apache.regexp.internal" or - p = "com.sun.org.apache.xalan.internal" or - p = "com.sun.org.apache.xalan.internal.extensions" or - p = "com.sun.org.apache.xalan.internal.lib" or - p = "com.sun.org.apache.xalan.internal.res" or - p = "com.sun.org.apache.xalan.internal.templates" or - p = "com.sun.org.apache.xalan.internal.utils" or - p = "com.sun.org.apache.xalan.internal.xslt" or - p = "com.sun.org.apache.xalan.internal.xsltc" or - p = "com.sun.org.apache.xalan.internal.xsltc.cmdline" or - p = "com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt" or - p = "com.sun.org.apache.xalan.internal.xsltc.compiler" or - p = "com.sun.org.apache.xalan.internal.xsltc.compiler.util" or - p = "com.sun.org.apache.xalan.internal.xsltc.dom" or - p = "com.sun.org.apache.xalan.internal.xsltc.runtime" or - p = "com.sun.org.apache.xalan.internal.xsltc.runtime.output" or - p = "com.sun.org.apache.xalan.internal.xsltc.trax" or - p = "com.sun.org.apache.xalan.internal.xsltc.util" or - p = "com.sun.org.apache.xerces.internal.dom" or - p = "com.sun.org.apache.xerces.internal.dom.events" or - p = "com.sun.org.apache.xerces.internal.impl" or - p = "com.sun.org.apache.xerces.internal.impl.dtd" or - p = "com.sun.org.apache.xerces.internal.impl.dtd.models" or - p = "com.sun.org.apache.xerces.internal.impl.dv" or - p = "com.sun.org.apache.xerces.internal.impl.dv.dtd" or - p = "com.sun.org.apache.xerces.internal.impl.dv.util" or - p = "com.sun.org.apache.xerces.internal.impl.dv.xs" or - p = "com.sun.org.apache.xerces.internal.impl.io" or - p = "com.sun.org.apache.xerces.internal.impl.msg" or - p = "com.sun.org.apache.xerces.internal.impl.validation" or - p = "com.sun.org.apache.xerces.internal.impl.xpath" or - p = "com.sun.org.apache.xerces.internal.impl.xpath.regex" or - p = "com.sun.org.apache.xerces.internal.impl.xs" or - p = "com.sun.org.apache.xerces.internal.impl.xs.identity" or - p = "com.sun.org.apache.xerces.internal.impl.xs.models" or - p = "com.sun.org.apache.xerces.internal.impl.xs.opti" or - p = "com.sun.org.apache.xerces.internal.impl.xs.traversers" or - p = "com.sun.org.apache.xerces.internal.impl.xs.util" or - p = "com.sun.org.apache.xerces.internal.jaxp" or - p = "com.sun.org.apache.xerces.internal.jaxp.datatype" or - p = "com.sun.org.apache.xerces.internal.jaxp.validation" or - p = "com.sun.org.apache.xerces.internal.parsers" or - p = "com.sun.org.apache.xerces.internal.util" or - p = "com.sun.org.apache.xerces.internal.utils" or - p = "com.sun.org.apache.xerces.internal.xinclude" or - p = "com.sun.org.apache.xerces.internal.xni" or - p = "com.sun.org.apache.xerces.internal.xni.grammars" or - p = "com.sun.org.apache.xerces.internal.xni.parser" or - p = "com.sun.org.apache.xerces.internal.xpointer" or - p = "com.sun.org.apache.xerces.internal.xs" or - p = "com.sun.org.apache.xerces.internal.xs.datatypes" or - p = "com.sun.org.apache.xml.internal.dtm" or - p = "com.sun.org.apache.xml.internal.dtm.ref" or - p = "com.sun.org.apache.xml.internal.dtm.ref.dom2dtm" or - p = "com.sun.org.apache.xml.internal.dtm.ref.sax2dtm" or - p = "com.sun.org.apache.xml.internal.res" or - p = "com.sun.org.apache.xml.internal.resolver" or - p = "com.sun.org.apache.xml.internal.resolver.helpers" or - p = "com.sun.org.apache.xml.internal.resolver.readers" or - p = "com.sun.org.apache.xml.internal.resolver.tools" or - p = "com.sun.org.apache.xml.internal.security" or - p = "com.sun.org.apache.xml.internal.security.algorithms" or - p = "com.sun.org.apache.xml.internal.security.algorithms.implementations" or - p = "com.sun.org.apache.xml.internal.security.c14n" or - p = "com.sun.org.apache.xml.internal.security.c14n.helper" or - p = "com.sun.org.apache.xml.internal.security.c14n.implementations" or - p = "com.sun.org.apache.xml.internal.security.encryption" or - p = "com.sun.org.apache.xml.internal.security.exceptions" or - p = "com.sun.org.apache.xml.internal.security.keys" or - p = "com.sun.org.apache.xml.internal.security.keys.content" or - p = "com.sun.org.apache.xml.internal.security.keys.content.keyvalues" or - p = "com.sun.org.apache.xml.internal.security.keys.content.x509" or - p = "com.sun.org.apache.xml.internal.security.keys.keyresolver" or - p = "com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations" or - p = "com.sun.org.apache.xml.internal.security.keys.storage" or - p = "com.sun.org.apache.xml.internal.security.keys.storage.implementations" or - p = "com.sun.org.apache.xml.internal.security.signature" or - p = "com.sun.org.apache.xml.internal.security.signature.reference" or - p = "com.sun.org.apache.xml.internal.security.transforms" or - p = "com.sun.org.apache.xml.internal.security.transforms.implementations" or - p = "com.sun.org.apache.xml.internal.security.transforms.params" or - p = "com.sun.org.apache.xml.internal.security.utils" or - p = "com.sun.org.apache.xml.internal.security.utils.resolver" or - p = "com.sun.org.apache.xml.internal.security.utils.resolver.implementations" or - p = "com.sun.org.apache.xml.internal.serialize" or - p = "com.sun.org.apache.xml.internal.serializer" or - p = "com.sun.org.apache.xml.internal.serializer.utils" or - p = "com.sun.org.apache.xml.internal.utils" or - p = "com.sun.org.apache.xml.internal.utils.res" or - p = "com.sun.org.apache.xpath.internal" or - p = "com.sun.org.apache.xpath.internal.axes" or - p = "com.sun.org.apache.xpath.internal.compiler" or - p = "com.sun.org.apache.xpath.internal.domapi" or - p = "com.sun.org.apache.xpath.internal.functions" or - p = "com.sun.org.apache.xpath.internal.jaxp" or - p = "com.sun.org.apache.xpath.internal.objects" or - p = "com.sun.org.apache.xpath.internal.operations" or - p = "com.sun.org.apache.xpath.internal.patterns" or - p = "com.sun.org.apache.xpath.internal.res" or - p = "com.sun.org.glassfish.external.amx" or - p = "com.sun.org.glassfish.external.arc" or - p = "com.sun.org.glassfish.external.probe.provider" or - p = "com.sun.org.glassfish.external.probe.provider.annotations" or - p = "com.sun.org.glassfish.external.statistics" or - p = "com.sun.org.glassfish.external.statistics.annotations" or - p = "com.sun.org.glassfish.external.statistics.impl" or - p = "com.sun.org.glassfish.gmbal" or - p = "com.sun.org.glassfish.gmbal.util" or - p = "com.sun.org.omg.CORBA" or - p = "com.sun.org.omg.CORBA.ValueDefPackage" or - p = "com.sun.org.omg.CORBA.portable" or - p = "com.sun.org.omg.SendingContext" or - p = "com.sun.org.omg.SendingContext.CodeBasePackage" or - p = "com.sun.pisces" or - p = "com.sun.prism" or - p = "com.sun.prism.d3d" or - p = "com.sun.prism.es2" or - p = "com.sun.prism.image" or - p = "com.sun.prism.impl" or - p = "com.sun.prism.impl.packrect" or - p = "com.sun.prism.impl.paint" or - p = "com.sun.prism.impl.ps" or - p = "com.sun.prism.impl.shape" or - p = "com.sun.prism.j2d" or - p = "com.sun.prism.j2d.paint" or - p = "com.sun.prism.j2d.print" or - p = "com.sun.prism.paint" or - p = "com.sun.prism.ps" or - p = "com.sun.prism.shader" or - p = "com.sun.prism.shape" or - p = "com.sun.prism.sw" or - p = "com.sun.rmi.rmid" or - p = "com.sun.rowset" or - p = "com.sun.rowset.internal" or - p = "com.sun.rowset.providers" or - p = "com.sun.scenario" or - p = "com.sun.scenario.animation" or - p = "com.sun.scenario.animation.shared" or - p = "com.sun.scenario.effect" or - p = "com.sun.scenario.effect.impl" or - p = "com.sun.scenario.effect.impl.es2" or - p = "com.sun.scenario.effect.impl.hw" or - p = "com.sun.scenario.effect.impl.hw.d3d" or - p = "com.sun.scenario.effect.impl.prism" or - p = "com.sun.scenario.effect.impl.prism.ps" or - p = "com.sun.scenario.effect.impl.prism.sw" or - p = "com.sun.scenario.effect.impl.state" or - p = "com.sun.scenario.effect.impl.sw" or - p = "com.sun.scenario.effect.impl.sw.java" or - p = "com.sun.scenario.effect.impl.sw.sse" or - p = "com.sun.scenario.effect.light" or - p = "com.sun.security.cert.internal.x509" or - p = "com.sun.security.ntlm" or - p = "com.sun.security.sasl" or - p = "com.sun.security.sasl.digest" or - p = "com.sun.security.sasl.gsskerb" or - p = "com.sun.security.sasl.ntlm" or - p = "com.sun.security.sasl.util" or - p = "com.sun.swing.internal.plaf.basic.resources" or - p = "com.sun.swing.internal.plaf.metal.resources" or - p = "com.sun.swing.internal.plaf.synth.resources" or - p = "com.sun.tools.classfile" or - p = "com.sun.tools.corba.se.idl" or - p = "com.sun.tools.corba.se.idl.constExpr" or - p = "com.sun.tools.corba.se.idl.som.cff" or - p = "com.sun.tools.corba.se.idl.som.idlemit" or - p = "com.sun.tools.corba.se.idl.toJavaPortable" or - p = "com.sun.tools.doclets.formats.html" or - p = "com.sun.tools.doclets.formats.html.markup" or - p = "com.sun.tools.doclets.formats.html.resources" or - p = "com.sun.tools.doclets.internal.toolkit" or - p = "com.sun.tools.doclets.internal.toolkit.builders" or - p = "com.sun.tools.doclets.internal.toolkit.resources" or - p = "com.sun.tools.doclets.internal.toolkit.taglets" or - p = "com.sun.tools.doclets.internal.toolkit.util" or - p = "com.sun.tools.doclets.internal.toolkit.util.links" or - p = "com.sun.tools.doclint" or - p = "com.sun.tools.doclint.resources" or - p = "com.sun.tools.example.debug.expr" or - p = "com.sun.tools.example.debug.tty" or - p = "com.sun.tools.extcheck" or - p = "com.sun.tools.hat" or - p = "com.sun.tools.hat.internal.model" or - p = "com.sun.tools.hat.internal.oql" or - p = "com.sun.tools.hat.internal.parser" or - p = "com.sun.tools.hat.internal.server" or - p = "com.sun.tools.hat.internal.util" or - p = "com.sun.tools.internal.jxc" or - p = "com.sun.tools.internal.jxc.ap" or - p = "com.sun.tools.internal.jxc.api" or - p = "com.sun.tools.internal.jxc.api.impl.j2s" or - p = "com.sun.tools.internal.jxc.gen.config" or - p = "com.sun.tools.internal.jxc.model.nav" or - p = "com.sun.tools.internal.ws" or - p = "com.sun.tools.internal.ws.api" or - p = "com.sun.tools.internal.ws.api.wsdl" or - p = "com.sun.tools.internal.ws.processor" or - p = "com.sun.tools.internal.ws.processor.generator" or - p = "com.sun.tools.internal.ws.processor.model" or - p = "com.sun.tools.internal.ws.processor.model.exporter" or - p = "com.sun.tools.internal.ws.processor.model.java" or - p = "com.sun.tools.internal.ws.processor.model.jaxb" or - p = "com.sun.tools.internal.ws.processor.modeler" or - p = "com.sun.tools.internal.ws.processor.modeler.annotation" or - p = "com.sun.tools.internal.ws.processor.modeler.wsdl" or - p = "com.sun.tools.internal.ws.processor.util" or - p = "com.sun.tools.internal.ws.resources" or - p = "com.sun.tools.internal.ws.spi" or - p = "com.sun.tools.internal.ws.util" or - p = "com.sun.tools.internal.ws.util.xml" or - p = "com.sun.tools.internal.ws.wscompile" or - p = "com.sun.tools.internal.ws.wscompile.plugin.at_generated" or - p = "com.sun.tools.internal.ws.wsdl.document" or - p = "com.sun.tools.internal.ws.wsdl.document.http" or - p = "com.sun.tools.internal.ws.wsdl.document.jaxws" or - p = "com.sun.tools.internal.ws.wsdl.document.mime" or - p = "com.sun.tools.internal.ws.wsdl.document.schema" or - p = "com.sun.tools.internal.ws.wsdl.document.soap" or - p = "com.sun.tools.internal.ws.wsdl.framework" or - p = "com.sun.tools.internal.ws.wsdl.parser" or - p = "com.sun.tools.internal.xjc" or - p = "com.sun.tools.internal.xjc.addon.accessors" or - p = "com.sun.tools.internal.xjc.addon.at_generated" or - p = "com.sun.tools.internal.xjc.addon.code_injector" or - p = "com.sun.tools.internal.xjc.addon.episode" or - p = "com.sun.tools.internal.xjc.addon.locator" or - p = "com.sun.tools.internal.xjc.addon.sync" or - p = "com.sun.tools.internal.xjc.api" or - p = "com.sun.tools.internal.xjc.api.impl.s2j" or - p = "com.sun.tools.internal.xjc.api.util" or - p = "com.sun.tools.internal.xjc.generator.annotation.spec" or - p = "com.sun.tools.internal.xjc.generator.bean" or - p = "com.sun.tools.internal.xjc.generator.bean.field" or - p = "com.sun.tools.internal.xjc.generator.util" or - p = "com.sun.tools.internal.xjc.model" or - p = "com.sun.tools.internal.xjc.model.nav" or - p = "com.sun.tools.internal.xjc.outline" or - p = "com.sun.tools.internal.xjc.reader" or - p = "com.sun.tools.internal.xjc.reader.dtd" or - p = "com.sun.tools.internal.xjc.reader.dtd.bindinfo" or - p = "com.sun.tools.internal.xjc.reader.gbind" or - p = "com.sun.tools.internal.xjc.reader.internalizer" or - p = "com.sun.tools.internal.xjc.reader.relaxng" or - p = "com.sun.tools.internal.xjc.reader.xmlschema" or - p = "com.sun.tools.internal.xjc.reader.xmlschema.bindinfo" or - p = "com.sun.tools.internal.xjc.reader.xmlschema.ct" or - p = "com.sun.tools.internal.xjc.reader.xmlschema.parser" or - p = "com.sun.tools.internal.xjc.runtime" or - p = "com.sun.tools.internal.xjc.util" or - p = "com.sun.tools.internal.xjc.writer" or - p = "com.sun.tools.javac.api" or - p = "com.sun.tools.javac.code" or - p = "com.sun.tools.javac.comp" or - p = "com.sun.tools.javac.file" or - p = "com.sun.tools.javac.jvm" or - p = "com.sun.tools.javac.main" or - p = "com.sun.tools.javac.model" or - p = "com.sun.tools.javac.nio" or - p = "com.sun.tools.javac.parser" or - p = "com.sun.tools.javac.processing" or - p = "com.sun.tools.javac.resources" or - p = "com.sun.tools.javac.sym" or - p = "com.sun.tools.javac.tree" or - p = "com.sun.tools.javac.util" or - p = "com.sun.tools.javadoc.api" or - p = "com.sun.tools.javadoc.resources" or - p = "com.sun.tools.javah" or - p = "com.sun.tools.javah.resources" or - p = "com.sun.tools.javap" or - p = "com.sun.tools.javap.resources" or - p = "com.sun.tools.jdeps" or - p = "com.sun.tools.jdeps.resources" or - p = "com.sun.tools.jdi" or - p = "com.sun.tools.jdi.resources" or - p = "com.sun.tools.script.shell" or - p = "com.sun.tracing" or - p = "com.sun.tracing.dtrace" or - p = "com.sun.webkit" or - p = "com.sun.webkit.dom" or - p = "com.sun.webkit.event" or - p = "com.sun.webkit.graphics" or - p = "com.sun.webkit.network" or - p = "com.sun.webkit.network.about" or - p = "com.sun.webkit.network.data" or - p = "com.sun.webkit.perf" or - p = "com.sun.webkit.plugin" or - p = "com.sun.webkit.text" or - p = "com.sun.xml.internal.bind" or - p = "com.sun.xml.internal.bind.annotation" or - p = "com.sun.xml.internal.bind.api" or - p = "com.sun.xml.internal.bind.api.impl" or - p = "com.sun.xml.internal.bind.marshaller" or - p = "com.sun.xml.internal.bind.unmarshaller" or - p = "com.sun.xml.internal.bind.util" or - p = "com.sun.xml.internal.bind.v2" or - p = "com.sun.xml.internal.bind.v2.bytecode" or - p = "com.sun.xml.internal.bind.v2.model.annotation" or - p = "com.sun.xml.internal.bind.v2.model.core" or - p = "com.sun.xml.internal.bind.v2.model.impl" or - p = "com.sun.xml.internal.bind.v2.model.nav" or - p = "com.sun.xml.internal.bind.v2.model.runtime" or - p = "com.sun.xml.internal.bind.v2.model.util" or - p = "com.sun.xml.internal.bind.v2.runtime" or - p = "com.sun.xml.internal.bind.v2.runtime.output" or - p = "com.sun.xml.internal.bind.v2.runtime.property" or - p = "com.sun.xml.internal.bind.v2.runtime.reflect" or - p = "com.sun.xml.internal.bind.v2.runtime.reflect.opt" or - p = "com.sun.xml.internal.bind.v2.runtime.unmarshaller" or - p = "com.sun.xml.internal.bind.v2.schemagen" or - p = "com.sun.xml.internal.bind.v2.schemagen.episode" or - p = "com.sun.xml.internal.bind.v2.schemagen.xmlschema" or - p = "com.sun.xml.internal.bind.v2.util" or - p = "com.sun.xml.internal.dtdparser" or - p = "com.sun.xml.internal.fastinfoset" or - p = "com.sun.xml.internal.fastinfoset.algorithm" or - p = "com.sun.xml.internal.fastinfoset.alphabet" or - p = "com.sun.xml.internal.fastinfoset.dom" or - p = "com.sun.xml.internal.fastinfoset.org.apache.xerces.util" or - p = "com.sun.xml.internal.fastinfoset.sax" or - p = "com.sun.xml.internal.fastinfoset.stax" or - p = "com.sun.xml.internal.fastinfoset.stax.events" or - p = "com.sun.xml.internal.fastinfoset.stax.factory" or - p = "com.sun.xml.internal.fastinfoset.stax.util" or - p = "com.sun.xml.internal.fastinfoset.tools" or - p = "com.sun.xml.internal.fastinfoset.util" or - p = "com.sun.xml.internal.fastinfoset.vocab" or - p = "com.sun.xml.internal.messaging.saaj" or - p = "com.sun.xml.internal.messaging.saaj.client.p2p" or - p = "com.sun.xml.internal.messaging.saaj.packaging.mime" or - p = "com.sun.xml.internal.messaging.saaj.packaging.mime.internet" or - p = "com.sun.xml.internal.messaging.saaj.packaging.mime.util" or - p = "com.sun.xml.internal.messaging.saaj.soap" or - p = "com.sun.xml.internal.messaging.saaj.soap.dynamic" or - p = "com.sun.xml.internal.messaging.saaj.soap.impl" or - p = "com.sun.xml.internal.messaging.saaj.soap.name" or - p = "com.sun.xml.internal.messaging.saaj.soap.ver1_1" or - p = "com.sun.xml.internal.messaging.saaj.soap.ver1_2" or - p = "com.sun.xml.internal.messaging.saaj.util" or - p = "com.sun.xml.internal.messaging.saaj.util.transform" or - p = "com.sun.xml.internal.org.jvnet.fastinfoset" or - p = "com.sun.xml.internal.org.jvnet.fastinfoset.sax" or - p = "com.sun.xml.internal.org.jvnet.fastinfoset.sax.helpers" or - p = "com.sun.xml.internal.org.jvnet.fastinfoset.stax" or - p = "com.sun.xml.internal.org.jvnet.mimepull" or - p = "com.sun.xml.internal.org.jvnet.staxex" or - p = "com.sun.xml.internal.rngom.ast.builder" or - p = "com.sun.xml.internal.rngom.ast.om" or - p = "com.sun.xml.internal.rngom.ast.util" or - p = "com.sun.xml.internal.rngom.binary" or - p = "com.sun.xml.internal.rngom.binary.visitor" or - p = "com.sun.xml.internal.rngom.digested" or - p = "com.sun.xml.internal.rngom.dt" or - p = "com.sun.xml.internal.rngom.dt.builtin" or - p = "com.sun.xml.internal.rngom.nc" or - p = "com.sun.xml.internal.rngom.parse" or - p = "com.sun.xml.internal.rngom.parse.compact" or - p = "com.sun.xml.internal.rngom.parse.host" or - p = "com.sun.xml.internal.rngom.parse.xml" or - p = "com.sun.xml.internal.rngom.util" or - p = "com.sun.xml.internal.rngom.xml.sax" or - p = "com.sun.xml.internal.rngom.xml.util" or - p = "com.sun.xml.internal.stream" or - p = "com.sun.xml.internal.stream.buffer" or - p = "com.sun.xml.internal.stream.buffer.sax" or - p = "com.sun.xml.internal.stream.buffer.stax" or - p = "com.sun.xml.internal.stream.dtd" or - p = "com.sun.xml.internal.stream.dtd.nonvalidating" or - p = "com.sun.xml.internal.stream.events" or - p = "com.sun.xml.internal.stream.util" or - p = "com.sun.xml.internal.stream.writers" or - p = "com.sun.xml.internal.txw2" or - p = "com.sun.xml.internal.txw2.annotation" or - p = "com.sun.xml.internal.txw2.output" or - p = "com.sun.xml.internal.ws" or - p = "com.sun.xml.internal.ws.addressing" or - p = "com.sun.xml.internal.ws.addressing.model" or - p = "com.sun.xml.internal.ws.addressing.policy" or - p = "com.sun.xml.internal.ws.addressing.v200408" or - p = "com.sun.xml.internal.ws.api" or - p = "com.sun.xml.internal.ws.api.addressing" or - p = "com.sun.xml.internal.ws.api.client" or - p = "com.sun.xml.internal.ws.api.config.management" or - p = "com.sun.xml.internal.ws.api.config.management.policy" or - p = "com.sun.xml.internal.ws.api.databinding" or - p = "com.sun.xml.internal.ws.api.fastinfoset" or - p = "com.sun.xml.internal.ws.api.ha" or - p = "com.sun.xml.internal.ws.api.handler" or - p = "com.sun.xml.internal.ws.api.message" or - p = "com.sun.xml.internal.ws.api.message.saaj" or - p = "com.sun.xml.internal.ws.api.message.stream" or - p = "com.sun.xml.internal.ws.api.model" or - p = "com.sun.xml.internal.ws.api.model.soap" or - p = "com.sun.xml.internal.ws.api.model.wsdl" or - p = "com.sun.xml.internal.ws.api.model.wsdl.editable" or - p = "com.sun.xml.internal.ws.api.pipe" or - p = "com.sun.xml.internal.ws.api.pipe.helper" or - p = "com.sun.xml.internal.ws.api.policy" or - p = "com.sun.xml.internal.ws.api.policy.subject" or - p = "com.sun.xml.internal.ws.api.server" or - p = "com.sun.xml.internal.ws.api.streaming" or - p = "com.sun.xml.internal.ws.api.wsdl.parser" or - p = "com.sun.xml.internal.ws.api.wsdl.writer" or - p = "com.sun.xml.internal.ws.assembler" or - p = "com.sun.xml.internal.ws.assembler.dev" or - p = "com.sun.xml.internal.ws.assembler.jaxws" or - p = "com.sun.xml.internal.ws.binding" or - p = "com.sun.xml.internal.ws.client" or - p = "com.sun.xml.internal.ws.client.dispatch" or - p = "com.sun.xml.internal.ws.client.sei" or - p = "com.sun.xml.internal.ws.commons.xmlutil" or - p = "com.sun.xml.internal.ws.config.management.policy" or - p = "com.sun.xml.internal.ws.config.metro.dev" or - p = "com.sun.xml.internal.ws.config.metro.util" or - p = "com.sun.xml.internal.ws.db" or - p = "com.sun.xml.internal.ws.db.glassfish" or - p = "com.sun.xml.internal.ws.developer" or - p = "com.sun.xml.internal.ws.dump" or - p = "com.sun.xml.internal.ws.encoding" or - p = "com.sun.xml.internal.ws.encoding.fastinfoset" or - p = "com.sun.xml.internal.ws.encoding.policy" or - p = "com.sun.xml.internal.ws.encoding.soap" or - p = "com.sun.xml.internal.ws.encoding.soap.streaming" or - p = "com.sun.xml.internal.ws.encoding.xml" or - p = "com.sun.xml.internal.ws.fault" or - p = "com.sun.xml.internal.ws.handler" or - p = "com.sun.xml.internal.ws.message" or - p = "com.sun.xml.internal.ws.message.jaxb" or - p = "com.sun.xml.internal.ws.message.saaj" or - p = "com.sun.xml.internal.ws.message.source" or - p = "com.sun.xml.internal.ws.message.stream" or - p = "com.sun.xml.internal.ws.model" or - p = "com.sun.xml.internal.ws.model.soap" or - p = "com.sun.xml.internal.ws.model.wsdl" or - p = "com.sun.xml.internal.ws.org.objectweb.asm" or - p = "com.sun.xml.internal.ws.policy" or - p = "com.sun.xml.internal.ws.policy.jaxws" or - p = "com.sun.xml.internal.ws.policy.jaxws.spi" or - p = "com.sun.xml.internal.ws.policy.privateutil" or - p = "com.sun.xml.internal.ws.policy.sourcemodel" or - p = "com.sun.xml.internal.ws.policy.sourcemodel.attach" or - p = "com.sun.xml.internal.ws.policy.sourcemodel.wspolicy" or - p = "com.sun.xml.internal.ws.policy.spi" or - p = "com.sun.xml.internal.ws.policy.subject" or - p = "com.sun.xml.internal.ws.protocol.soap" or - p = "com.sun.xml.internal.ws.protocol.xml" or - p = "com.sun.xml.internal.ws.resources" or - p = "com.sun.xml.internal.ws.runtime.config" or - p = "com.sun.xml.internal.ws.server" or - p = "com.sun.xml.internal.ws.server.provider" or - p = "com.sun.xml.internal.ws.server.sei" or - p = "com.sun.xml.internal.ws.spi" or - p = "com.sun.xml.internal.ws.spi.db" or - p = "com.sun.xml.internal.ws.streaming" or - p = "com.sun.xml.internal.ws.transport" or - p = "com.sun.xml.internal.ws.transport.http" or - p = "com.sun.xml.internal.ws.transport.http.client" or - p = "com.sun.xml.internal.ws.transport.http.server" or - p = "com.sun.xml.internal.ws.util" or - p = "com.sun.xml.internal.ws.util.exception" or - p = "com.sun.xml.internal.ws.util.pipe" or - p = "com.sun.xml.internal.ws.util.xml" or - p = "com.sun.xml.internal.ws.wsdl" or - p = "com.sun.xml.internal.ws.wsdl.parser" or - p = "com.sun.xml.internal.ws.wsdl.writer" or - p = "com.sun.xml.internal.ws.wsdl.writer.document" or - p = "com.sun.xml.internal.ws.wsdl.writer.document.http" or - p = "com.sun.xml.internal.ws.wsdl.writer.document.soap" or - p = "com.sun.xml.internal.ws.wsdl.writer.document.soap12" or - p = "com.sun.xml.internal.ws.wsdl.writer.document.xsd" or - p = "com.sun.xml.internal.xsom" or - p = "com.sun.xml.internal.xsom.impl" or - p = "com.sun.xml.internal.xsom.impl.parser" or - p = "com.sun.xml.internal.xsom.impl.parser.state" or - p = "com.sun.xml.internal.xsom.impl.scd" or - p = "com.sun.xml.internal.xsom.impl.util" or - p = "com.sun.xml.internal.xsom.parser" or - p = "com.sun.xml.internal.xsom.util" or - p = "com.sun.xml.internal.xsom.visitor" or - p = "java.awt.dnd.peer" or - p = "java.awt.peer" or - p = "javafx.embed.swt" or - p = "jdk" or - p = "jdk.internal.cmm" or - p = "jdk.internal.dynalink" or - p = "jdk.internal.dynalink.beans" or - p = "jdk.internal.dynalink.linker" or - p = "jdk.internal.dynalink.support" or - p = "jdk.internal.instrumentation" or - p = "jdk.internal.org.objectweb.asm" or - p = "jdk.internal.org.objectweb.asm.commons" or - p = "jdk.internal.org.objectweb.asm.signature" or - p = "jdk.internal.org.objectweb.asm.tree" or - p = "jdk.internal.org.objectweb.asm.tree.analysis" or - p = "jdk.internal.org.objectweb.asm.util" or - p = "jdk.internal.org.xml.sax" or - p = "jdk.internal.org.xml.sax.helpers" or - p = "jdk.internal.util.xml" or - p = "jdk.internal.util.xml.impl" or - p = "jdk.jfr.events" or - p = "jdk.management.resource.internal" or - p = "jdk.management.resource.internal.inst" or - p = "jdk.nashorn.internal" or - p = "jdk.nashorn.internal.codegen" or - p = "jdk.nashorn.internal.codegen.types" or - p = "jdk.nashorn.internal.ir" or - p = "jdk.nashorn.internal.ir.annotations" or - p = "jdk.nashorn.internal.ir.debug" or - p = "jdk.nashorn.internal.ir.visitor" or - p = "jdk.nashorn.internal.lookup" or - p = "jdk.nashorn.internal.objects" or - p = "jdk.nashorn.internal.objects.annotations" or - p = "jdk.nashorn.internal.parser" or - p = "jdk.nashorn.internal.runtime" or - p = "jdk.nashorn.internal.runtime.arrays" or - p = "jdk.nashorn.internal.runtime.events" or - p = "jdk.nashorn.internal.runtime.linker" or - p = "jdk.nashorn.internal.runtime.logging" or - p = "jdk.nashorn.internal.runtime.options" or - p = "jdk.nashorn.internal.runtime.regexp" or - p = "jdk.nashorn.internal.runtime.regexp.joni" or - p = "jdk.nashorn.internal.runtime.regexp.joni.ast" or - p = "jdk.nashorn.internal.runtime.regexp.joni.constants" or - p = "jdk.nashorn.internal.runtime.regexp.joni.encoding" or - p = "jdk.nashorn.internal.runtime.regexp.joni.exception" or - p = "jdk.nashorn.internal.scripts" or - p = "jdk.nashorn.tools" or - p = "oracle.jrockit.jfr" or - p = "oracle.jrockit.jfr.events" or - p = "oracle.jrockit.jfr.jdkevents" or - p = "oracle.jrockit.jfr.jdkevents.throwabletransform" or - p = "oracle.jrockit.jfr.openmbean" or - p = "oracle.jrockit.jfr.parser" or - p = "oracle.jrockit.jfr.settings" or - p = "oracle.jrockit.jfr.tools" or - p = "org.jcp.xml.dsig.internal" or - p = "org.jcp.xml.dsig.internal.dom" or - p = "org.omg.stub.javax.management.remote.rmi" or - p = "org.relaxng.datatype" or - p = "org.relaxng.datatype.helpers" or - p = "sun.applet" or - p = "sun.applet.resources" or - p = "sun.audio" or - p = "sun.awt" or - p = "sun.awt.X11" or - p = "sun.awt.datatransfer" or - p = "sun.awt.dnd" or - p = "sun.awt.event" or - p = "sun.awt.geom" or - p = "sun.awt.im" or - p = "sun.awt.image" or - p = "sun.awt.image.codec" or - p = "sun.awt.motif" or - p = "sun.awt.resources" or - p = "sun.awt.shell" or - p = "sun.awt.util" or - p = "sun.awt.windows" or - p = "sun.corba" or - p = "sun.dc" or - p = "sun.dc.path" or - p = "sun.dc.pr" or - p = "sun.font" or - p = "sun.instrument" or - p = "sun.invoke" or - p = "sun.invoke.anon" or - p = "sun.invoke.empty" or - p = "sun.invoke.util" or - p = "sun.io" or - p = "sun.java2d" or - p = "sun.java2d.cmm" or - p = "sun.java2d.cmm.kcms" or - p = "sun.java2d.cmm.lcms" or - p = "sun.java2d.d3d" or - p = "sun.java2d.jules" or - p = "sun.java2d.loops" or - p = "sun.java2d.opengl" or - p = "sun.java2d.pipe" or - p = "sun.java2d.pipe.hw" or - p = "sun.java2d.pisces" or - p = "sun.java2d.windows" or - p = "sun.java2d.x11" or - p = "sun.java2d.xr" or - p = "sun.jvmstat.monitor" or - p = "sun.jvmstat.monitor.event" or - p = "sun.jvmstat.monitor.remote" or - p = "sun.jvmstat.perfdata.monitor" or - p = "sun.jvmstat.perfdata.monitor.protocol.file" or - p = "sun.jvmstat.perfdata.monitor.protocol.local" or - p = "sun.jvmstat.perfdata.monitor.protocol.rmi" or - p = "sun.jvmstat.perfdata.monitor.v1_0" or - p = "sun.jvmstat.perfdata.monitor.v2_0" or - p = "sun.launcher" or - p = "sun.launcher.resources" or - p = "sun.lwawt" or - p = "sun.lwawt.macosx" or - p = "sun.management" or - p = "sun.management.counter" or - p = "sun.management.counter.perf" or - p = "sun.management.jdp" or - p = "sun.management.jmxremote" or - p = "sun.management.resources" or - p = "sun.management.snmp" or - p = "sun.management.snmp.jvminstr" or - p = "sun.management.snmp.jvmmib" or - p = "sun.management.snmp.util" or - p = "sun.misc" or - p = "sun.misc.resources" or - p = "sun.net" or - p = "sun.net.dns" or - p = "sun.net.ftp" or - p = "sun.net.ftp.impl" or - p = "sun.net.httpserver" or - p = "sun.net.idn" or - p = "sun.net.sdp" or - p = "sun.net.smtp" or - p = "sun.net.spi" or - p = "sun.net.spi.nameservice" or - p = "sun.net.spi.nameservice.dns" or - p = "sun.net.util" or - p = "sun.net.www" or - p = "sun.net.www.content.audio" or - p = "sun.net.www.content.image" or - p = "sun.net.www.content.text" or - p = "sun.net.www.http" or - p = "sun.net.www.protocol.file" or - p = "sun.net.www.protocol.ftp" or - p = "sun.net.www.protocol.http" or - p = "sun.net.www.protocol.http.logging" or - p = "sun.net.www.protocol.http.ntlm" or - p = "sun.net.www.protocol.http.spnego" or - p = "sun.net.www.protocol.https" or - p = "sun.net.www.protocol.jar" or - p = "sun.net.www.protocol.mailto" or - p = "sun.net.www.protocol.netdoc" or - p = "sun.nio" or - p = "sun.nio.ch" or - p = "sun.nio.ch.sctp" or - p = "sun.nio.cs" or - p = "sun.nio.cs.ext" or - p = "sun.nio.fs" or - p = "sun.print" or - p = "sun.print.resources" or - p = "sun.reflect" or - p = "sun.reflect.annotation" or - p = "sun.reflect.generics.factory" or - p = "sun.reflect.generics.parser" or - p = "sun.reflect.generics.reflectiveObjects" or - p = "sun.reflect.generics.repository" or - p = "sun.reflect.generics.scope" or - p = "sun.reflect.generics.tree" or - p = "sun.reflect.generics.visitor" or - p = "sun.reflect.misc" or - p = "sun.rmi.log" or - p = "sun.rmi.registry" or - p = "sun.rmi.rmic" or - p = "sun.rmi.rmic.iiop" or - p = "sun.rmi.rmic.newrmic" or - p = "sun.rmi.rmic.newrmic.jrmp" or - p = "sun.rmi.runtime" or - p = "sun.rmi.server" or - p = "sun.rmi.transport" or - p = "sun.rmi.transport.proxy" or - p = "sun.rmi.transport.tcp" or - p = "sun.security.acl" or - p = "sun.security.action" or - p = "sun.security.ec" or - p = "sun.security.internal.interfaces" or - p = "sun.security.internal.spec" or - p = "sun.security.jca" or - p = "sun.security.jgss" or - p = "sun.security.jgss.krb5" or - p = "sun.security.jgss.spi" or - p = "sun.security.jgss.spnego" or - p = "sun.security.jgss.wrapper" or - p = "sun.security.krb5" or - p = "sun.security.krb5.internal" or - p = "sun.security.krb5.internal.ccache" or - p = "sun.security.krb5.internal.crypto" or - p = "sun.security.krb5.internal.crypto.dk" or - p = "sun.security.krb5.internal.ktab" or - p = "sun.security.krb5.internal.rcache" or - p = "sun.security.krb5.internal.tools" or - p = "sun.security.krb5.internal.util" or - p = "sun.security.mscapi" or - p = "sun.security.pkcs" or - p = "sun.security.pkcs10" or - p = "sun.security.pkcs11" or - p = "sun.security.pkcs11.wrapper" or - p = "sun.security.pkcs12" or - p = "sun.security.provider" or - p = "sun.security.provider.certpath" or - p = "sun.security.provider.certpath.ldap" or - p = "sun.security.provider.certpath.ssl" or - p = "sun.security.rsa" or - p = "sun.security.smartcardio" or - p = "sun.security.ssl" or - p = "sun.security.ssl.krb5" or - p = "sun.security.timestamp" or - p = "sun.security.tools" or - p = "sun.security.tools.jarsigner" or - p = "sun.security.tools.keytool" or - p = "sun.security.tools.policytool" or - p = "sun.security.util" or - p = "sun.security.validator" or - p = "sun.security.x509" or - p = "sun.swing" or - p = "sun.swing.icon" or - p = "sun.swing.plaf" or - p = "sun.swing.plaf.synth" or - p = "sun.swing.plaf.windows" or - p = "sun.swing.table" or - p = "sun.swing.text" or - p = "sun.swing.text.html" or - p = "sun.text" or - p = "sun.text.bidi" or - p = "sun.text.normalizer" or - p = "sun.text.resources" or - p = "sun.text.resources.en" or - p = "sun.tools.asm" or - p = "sun.tools.attach" or - p = "sun.tools.jar" or - p = "sun.tools.jar.resources" or - p = "sun.tools.java" or - p = "sun.tools.javac" or - p = "sun.tools.jcmd" or - p = "sun.tools.jconsole" or - p = "sun.tools.jconsole.inspector" or - p = "sun.tools.jinfo" or - p = "sun.tools.jmap" or - p = "sun.tools.jps" or - p = "sun.tools.jstack" or - p = "sun.tools.jstat" or - p = "sun.tools.jstatd" or - p = "sun.tools.native2ascii" or - p = "sun.tools.native2ascii.resources" or - p = "sun.tools.serialver" or - p = "sun.tools.tree" or - p = "sun.tools.util" or - p = "sun.tracing" or - p = "sun.tracing.dtrace" or - p = "sun.usagetracker" or - p = "sun.util" or - p = "sun.util.calendar" or - p = "sun.util.cldr" or - p = "sun.util.locale" or - p = "sun.util.locale.provider" or - p = "sun.util.logging" or - p = "sun.util.logging.resources" or - p = "sun.util.resources" or - p = "sun.util.resources.en" or - p = "sun.util.spi" or - p = "sun.util.xml" + p = + [ + "apple.applescript", "apple.laf", "apple.launcher", "apple.security", "com.apple.concurrent", + "com.apple.eawt", "com.apple.eawt.event", "com.apple.eio", "com.apple.laf", + "com.apple.laf.resources", "com.oracle.jrockit.jfr", "com.oracle.jrockit.jfr.client", + "com.oracle.jrockit.jfr.management", "com.oracle.security.ucrypto", "com.oracle.util", + "com.oracle.webservices.internal.api", "com.oracle.webservices.internal.api.databinding", + "com.oracle.webservices.internal.api.message", + "com.oracle.webservices.internal.impl.encoding", + "com.oracle.webservices.internal.impl.internalspi.encoding", + "com.oracle.xmlns.internal.webservices.jaxws_databinding", + "com.sun.accessibility.internal.resources", "com.sun.activation.registries", "com.sun.awt", + "com.sun.beans", "com.sun.beans.decoder", "com.sun.beans.editors", "com.sun.beans.finder", + "com.sun.beans.infos", "com.sun.beans.util", "com.sun.codemodel.internal", + "com.sun.codemodel.internal.fmt", "com.sun.codemodel.internal.util", + "com.sun.codemodel.internal.writer", "com.sun.corba.se.impl.activation", + "com.sun.corba.se.impl.copyobject", "com.sun.corba.se.impl.corba", + "com.sun.corba.se.impl.dynamicany", "com.sun.corba.se.impl.encoding", + "com.sun.corba.se.impl.interceptors", "com.sun.corba.se.impl.io", "com.sun.corba.se.impl.ior", + "com.sun.corba.se.impl.ior.iiop", "com.sun.corba.se.impl.javax.rmi", + "com.sun.corba.se.impl.javax.rmi.CORBA", "com.sun.corba.se.impl.legacy.connection", + "com.sun.corba.se.impl.logging", "com.sun.corba.se.impl.monitoring", + "com.sun.corba.se.impl.naming.cosnaming", "com.sun.corba.se.impl.naming.namingutil", + "com.sun.corba.se.impl.naming.pcosnaming", "com.sun.corba.se.impl.oa", + "com.sun.corba.se.impl.oa.poa", "com.sun.corba.se.impl.oa.toa", "com.sun.corba.se.impl.orb", + "com.sun.corba.se.impl.orbutil", "com.sun.corba.se.impl.orbutil.closure", + "com.sun.corba.se.impl.orbutil.concurrent", "com.sun.corba.se.impl.orbutil.fsm", + "com.sun.corba.se.impl.orbutil.graph", "com.sun.corba.se.impl.orbutil.threadpool", + "com.sun.corba.se.impl.presentation.rmi", "com.sun.corba.se.impl.protocol", + "com.sun.corba.se.impl.protocol.giopmsgheaders", "com.sun.corba.se.impl.resolver", + "com.sun.corba.se.impl.transport", "com.sun.corba.se.impl.util", + "com.sun.corba.se.internal.CosNaming", "com.sun.corba.se.internal.Interceptors", + "com.sun.corba.se.internal.POA", "com.sun.corba.se.internal.corba", + "com.sun.corba.se.internal.iiop", "com.sun.corba.se.org.omg.CORBA", + "com.sun.corba.se.pept.broker", "com.sun.corba.se.pept.encoding", + "com.sun.corba.se.pept.protocol", "com.sun.corba.se.pept.transport", + "com.sun.corba.se.spi.activation", + "com.sun.corba.se.spi.activation.InitialNameServicePackage", + "com.sun.corba.se.spi.activation.LocatorPackage", + "com.sun.corba.se.spi.activation.RepositoryPackage", "com.sun.corba.se.spi.copyobject", + "com.sun.corba.se.spi.encoding", "com.sun.corba.se.spi.extension", "com.sun.corba.se.spi.ior", + "com.sun.corba.se.spi.ior.iiop", "com.sun.corba.se.spi.legacy.connection", + "com.sun.corba.se.spi.legacy.interceptor", "com.sun.corba.se.spi.logging", + "com.sun.corba.se.spi.monitoring", "com.sun.corba.se.spi.oa", "com.sun.corba.se.spi.orb", + "com.sun.corba.se.spi.orbutil.closure", "com.sun.corba.se.spi.orbutil.fsm", + "com.sun.corba.se.spi.orbutil.proxy", "com.sun.corba.se.spi.orbutil.threadpool", + "com.sun.corba.se.spi.presentation.rmi", "com.sun.corba.se.spi.protocol", + "com.sun.corba.se.spi.resolver", "com.sun.corba.se.spi.servicecontext", + "com.sun.corba.se.spi.transport", "com.sun.crypto.provider", "com.sun.demo.jvmti.hprof", + "com.sun.deploy.uitoolkit.impl.fx", "com.sun.deploy.uitoolkit.impl.fx.ui", + "com.sun.deploy.uitoolkit.impl.fx.ui.resources", "com.sun.glass.events", + "com.sun.glass.events.mac", "com.sun.glass.ui", "com.sun.glass.ui.delegate", + "com.sun.glass.ui.gtk", "com.sun.glass.ui.mac", "com.sun.glass.ui.win", "com.sun.glass.utils", + "com.sun.image.codec.jpeg", "com.sun.imageio.plugins.bmp", "com.sun.imageio.plugins.common", + "com.sun.imageio.plugins.gif", "com.sun.imageio.plugins.jpeg", "com.sun.imageio.plugins.png", + "com.sun.imageio.plugins.wbmp", "com.sun.imageio.spi", "com.sun.imageio.stream", + "com.sun.istack.internal", "com.sun.istack.internal.localization", + "com.sun.istack.internal.logging", "com.sun.istack.internal.tools", + "com.sun.java.accessibility", "com.sun.java.accessibility.util.java.awt", + "com.sun.java.browser.dom", "com.sun.java.browser.net", "com.sun.java.swing", + "com.sun.java.swing.plaf.gtk", "com.sun.java.swing.plaf.gtk.resources", + "com.sun.java.swing.plaf.motif", "com.sun.java.swing.plaf.motif.resources", + "com.sun.java.swing.plaf.nimbus", "com.sun.java.swing.plaf.windows", + "com.sun.java.swing.plaf.windows.resources", "com.sun.java.util.jar.pack", + "com.sun.java_cup.internal.runtime", "com.sun.javafx", "com.sun.javafx.animation", + "com.sun.javafx.applet", "com.sun.javafx.application", "com.sun.javafx.beans", + "com.sun.javafx.beans.event", "com.sun.javafx.binding", "com.sun.javafx.charts", + "com.sun.javafx.collections", "com.sun.javafx.css", "com.sun.javafx.css.converters", + "com.sun.javafx.css.parser", "com.sun.javafx.cursor", "com.sun.javafx.effect", + "com.sun.javafx.embed", "com.sun.javafx.event", "com.sun.javafx.font", + "com.sun.javafx.font.coretext", "com.sun.javafx.font.directwrite", + "com.sun.javafx.font.freetype", "com.sun.javafx.font.t2k", "com.sun.javafx.fxml", + "com.sun.javafx.fxml.builder", "com.sun.javafx.fxml.expression", "com.sun.javafx.geom", + "com.sun.javafx.geom.transform", "com.sun.javafx.geometry", "com.sun.javafx.iio", + "com.sun.javafx.iio.bmp", "com.sun.javafx.iio.common", "com.sun.javafx.iio.gif", + "com.sun.javafx.iio.ios", "com.sun.javafx.iio.jpeg", "com.sun.javafx.iio.png", + "com.sun.javafx.image", "com.sun.javafx.image.impl", "com.sun.javafx.jmx", + "com.sun.javafx.logging", "com.sun.javafx.media", "com.sun.javafx.menu", + "com.sun.javafx.perf", "com.sun.javafx.print", "com.sun.javafx.property", + "com.sun.javafx.property.adapter", "com.sun.javafx.robot", "com.sun.javafx.robot.impl", + "com.sun.javafx.runtime", "com.sun.javafx.runtime.async", "com.sun.javafx.runtime.eula", + "com.sun.javafx.scene", "com.sun.javafx.scene.control", + "com.sun.javafx.scene.control.behavior", "com.sun.javafx.scene.control.skin", + "com.sun.javafx.scene.control.skin.resources", "com.sun.javafx.scene.input", + "com.sun.javafx.scene.layout.region", "com.sun.javafx.scene.paint", + "com.sun.javafx.scene.shape", "com.sun.javafx.scene.text", "com.sun.javafx.scene.transform", + "com.sun.javafx.scene.traversal", "com.sun.javafx.scene.web", + "com.sun.javafx.scene.web.behavior", "com.sun.javafx.scene.web.skin", + "com.sun.javafx.sg.prism", "com.sun.javafx.sg.prism.web", "com.sun.javafx.stage", + "com.sun.javafx.text", "com.sun.javafx.tk", "com.sun.javafx.tk.quantum", + "com.sun.javafx.util", "com.sun.javafx.webkit", "com.sun.javafx.webkit.drt", + "com.sun.javafx.webkit.prism", "com.sun.javafx.webkit.prism.theme", + "com.sun.javafx.webkit.theme", "com.sun.jmx.defaults", "com.sun.jmx.interceptor", + "com.sun.jmx.mbeanserver", "com.sun.jmx.remote.internal", "com.sun.jmx.remote.protocol.iiop", + "com.sun.jmx.remote.protocol.rmi", "com.sun.jmx.remote.security", "com.sun.jmx.remote.util", + "com.sun.jmx.snmp", "com.sun.jmx.snmp.IPAcl", "com.sun.jmx.snmp.agent", + "com.sun.jmx.snmp.daemon", "com.sun.jmx.snmp.defaults", "com.sun.jmx.snmp.internal", + "com.sun.jmx.snmp.mpm", "com.sun.jmx.snmp.tasks", "com.sun.jndi.cosnaming", + "com.sun.jndi.dns", "com.sun.jndi.ldap", "com.sun.jndi.ldap.ext", "com.sun.jndi.ldap.pool", + "com.sun.jndi.ldap.sasl", "com.sun.jndi.rmi.registry", "com.sun.jndi.toolkit.corba", + "com.sun.jndi.toolkit.ctx", "com.sun.jndi.toolkit.dir", "com.sun.jndi.toolkit.url", + "com.sun.jndi.url.corbaname", "com.sun.jndi.url.dns", "com.sun.jndi.url.iiop", + "com.sun.jndi.url.iiopname", "com.sun.jndi.url.ldap", "com.sun.jndi.url.ldaps", + "com.sun.jndi.url.rmi", "com.sun.management.jmx", "com.sun.media.jfxmedia", + "com.sun.media.jfxmedia.control", "com.sun.media.jfxmedia.effects", + "com.sun.media.jfxmedia.events", "com.sun.media.jfxmedia.locator", + "com.sun.media.jfxmedia.logging", "com.sun.media.jfxmedia.track", + "com.sun.media.jfxmediaimpl", "com.sun.media.jfxmediaimpl.platform", + "com.sun.media.jfxmediaimpl.platform.gstreamer", "com.sun.media.jfxmediaimpl.platform.ios", + "com.sun.media.jfxmediaimpl.platform.java", "com.sun.media.jfxmediaimpl.platform.osx", + "com.sun.media.sound", "com.sun.naming.internal", "com.sun.net.ssl", + "com.sun.net.ssl.internal.ssl", "com.sun.net.ssl.internal.www.protocol.https", + "com.sun.nio.file", "com.sun.nio.zipfs", "com.sun.openpisces", + "com.sun.org.apache.bcel.internal", "com.sun.org.apache.bcel.internal.classfile", + "com.sun.org.apache.bcel.internal.generic", "com.sun.org.apache.bcel.internal.util", + "com.sun.org.apache.regexp.internal", "com.sun.org.apache.xalan.internal", + "com.sun.org.apache.xalan.internal.extensions", "com.sun.org.apache.xalan.internal.lib", + "com.sun.org.apache.xalan.internal.res", "com.sun.org.apache.xalan.internal.templates", + "com.sun.org.apache.xalan.internal.utils", "com.sun.org.apache.xalan.internal.xslt", + "com.sun.org.apache.xalan.internal.xsltc", "com.sun.org.apache.xalan.internal.xsltc.cmdline", + "com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt", + "com.sun.org.apache.xalan.internal.xsltc.compiler", + "com.sun.org.apache.xalan.internal.xsltc.compiler.util", + "com.sun.org.apache.xalan.internal.xsltc.dom", + "com.sun.org.apache.xalan.internal.xsltc.runtime", + "com.sun.org.apache.xalan.internal.xsltc.runtime.output", + "com.sun.org.apache.xalan.internal.xsltc.trax", + "com.sun.org.apache.xalan.internal.xsltc.util", "com.sun.org.apache.xerces.internal.dom", + "com.sun.org.apache.xerces.internal.dom.events", "com.sun.org.apache.xerces.internal.impl", + "com.sun.org.apache.xerces.internal.impl.dtd", + "com.sun.org.apache.xerces.internal.impl.dtd.models", + "com.sun.org.apache.xerces.internal.impl.dv", + "com.sun.org.apache.xerces.internal.impl.dv.dtd", + "com.sun.org.apache.xerces.internal.impl.dv.util", + "com.sun.org.apache.xerces.internal.impl.dv.xs", "com.sun.org.apache.xerces.internal.impl.io", + "com.sun.org.apache.xerces.internal.impl.msg", + "com.sun.org.apache.xerces.internal.impl.validation", + "com.sun.org.apache.xerces.internal.impl.xpath", + "com.sun.org.apache.xerces.internal.impl.xpath.regex", + "com.sun.org.apache.xerces.internal.impl.xs", + "com.sun.org.apache.xerces.internal.impl.xs.identity", + "com.sun.org.apache.xerces.internal.impl.xs.models", + "com.sun.org.apache.xerces.internal.impl.xs.opti", + "com.sun.org.apache.xerces.internal.impl.xs.traversers", + "com.sun.org.apache.xerces.internal.impl.xs.util", "com.sun.org.apache.xerces.internal.jaxp", + "com.sun.org.apache.xerces.internal.jaxp.datatype", + "com.sun.org.apache.xerces.internal.jaxp.validation", + "com.sun.org.apache.xerces.internal.parsers", "com.sun.org.apache.xerces.internal.util", + "com.sun.org.apache.xerces.internal.utils", "com.sun.org.apache.xerces.internal.xinclude", + "com.sun.org.apache.xerces.internal.xni", "com.sun.org.apache.xerces.internal.xni.grammars", + "com.sun.org.apache.xerces.internal.xni.parser", + "com.sun.org.apache.xerces.internal.xpointer", "com.sun.org.apache.xerces.internal.xs", + "com.sun.org.apache.xerces.internal.xs.datatypes", "com.sun.org.apache.xml.internal.dtm", + "com.sun.org.apache.xml.internal.dtm.ref", "com.sun.org.apache.xml.internal.dtm.ref.dom2dtm", + "com.sun.org.apache.xml.internal.dtm.ref.sax2dtm", "com.sun.org.apache.xml.internal.res", + "com.sun.org.apache.xml.internal.resolver", + "com.sun.org.apache.xml.internal.resolver.helpers", + "com.sun.org.apache.xml.internal.resolver.readers", + "com.sun.org.apache.xml.internal.resolver.tools", "com.sun.org.apache.xml.internal.security", + "com.sun.org.apache.xml.internal.security.algorithms", + "com.sun.org.apache.xml.internal.security.algorithms.implementations", + "com.sun.org.apache.xml.internal.security.c14n", + "com.sun.org.apache.xml.internal.security.c14n.helper", + "com.sun.org.apache.xml.internal.security.c14n.implementations", + "com.sun.org.apache.xml.internal.security.encryption", + "com.sun.org.apache.xml.internal.security.exceptions", + "com.sun.org.apache.xml.internal.security.keys", + "com.sun.org.apache.xml.internal.security.keys.content", + "com.sun.org.apache.xml.internal.security.keys.content.keyvalues", + "com.sun.org.apache.xml.internal.security.keys.content.x509", + "com.sun.org.apache.xml.internal.security.keys.keyresolver", + "com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations", + "com.sun.org.apache.xml.internal.security.keys.storage", + "com.sun.org.apache.xml.internal.security.keys.storage.implementations", + "com.sun.org.apache.xml.internal.security.signature", + "com.sun.org.apache.xml.internal.security.signature.reference", + "com.sun.org.apache.xml.internal.security.transforms", + "com.sun.org.apache.xml.internal.security.transforms.implementations", + "com.sun.org.apache.xml.internal.security.transforms.params", + "com.sun.org.apache.xml.internal.security.utils", + "com.sun.org.apache.xml.internal.security.utils.resolver", + "com.sun.org.apache.xml.internal.security.utils.resolver.implementations", + "com.sun.org.apache.xml.internal.serialize", "com.sun.org.apache.xml.internal.serializer", + "com.sun.org.apache.xml.internal.serializer.utils", "com.sun.org.apache.xml.internal.utils", + "com.sun.org.apache.xml.internal.utils.res", "com.sun.org.apache.xpath.internal", + "com.sun.org.apache.xpath.internal.axes", "com.sun.org.apache.xpath.internal.compiler", + "com.sun.org.apache.xpath.internal.domapi", "com.sun.org.apache.xpath.internal.functions", + "com.sun.org.apache.xpath.internal.jaxp", "com.sun.org.apache.xpath.internal.objects", + "com.sun.org.apache.xpath.internal.operations", "com.sun.org.apache.xpath.internal.patterns", + "com.sun.org.apache.xpath.internal.res", "com.sun.org.glassfish.external.amx", + "com.sun.org.glassfish.external.arc", "com.sun.org.glassfish.external.probe.provider", + "com.sun.org.glassfish.external.probe.provider.annotations", + "com.sun.org.glassfish.external.statistics", + "com.sun.org.glassfish.external.statistics.annotations", + "com.sun.org.glassfish.external.statistics.impl", "com.sun.org.glassfish.gmbal", + "com.sun.org.glassfish.gmbal.util", "com.sun.org.omg.CORBA", + "com.sun.org.omg.CORBA.ValueDefPackage", "com.sun.org.omg.CORBA.portable", + "com.sun.org.omg.SendingContext", "com.sun.org.omg.SendingContext.CodeBasePackage", + "com.sun.pisces", "com.sun.prism", "com.sun.prism.d3d", "com.sun.prism.es2", + "com.sun.prism.image", "com.sun.prism.impl", "com.sun.prism.impl.packrect", + "com.sun.prism.impl.paint", "com.sun.prism.impl.ps", "com.sun.prism.impl.shape", + "com.sun.prism.j2d", "com.sun.prism.j2d.paint", "com.sun.prism.j2d.print", + "com.sun.prism.paint", "com.sun.prism.ps", "com.sun.prism.shader", "com.sun.prism.shape", + "com.sun.prism.sw", "com.sun.rmi.rmid", "com.sun.rowset", "com.sun.rowset.internal", + "com.sun.rowset.providers", "com.sun.scenario", "com.sun.scenario.animation", + "com.sun.scenario.animation.shared", "com.sun.scenario.effect", + "com.sun.scenario.effect.impl", "com.sun.scenario.effect.impl.es2", + "com.sun.scenario.effect.impl.hw", "com.sun.scenario.effect.impl.hw.d3d", + "com.sun.scenario.effect.impl.prism", "com.sun.scenario.effect.impl.prism.ps", + "com.sun.scenario.effect.impl.prism.sw", "com.sun.scenario.effect.impl.state", + "com.sun.scenario.effect.impl.sw", "com.sun.scenario.effect.impl.sw.java", + "com.sun.scenario.effect.impl.sw.sse", "com.sun.scenario.effect.light", + "com.sun.security.cert.internal.x509", "com.sun.security.ntlm", "com.sun.security.sasl", + "com.sun.security.sasl.digest", "com.sun.security.sasl.gsskerb", "com.sun.security.sasl.ntlm", + "com.sun.security.sasl.util", "com.sun.swing.internal.plaf.basic.resources", + "com.sun.swing.internal.plaf.metal.resources", "com.sun.swing.internal.plaf.synth.resources", + "com.sun.tools.classfile", "com.sun.tools.corba.se.idl", + "com.sun.tools.corba.se.idl.constExpr", "com.sun.tools.corba.se.idl.som.cff", + "com.sun.tools.corba.se.idl.som.idlemit", "com.sun.tools.corba.se.idl.toJavaPortable", + "com.sun.tools.doclets.formats.html", "com.sun.tools.doclets.formats.html.markup", + "com.sun.tools.doclets.formats.html.resources", "com.sun.tools.doclets.internal.toolkit", + "com.sun.tools.doclets.internal.toolkit.builders", + "com.sun.tools.doclets.internal.toolkit.resources", + "com.sun.tools.doclets.internal.toolkit.taglets", + "com.sun.tools.doclets.internal.toolkit.util", + "com.sun.tools.doclets.internal.toolkit.util.links", "com.sun.tools.doclint", + "com.sun.tools.doclint.resources", "com.sun.tools.example.debug.expr", + "com.sun.tools.example.debug.tty", "com.sun.tools.extcheck", "com.sun.tools.hat", + "com.sun.tools.hat.internal.model", "com.sun.tools.hat.internal.oql", + "com.sun.tools.hat.internal.parser", "com.sun.tools.hat.internal.server", + "com.sun.tools.hat.internal.util", "com.sun.tools.internal.jxc", + "com.sun.tools.internal.jxc.ap", "com.sun.tools.internal.jxc.api", + "com.sun.tools.internal.jxc.api.impl.j2s", "com.sun.tools.internal.jxc.gen.config", + "com.sun.tools.internal.jxc.model.nav", "com.sun.tools.internal.ws", + "com.sun.tools.internal.ws.api", "com.sun.tools.internal.ws.api.wsdl", + "com.sun.tools.internal.ws.processor", "com.sun.tools.internal.ws.processor.generator", + "com.sun.tools.internal.ws.processor.model", + "com.sun.tools.internal.ws.processor.model.exporter", + "com.sun.tools.internal.ws.processor.model.java", + "com.sun.tools.internal.ws.processor.model.jaxb", + "com.sun.tools.internal.ws.processor.modeler", + "com.sun.tools.internal.ws.processor.modeler.annotation", + "com.sun.tools.internal.ws.processor.modeler.wsdl", + "com.sun.tools.internal.ws.processor.util", "com.sun.tools.internal.ws.resources", + "com.sun.tools.internal.ws.spi", "com.sun.tools.internal.ws.util", + "com.sun.tools.internal.ws.util.xml", "com.sun.tools.internal.ws.wscompile", + "com.sun.tools.internal.ws.wscompile.plugin.at_generated", + "com.sun.tools.internal.ws.wsdl.document", "com.sun.tools.internal.ws.wsdl.document.http", + "com.sun.tools.internal.ws.wsdl.document.jaxws", + "com.sun.tools.internal.ws.wsdl.document.mime", + "com.sun.tools.internal.ws.wsdl.document.schema", + "com.sun.tools.internal.ws.wsdl.document.soap", "com.sun.tools.internal.ws.wsdl.framework", + "com.sun.tools.internal.ws.wsdl.parser", "com.sun.tools.internal.xjc", + "com.sun.tools.internal.xjc.addon.accessors", "com.sun.tools.internal.xjc.addon.at_generated", + "com.sun.tools.internal.xjc.addon.code_injector", "com.sun.tools.internal.xjc.addon.episode", + "com.sun.tools.internal.xjc.addon.locator", "com.sun.tools.internal.xjc.addon.sync", + "com.sun.tools.internal.xjc.api", "com.sun.tools.internal.xjc.api.impl.s2j", + "com.sun.tools.internal.xjc.api.util", "com.sun.tools.internal.xjc.generator.annotation.spec", + "com.sun.tools.internal.xjc.generator.bean", + "com.sun.tools.internal.xjc.generator.bean.field", + "com.sun.tools.internal.xjc.generator.util", "com.sun.tools.internal.xjc.model", + "com.sun.tools.internal.xjc.model.nav", "com.sun.tools.internal.xjc.outline", + "com.sun.tools.internal.xjc.reader", "com.sun.tools.internal.xjc.reader.dtd", + "com.sun.tools.internal.xjc.reader.dtd.bindinfo", "com.sun.tools.internal.xjc.reader.gbind", + "com.sun.tools.internal.xjc.reader.internalizer", "com.sun.tools.internal.xjc.reader.relaxng", + "com.sun.tools.internal.xjc.reader.xmlschema", + "com.sun.tools.internal.xjc.reader.xmlschema.bindinfo", + "com.sun.tools.internal.xjc.reader.xmlschema.ct", + "com.sun.tools.internal.xjc.reader.xmlschema.parser", "com.sun.tools.internal.xjc.runtime", + "com.sun.tools.internal.xjc.util", "com.sun.tools.internal.xjc.writer", + "com.sun.tools.javac.api", "com.sun.tools.javac.code", "com.sun.tools.javac.comp", + "com.sun.tools.javac.file", "com.sun.tools.javac.jvm", "com.sun.tools.javac.main", + "com.sun.tools.javac.model", "com.sun.tools.javac.nio", "com.sun.tools.javac.parser", + "com.sun.tools.javac.processing", "com.sun.tools.javac.resources", "com.sun.tools.javac.sym", + "com.sun.tools.javac.tree", "com.sun.tools.javac.util", "com.sun.tools.javadoc.api", + "com.sun.tools.javadoc.resources", "com.sun.tools.javah", "com.sun.tools.javah.resources", + "com.sun.tools.javap", "com.sun.tools.javap.resources", "com.sun.tools.jdeps", + "com.sun.tools.jdeps.resources", "com.sun.tools.jdi", "com.sun.tools.jdi.resources", + "com.sun.tools.script.shell", "com.sun.tracing", "com.sun.tracing.dtrace", "com.sun.webkit", + "com.sun.webkit.dom", "com.sun.webkit.event", "com.sun.webkit.graphics", + "com.sun.webkit.network", "com.sun.webkit.network.about", "com.sun.webkit.network.data", + "com.sun.webkit.perf", "com.sun.webkit.plugin", "com.sun.webkit.text", + "com.sun.xml.internal.bind", "com.sun.xml.internal.bind.annotation", + "com.sun.xml.internal.bind.api", "com.sun.xml.internal.bind.api.impl", + "com.sun.xml.internal.bind.marshaller", "com.sun.xml.internal.bind.unmarshaller", + "com.sun.xml.internal.bind.util", "com.sun.xml.internal.bind.v2", + "com.sun.xml.internal.bind.v2.bytecode", "com.sun.xml.internal.bind.v2.model.annotation", + "com.sun.xml.internal.bind.v2.model.core", "com.sun.xml.internal.bind.v2.model.impl", + "com.sun.xml.internal.bind.v2.model.nav", "com.sun.xml.internal.bind.v2.model.runtime", + "com.sun.xml.internal.bind.v2.model.util", "com.sun.xml.internal.bind.v2.runtime", + "com.sun.xml.internal.bind.v2.runtime.output", + "com.sun.xml.internal.bind.v2.runtime.property", + "com.sun.xml.internal.bind.v2.runtime.reflect", + "com.sun.xml.internal.bind.v2.runtime.reflect.opt", + "com.sun.xml.internal.bind.v2.runtime.unmarshaller", "com.sun.xml.internal.bind.v2.schemagen", + "com.sun.xml.internal.bind.v2.schemagen.episode", + "com.sun.xml.internal.bind.v2.schemagen.xmlschema", "com.sun.xml.internal.bind.v2.util", + "com.sun.xml.internal.dtdparser", "com.sun.xml.internal.fastinfoset", + "com.sun.xml.internal.fastinfoset.algorithm", "com.sun.xml.internal.fastinfoset.alphabet", + "com.sun.xml.internal.fastinfoset.dom", + "com.sun.xml.internal.fastinfoset.org.apache.xerces.util", + "com.sun.xml.internal.fastinfoset.sax", "com.sun.xml.internal.fastinfoset.stax", + "com.sun.xml.internal.fastinfoset.stax.events", + "com.sun.xml.internal.fastinfoset.stax.factory", "com.sun.xml.internal.fastinfoset.stax.util", + "com.sun.xml.internal.fastinfoset.tools", "com.sun.xml.internal.fastinfoset.util", + "com.sun.xml.internal.fastinfoset.vocab", "com.sun.xml.internal.messaging.saaj", + "com.sun.xml.internal.messaging.saaj.client.p2p", + "com.sun.xml.internal.messaging.saaj.packaging.mime", + "com.sun.xml.internal.messaging.saaj.packaging.mime.internet", + "com.sun.xml.internal.messaging.saaj.packaging.mime.util", + "com.sun.xml.internal.messaging.saaj.soap", + "com.sun.xml.internal.messaging.saaj.soap.dynamic", + "com.sun.xml.internal.messaging.saaj.soap.impl", + "com.sun.xml.internal.messaging.saaj.soap.name", + "com.sun.xml.internal.messaging.saaj.soap.ver1_1", + "com.sun.xml.internal.messaging.saaj.soap.ver1_2", "com.sun.xml.internal.messaging.saaj.util", + "com.sun.xml.internal.messaging.saaj.util.transform", + "com.sun.xml.internal.org.jvnet.fastinfoset", + "com.sun.xml.internal.org.jvnet.fastinfoset.sax", + "com.sun.xml.internal.org.jvnet.fastinfoset.sax.helpers", + "com.sun.xml.internal.org.jvnet.fastinfoset.stax", "com.sun.xml.internal.org.jvnet.mimepull", + "com.sun.xml.internal.org.jvnet.staxex", "com.sun.xml.internal.rngom.ast.builder", + "com.sun.xml.internal.rngom.ast.om", "com.sun.xml.internal.rngom.ast.util", + "com.sun.xml.internal.rngom.binary", "com.sun.xml.internal.rngom.binary.visitor", + "com.sun.xml.internal.rngom.digested", "com.sun.xml.internal.rngom.dt", + "com.sun.xml.internal.rngom.dt.builtin", "com.sun.xml.internal.rngom.nc", + "com.sun.xml.internal.rngom.parse", "com.sun.xml.internal.rngom.parse.compact", + "com.sun.xml.internal.rngom.parse.host", "com.sun.xml.internal.rngom.parse.xml", + "com.sun.xml.internal.rngom.util", "com.sun.xml.internal.rngom.xml.sax", + "com.sun.xml.internal.rngom.xml.util", "com.sun.xml.internal.stream", + "com.sun.xml.internal.stream.buffer", "com.sun.xml.internal.stream.buffer.sax", + "com.sun.xml.internal.stream.buffer.stax", "com.sun.xml.internal.stream.dtd", + "com.sun.xml.internal.stream.dtd.nonvalidating", "com.sun.xml.internal.stream.events", + "com.sun.xml.internal.stream.util", "com.sun.xml.internal.stream.writers", + "com.sun.xml.internal.txw2", "com.sun.xml.internal.txw2.annotation", + "com.sun.xml.internal.txw2.output", "com.sun.xml.internal.ws", + "com.sun.xml.internal.ws.addressing", "com.sun.xml.internal.ws.addressing.model", + "com.sun.xml.internal.ws.addressing.policy", "com.sun.xml.internal.ws.addressing.v200408", + "com.sun.xml.internal.ws.api", "com.sun.xml.internal.ws.api.addressing", + "com.sun.xml.internal.ws.api.client", "com.sun.xml.internal.ws.api.config.management", + "com.sun.xml.internal.ws.api.config.management.policy", + "com.sun.xml.internal.ws.api.databinding", "com.sun.xml.internal.ws.api.fastinfoset", + "com.sun.xml.internal.ws.api.ha", "com.sun.xml.internal.ws.api.handler", + "com.sun.xml.internal.ws.api.message", "com.sun.xml.internal.ws.api.message.saaj", + "com.sun.xml.internal.ws.api.message.stream", "com.sun.xml.internal.ws.api.model", + "com.sun.xml.internal.ws.api.model.soap", "com.sun.xml.internal.ws.api.model.wsdl", + "com.sun.xml.internal.ws.api.model.wsdl.editable", "com.sun.xml.internal.ws.api.pipe", + "com.sun.xml.internal.ws.api.pipe.helper", "com.sun.xml.internal.ws.api.policy", + "com.sun.xml.internal.ws.api.policy.subject", "com.sun.xml.internal.ws.api.server", + "com.sun.xml.internal.ws.api.streaming", "com.sun.xml.internal.ws.api.wsdl.parser", + "com.sun.xml.internal.ws.api.wsdl.writer", "com.sun.xml.internal.ws.assembler", + "com.sun.xml.internal.ws.assembler.dev", "com.sun.xml.internal.ws.assembler.jaxws", + "com.sun.xml.internal.ws.binding", "com.sun.xml.internal.ws.client", + "com.sun.xml.internal.ws.client.dispatch", "com.sun.xml.internal.ws.client.sei", + "com.sun.xml.internal.ws.commons.xmlutil", "com.sun.xml.internal.ws.config.management.policy", + "com.sun.xml.internal.ws.config.metro.dev", "com.sun.xml.internal.ws.config.metro.util", + "com.sun.xml.internal.ws.db", "com.sun.xml.internal.ws.db.glassfish", + "com.sun.xml.internal.ws.developer", "com.sun.xml.internal.ws.dump", + "com.sun.xml.internal.ws.encoding", "com.sun.xml.internal.ws.encoding.fastinfoset", + "com.sun.xml.internal.ws.encoding.policy", "com.sun.xml.internal.ws.encoding.soap", + "com.sun.xml.internal.ws.encoding.soap.streaming", "com.sun.xml.internal.ws.encoding.xml", + "com.sun.xml.internal.ws.fault", "com.sun.xml.internal.ws.handler", + "com.sun.xml.internal.ws.message", "com.sun.xml.internal.ws.message.jaxb", + "com.sun.xml.internal.ws.message.saaj", "com.sun.xml.internal.ws.message.source", + "com.sun.xml.internal.ws.message.stream", "com.sun.xml.internal.ws.model", + "com.sun.xml.internal.ws.model.soap", "com.sun.xml.internal.ws.model.wsdl", + "com.sun.xml.internal.ws.org.objectweb.asm", "com.sun.xml.internal.ws.policy", + "com.sun.xml.internal.ws.policy.jaxws", "com.sun.xml.internal.ws.policy.jaxws.spi", + "com.sun.xml.internal.ws.policy.privateutil", "com.sun.xml.internal.ws.policy.sourcemodel", + "com.sun.xml.internal.ws.policy.sourcemodel.attach", + "com.sun.xml.internal.ws.policy.sourcemodel.wspolicy", "com.sun.xml.internal.ws.policy.spi", + "com.sun.xml.internal.ws.policy.subject", "com.sun.xml.internal.ws.protocol.soap", + "com.sun.xml.internal.ws.protocol.xml", "com.sun.xml.internal.ws.resources", + "com.sun.xml.internal.ws.runtime.config", "com.sun.xml.internal.ws.server", + "com.sun.xml.internal.ws.server.provider", "com.sun.xml.internal.ws.server.sei", + "com.sun.xml.internal.ws.spi", "com.sun.xml.internal.ws.spi.db", + "com.sun.xml.internal.ws.streaming", "com.sun.xml.internal.ws.transport", + "com.sun.xml.internal.ws.transport.http", "com.sun.xml.internal.ws.transport.http.client", + "com.sun.xml.internal.ws.transport.http.server", "com.sun.xml.internal.ws.util", + "com.sun.xml.internal.ws.util.exception", "com.sun.xml.internal.ws.util.pipe", + "com.sun.xml.internal.ws.util.xml", "com.sun.xml.internal.ws.wsdl", + "com.sun.xml.internal.ws.wsdl.parser", "com.sun.xml.internal.ws.wsdl.writer", + "com.sun.xml.internal.ws.wsdl.writer.document", + "com.sun.xml.internal.ws.wsdl.writer.document.http", + "com.sun.xml.internal.ws.wsdl.writer.document.soap", + "com.sun.xml.internal.ws.wsdl.writer.document.soap12", + "com.sun.xml.internal.ws.wsdl.writer.document.xsd", "com.sun.xml.internal.xsom", + "com.sun.xml.internal.xsom.impl", "com.sun.xml.internal.xsom.impl.parser", + "com.sun.xml.internal.xsom.impl.parser.state", "com.sun.xml.internal.xsom.impl.scd", + "com.sun.xml.internal.xsom.impl.util", "com.sun.xml.internal.xsom.parser", + "com.sun.xml.internal.xsom.util", "com.sun.xml.internal.xsom.visitor", "java.awt.dnd.peer", + "java.awt.peer", "javafx.embed.swt", "jdk", "jdk.internal.cmm", "jdk.internal.dynalink", + "jdk.internal.dynalink.beans", "jdk.internal.dynalink.linker", + "jdk.internal.dynalink.support", "jdk.internal.instrumentation", + "jdk.internal.org.objectweb.asm", "jdk.internal.org.objectweb.asm.commons", + "jdk.internal.org.objectweb.asm.signature", "jdk.internal.org.objectweb.asm.tree", + "jdk.internal.org.objectweb.asm.tree.analysis", "jdk.internal.org.objectweb.asm.util", + "jdk.internal.org.xml.sax", "jdk.internal.org.xml.sax.helpers", "jdk.internal.util.xml", + "jdk.internal.util.xml.impl", "jdk.jfr.events", "jdk.management.resource.internal", + "jdk.management.resource.internal.inst", "jdk.nashorn.internal", + "jdk.nashorn.internal.codegen", "jdk.nashorn.internal.codegen.types", + "jdk.nashorn.internal.ir", "jdk.nashorn.internal.ir.annotations", + "jdk.nashorn.internal.ir.debug", "jdk.nashorn.internal.ir.visitor", + "jdk.nashorn.internal.lookup", "jdk.nashorn.internal.objects", + "jdk.nashorn.internal.objects.annotations", "jdk.nashorn.internal.parser", + "jdk.nashorn.internal.runtime", "jdk.nashorn.internal.runtime.arrays", + "jdk.nashorn.internal.runtime.events", "jdk.nashorn.internal.runtime.linker", + "jdk.nashorn.internal.runtime.logging", "jdk.nashorn.internal.runtime.options", + "jdk.nashorn.internal.runtime.regexp", "jdk.nashorn.internal.runtime.regexp.joni", + "jdk.nashorn.internal.runtime.regexp.joni.ast", + "jdk.nashorn.internal.runtime.regexp.joni.constants", + "jdk.nashorn.internal.runtime.regexp.joni.encoding", + "jdk.nashorn.internal.runtime.regexp.joni.exception", "jdk.nashorn.internal.scripts", + "jdk.nashorn.tools", "oracle.jrockit.jfr", "oracle.jrockit.jfr.events", + "oracle.jrockit.jfr.jdkevents", "oracle.jrockit.jfr.jdkevents.throwabletransform", + "oracle.jrockit.jfr.openmbean", "oracle.jrockit.jfr.parser", "oracle.jrockit.jfr.settings", + "oracle.jrockit.jfr.tools", "org.jcp.xml.dsig.internal", "org.jcp.xml.dsig.internal.dom", + "org.omg.stub.javax.management.remote.rmi", "org.relaxng.datatype", + "org.relaxng.datatype.helpers", "sun.applet", "sun.applet.resources", "sun.audio", "sun.awt", + "sun.awt.X11", "sun.awt.datatransfer", "sun.awt.dnd", "sun.awt.event", "sun.awt.geom", + "sun.awt.im", "sun.awt.image", "sun.awt.image.codec", "sun.awt.motif", "sun.awt.resources", + "sun.awt.shell", "sun.awt.util", "sun.awt.windows", "sun.corba", "sun.dc", "sun.dc.path", + "sun.dc.pr", "sun.font", "sun.instrument", "sun.invoke", "sun.invoke.anon", + "sun.invoke.empty", "sun.invoke.util", "sun.io", "sun.java2d", "sun.java2d.cmm", + "sun.java2d.cmm.kcms", "sun.java2d.cmm.lcms", "sun.java2d.d3d", "sun.java2d.jules", + "sun.java2d.loops", "sun.java2d.opengl", "sun.java2d.pipe", "sun.java2d.pipe.hw", + "sun.java2d.pisces", "sun.java2d.windows", "sun.java2d.x11", "sun.java2d.xr", + "sun.jvmstat.monitor", "sun.jvmstat.monitor.event", "sun.jvmstat.monitor.remote", + "sun.jvmstat.perfdata.monitor", "sun.jvmstat.perfdata.monitor.protocol.file", + "sun.jvmstat.perfdata.monitor.protocol.local", "sun.jvmstat.perfdata.monitor.protocol.rmi", + "sun.jvmstat.perfdata.monitor.v1_0", "sun.jvmstat.perfdata.monitor.v2_0", "sun.launcher", + "sun.launcher.resources", "sun.lwawt", "sun.lwawt.macosx", "sun.management", + "sun.management.counter", "sun.management.counter.perf", "sun.management.jdp", + "sun.management.jmxremote", "sun.management.resources", "sun.management.snmp", + "sun.management.snmp.jvminstr", "sun.management.snmp.jvmmib", "sun.management.snmp.util", + "sun.misc", "sun.misc.resources", "sun.net", "sun.net.dns", "sun.net.ftp", "sun.net.ftp.impl", + "sun.net.httpserver", "sun.net.idn", "sun.net.sdp", "sun.net.smtp", "sun.net.spi", + "sun.net.spi.nameservice", "sun.net.spi.nameservice.dns", "sun.net.util", "sun.net.www", + "sun.net.www.content.audio", "sun.net.www.content.image", "sun.net.www.content.text", + "sun.net.www.http", "sun.net.www.protocol.file", "sun.net.www.protocol.ftp", + "sun.net.www.protocol.http", "sun.net.www.protocol.http.logging", + "sun.net.www.protocol.http.ntlm", "sun.net.www.protocol.http.spnego", + "sun.net.www.protocol.https", "sun.net.www.protocol.jar", "sun.net.www.protocol.mailto", + "sun.net.www.protocol.netdoc", "sun.nio", "sun.nio.ch", "sun.nio.ch.sctp", "sun.nio.cs", + "sun.nio.cs.ext", "sun.nio.fs", "sun.print", "sun.print.resources", "sun.reflect", + "sun.reflect.annotation", "sun.reflect.generics.factory", "sun.reflect.generics.parser", + "sun.reflect.generics.reflectiveObjects", "sun.reflect.generics.repository", + "sun.reflect.generics.scope", "sun.reflect.generics.tree", "sun.reflect.generics.visitor", + "sun.reflect.misc", "sun.rmi.log", "sun.rmi.registry", "sun.rmi.rmic", "sun.rmi.rmic.iiop", + "sun.rmi.rmic.newrmic", "sun.rmi.rmic.newrmic.jrmp", "sun.rmi.runtime", "sun.rmi.server", + "sun.rmi.transport", "sun.rmi.transport.proxy", "sun.rmi.transport.tcp", "sun.security.acl", + "sun.security.action", "sun.security.ec", "sun.security.internal.interfaces", + "sun.security.internal.spec", "sun.security.jca", "sun.security.jgss", + "sun.security.jgss.krb5", "sun.security.jgss.spi", "sun.security.jgss.spnego", + "sun.security.jgss.wrapper", "sun.security.krb5", "sun.security.krb5.internal", + "sun.security.krb5.internal.ccache", "sun.security.krb5.internal.crypto", + "sun.security.krb5.internal.crypto.dk", "sun.security.krb5.internal.ktab", + "sun.security.krb5.internal.rcache", "sun.security.krb5.internal.tools", + "sun.security.krb5.internal.util", "sun.security.mscapi", "sun.security.pkcs", + "sun.security.pkcs10", "sun.security.pkcs11", "sun.security.pkcs11.wrapper", + "sun.security.pkcs12", "sun.security.provider", "sun.security.provider.certpath", + "sun.security.provider.certpath.ldap", "sun.security.provider.certpath.ssl", + "sun.security.rsa", "sun.security.smartcardio", "sun.security.ssl", "sun.security.ssl.krb5", + "sun.security.timestamp", "sun.security.tools", "sun.security.tools.jarsigner", + "sun.security.tools.keytool", "sun.security.tools.policytool", "sun.security.util", + "sun.security.validator", "sun.security.x509", "sun.swing", "sun.swing.icon", + "sun.swing.plaf", "sun.swing.plaf.synth", "sun.swing.plaf.windows", "sun.swing.table", + "sun.swing.text", "sun.swing.text.html", "sun.text", "sun.text.bidi", "sun.text.normalizer", + "sun.text.resources", "sun.text.resources.en", "sun.tools.asm", "sun.tools.attach", + "sun.tools.jar", "sun.tools.jar.resources", "sun.tools.java", "sun.tools.javac", + "sun.tools.jcmd", "sun.tools.jconsole", "sun.tools.jconsole.inspector", "sun.tools.jinfo", + "sun.tools.jmap", "sun.tools.jps", "sun.tools.jstack", "sun.tools.jstat", "sun.tools.jstatd", + "sun.tools.native2ascii", "sun.tools.native2ascii.resources", "sun.tools.serialver", + "sun.tools.tree", "sun.tools.util", "sun.tracing", "sun.tracing.dtrace", "sun.usagetracker", + "sun.util", "sun.util.calendar", "sun.util.cldr", "sun.util.locale", + "sun.util.locale.provider", "sun.util.logging", "sun.util.logging.resources", + "sun.util.resources", "sun.util.resources.en", "sun.util.spi", "sun.util.xml" + ] } diff --git a/java/ql/src/Violations of Best Practice/Magic Constants/MagicConstants.qll b/java/ql/src/Violations of Best Practice/Magic Constants/MagicConstants.qll index 96c4d753d8f..15a738ba927 100644 --- a/java/ql/src/Violations of Best Practice/Magic Constants/MagicConstants.qll +++ b/java/ql/src/Violations of Best Practice/Magic Constants/MagicConstants.qll @@ -5,179 +5,30 @@ import java */ private predicate trivialPositiveIntValue(string s) { - s = "0" or - s = "1" or - s = "2" or - s = "3" or - s = "4" or - s = "5" or - s = "6" or - s = "7" or - s = "8" or - s = "9" or - s = "10" or - s = "11" or - s = "12" or - s = "13" or - s = "14" or - s = "15" or - s = "16" or - s = "17" or - s = "18" or - s = "19" or - s = "20" or - s = "16" or - s = "32" or - s = "64" or - s = "128" or - s = "256" or - s = "512" or - s = "1024" or - s = "2048" or - s = "4096" or - s = "16384" or - s = "32768" or - s = "65536" or - s = "1048576" or - s = "2147483648" or - s = "4294967296" or - s = "15" or - s = "31" or - s = "63" or - s = "127" or - s = "255" or - s = "511" or - s = "1023" or - s = "2047" or - s = "4095" or - s = "16383" or - s = "32767" or - s = "65535" or - s = "1048577" or - s = "2147483647" or - s = "4294967295" or - s = "0x00000001" or - s = "0x00000002" or - s = "0x00000004" or - s = "0x00000008" or - s = "0x00000010" or - s = "0x00000020" or - s = "0x00000040" or - s = "0x00000080" or - s = "0x00000100" or - s = "0x00000200" or - s = "0x00000400" or - s = "0x00000800" or - s = "0x00001000" or - s = "0x00002000" or - s = "0x00004000" or - s = "0x00008000" or - s = "0x00010000" or - s = "0x00020000" or - s = "0x00040000" or - s = "0x00080000" or - s = "0x00100000" or - s = "0x00200000" or - s = "0x00400000" or - s = "0x00800000" or - s = "0x01000000" or - s = "0x02000000" or - s = "0x04000000" or - s = "0x08000000" or - s = "0x10000000" or - s = "0x20000000" or - s = "0x40000000" or - s = "0x80000000" or - s = "0x00000001" or - s = "0x00000003" or - s = "0x00000007" or - s = "0x0000000f" or - s = "0x0000001f" or - s = "0x0000003f" or - s = "0x0000007f" or - s = "0x000000ff" or - s = "0x000001ff" or - s = "0x000003ff" or - s = "0x000007ff" or - s = "0x00000fff" or - s = "0x00001fff" or - s = "0x00003fff" or - s = "0x00007fff" or - s = "0x0000ffff" or - s = "0x0001ffff" or - s = "0x0003ffff" or - s = "0x0007ffff" or - s = "0x000fffff" or - s = "0x001fffff" or - s = "0x003fffff" or - s = "0x007fffff" or - s = "0x00ffffff" or - s = "0x01ffffff" or - s = "0x03ffffff" or - s = "0x07ffffff" or - s = "0x0fffffff" or - s = "0x1fffffff" or - s = "0x3fffffff" or - s = "0x7fffffff" or - s = "0xffffffff" or - s = "0x0001" or - s = "0x0002" or - s = "0x0004" or - s = "0x0008" or - s = "0x0010" or - s = "0x0020" or - s = "0x0040" or - s = "0x0080" or - s = "0x0100" or - s = "0x0200" or - s = "0x0400" or - s = "0x0800" or - s = "0x1000" or - s = "0x2000" or - s = "0x4000" or - s = "0x8000" or - s = "0x0001" or - s = "0x0003" or - s = "0x0007" or - s = "0x000f" or - s = "0x001f" or - s = "0x003f" or - s = "0x007f" or - s = "0x00ff" or - s = "0x01ff" or - s = "0x03ff" or - s = "0x07ff" or - s = "0x0fff" or - s = "0x1fff" or - s = "0x3fff" or - s = "0x7fff" or - s = "0xffff" or - s = "0x01" or - s = "0x02" or - s = "0x04" or - s = "0x08" or - s = "0x10" or - s = "0x20" or - s = "0x40" or - s = "0x80" or - s = "0x01" or - s = "0x03" or - s = "0x07" or - s = "0x0f" or - s = "0x1f" or - s = "0x3f" or - s = "0x7f" or - s = "0xff" or - s = "0x00" or - s = "10" or - s = "100" or - s = "1000" or - s = "10000" or - s = "100000" or - s = "1000000" or - s = "10000000" or - s = "100000000" or - s = "1000000000" + s = + [ + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", + "17", "18", "19", "20", "16", "32", "64", "128", "256", "512", "1024", "2048", "4096", + "16384", "32768", "65536", "1048576", "2147483648", "4294967296", "15", "31", "63", "127", + "255", "511", "1023", "2047", "4095", "16383", "32767", "65535", "1048577", "2147483647", + "4294967295", "0x00000001", "0x00000002", "0x00000004", "0x00000008", "0x00000010", + "0x00000020", "0x00000040", "0x00000080", "0x00000100", "0x00000200", "0x00000400", + "0x00000800", "0x00001000", "0x00002000", "0x00004000", "0x00008000", "0x00010000", + "0x00020000", "0x00040000", "0x00080000", "0x00100000", "0x00200000", "0x00400000", + "0x00800000", "0x01000000", "0x02000000", "0x04000000", "0x08000000", "0x10000000", + "0x20000000", "0x40000000", "0x80000000", "0x00000001", "0x00000003", "0x00000007", + "0x0000000f", "0x0000001f", "0x0000003f", "0x0000007f", "0x000000ff", "0x000001ff", + "0x000003ff", "0x000007ff", "0x00000fff", "0x00001fff", "0x00003fff", "0x00007fff", + "0x0000ffff", "0x0001ffff", "0x0003ffff", "0x0007ffff", "0x000fffff", "0x001fffff", + "0x003fffff", "0x007fffff", "0x00ffffff", "0x01ffffff", "0x03ffffff", "0x07ffffff", + "0x0fffffff", "0x1fffffff", "0x3fffffff", "0x7fffffff", "0xffffffff", "0x0001", "0x0002", + "0x0004", "0x0008", "0x0010", "0x0020", "0x0040", "0x0080", "0x0100", "0x0200", "0x0400", + "0x0800", "0x1000", "0x2000", "0x4000", "0x8000", "0x0001", "0x0003", "0x0007", "0x000f", + "0x001f", "0x003f", "0x007f", "0x00ff", "0x01ff", "0x03ff", "0x07ff", "0x0fff", "0x1fff", + "0x3fff", "0x7fff", "0xffff", "0x01", "0x02", "0x04", "0x08", "0x10", "0x20", "0x40", "0x80", + "0x01", "0x03", "0x07", "0x0f", "0x1f", "0x3f", "0x7f", "0xff", "0x00", "10", "100", "1000", + "10000", "100000", "1000000", "10000000", "100000000", "1000000000" + ] } private predicate trivialIntValue(string s) { From 882adc8e50d169aef2fef487252b4b1d9ff89697 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 13 Oct 2021 16:39:02 +0100 Subject: [PATCH 285/361] JS: Set literals. --- .../javascript/DynamicPropertyAccess.qll | 2 +- .../lib/semmle/javascript/StandardLibrary.qll | 8 +- .../frameworks/AngularJS/AngularJSCore.qll | 103 +--- .../AngularJS/AngularJSExpressions.qll | 23 +- .../javascript/frameworks/AsyncPackage.qll | 30 +- .../lib/semmle/javascript/frameworks/HTTP.qll | 46 +- .../frameworks/LodashUnderscore.qll | 482 ++++-------------- .../javascript/security/TaintedUrlSuffix.qll | 19 +- .../ClientSideUrlRedirectCustomizations.qll | 16 +- .../LoopBoundInjectionCustomizations.qll | 72 +-- .../src/Statements/UseOfReturnlessFunction.ql | 15 +- javascript/ql/src/meta/Consistency.ql | 22 +- 12 files changed, 170 insertions(+), 668 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll index 456fd773f64..89a65b13ebd 100644 --- a/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll +++ b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll @@ -14,7 +14,7 @@ private import semmle.javascript.dataflow.internal.FlowSteps SourceNode getAnEnumeratedArrayElement(SourceNode array) { exists(MethodCallNode call, string name | call = array.getAMethodCall(name) and - (name = "forEach" or name = "map") and + (name = ["forEach", "map"]) and result = call.getCallback(0).getParameter(0) ) or diff --git a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll index 9ca2bf1725f..ad77d40a833 100644 --- a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll +++ b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll @@ -55,13 +55,7 @@ private class ArrayIterationCallbackAsPartialInvoke extends DataFlow::PartialInv getNumArgument() = 2 and // Filter out library methods named 'forEach' etc not DataFlow::moduleImport(_).flowsTo(getReceiver()) and - exists(string name | name = getMethodName() | - name = "filter" or - name = "forEach" or - name = "map" or - name = "some" or - name = "every" - ) + getMethodName() = ["filter", "forEach", "map", "some", "every"] } override DataFlow::Node getBoundReceiver(DataFlow::Node callback) { diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index e8abb51c99d..88e55b390cb 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -177,15 +177,10 @@ class ModuleApiCallDependencyInjection extends DependencyInjection { * This method excludes the method names that are also present on the AngularJS '$provide' object. */ private int injectableArgPos() { - ( - methodName = "directive" or - methodName = "filter" or - methodName = "controller" or - methodName = "animation" - ) and + methodName = ["directive", "filter", "controller", "animation"] and result = 1 or - (methodName = "config" or methodName = "run") and + methodName = ["config", "run"] and result = 0 } @@ -199,64 +194,17 @@ class ModuleApiCallDependencyInjection extends DependencyInjection { * (cf. https://docs.angularjs.org/api/ng/directive/). */ private predicate builtinDirective(string name) { - name = "ngApp" or - name = "ngBind" or - name = "ngBindHtml" or - name = "ngBindTemplate" or - name = "ngBlur" or - name = "ngChange" or - name = "ngChecked" or - name = "ngClass" or - name = "ngClassEven" or - name = "ngClassOdd" or - name = "ngClick" or - name = "ngCloak" or - name = "ngController" or - name = "ngCopy" or - name = "ngCsp" or - name = "ngCut" or - name = "ngDblclick" or - name = "ngDisabled" or - name = "ngFocus" or - name = "ngForm" or - name = "ngHide" or - name = "ngHref" or - name = "ngIf" or - name = "ngInclude" or - name = "ngInit" or - name = "ngJq" or - name = "ngKeydown" or - name = "ngKeypress" or - name = "ngKeyup" or - name = "ngList" or - name = "ngMaxlength" or - name = "ngMinlength" or - name = "ngModel" or - name = "ngModelOptions" or - name = "ngMousedown" or - name = "ngMouseenter" or - name = "ngMouseleave" or - name = "ngMousemove" or - name = "ngMouseover" or - name = "ngMouseup" or - name = "ngNonBindable" or - name = "ngOpen" or - name = "ngOptions" or - name = "ngPaste" or - name = "ngPattern" or - name = "ngPluralize" or - name = "ngReadonly" or - name = "ngRepeat" or - name = "ngRequired" or - name = "ngSelected" or - name = "ngShow" or - name = "ngSrc" or - name = "ngSrcset" or - name = "ngStyle" or - name = "ngSubmit" or - name = "ngSwitch" or - name = "ngTransclude" or - name = "ngValue" + name = + [ + "ngApp", "ngBind", "ngBindHtml", "ngBindTemplate", "ngBlur", "ngChange", "ngChecked", + "ngClass", "ngClassEven", "ngClassOdd", "ngClick", "ngCloak", "ngController", "ngCopy", + "ngCsp", "ngCut", "ngDblclick", "ngDisabled", "ngFocus", "ngForm", "ngHide", "ngHref", "ngIf", + "ngInclude", "ngInit", "ngJq", "ngKeydown", "ngKeypress", "ngKeyup", "ngList", "ngMaxlength", + "ngMinlength", "ngModel", "ngModelOptions", "ngMousedown", "ngMouseenter", "ngMouseleave", + "ngMousemove", "ngMouseover", "ngMouseup", "ngNonBindable", "ngOpen", "ngOptions", "ngPaste", + "ngPattern", "ngPluralize", "ngReadonly", "ngRepeat", "ngRequired", "ngSelected", "ngShow", + "ngSrc", "ngSrcset", "ngStyle", "ngSubmit", "ngSwitch", "ngTransclude", "ngValue" + ] } private newtype TDirectiveInstance = @@ -676,10 +624,7 @@ private class JQLiteObject extends JQuery::ObjectSource::Range { ) ) or - exists(ServiceReference element | - element.getName() = "$rootElement" or - element.getName() = "$document" - | + exists(ServiceReference element | element.getName() = ["$rootElement", "$document"] | this = element.getAReference() ) } @@ -780,23 +725,17 @@ private class BuiltinServiceCall extends AngularJSCall { override predicate interpretsArgumentAsCode(Expr e) { exists(ScopeServiceReference scope, string methodName | - methodName = "$apply" or - methodName = "$applyAsync" or - methodName = "$eval" or - methodName = "$evalAsync" or - methodName = "$watch" or - methodName = "$watchCollection" or - methodName = "$watchGroup" + methodName = + [ + "$apply", "$applyAsync", "$eval", "$evalAsync", "$watch", "$watchCollection", + "$watchGroup" + ] | call = scope.getAMethodCall(methodName) and e = call.getArgument(0) ) or - exists(ServiceReference service | - service.getName() = "$compile" or - service.getName() = "$parse" or - service.getName() = "$interpolate" - | + exists(ServiceReference service | service.getName() = ["$compile", "$parse", "$interpolate"] | call = service.getACall() and e = call.getArgument(0) ) @@ -952,7 +891,7 @@ class ElementScope extends AngularScope, MkElementScope { DataFlow::SourceNode routeProviderRef() { result = builtinServiceRef("$routeProvider") or - exists(string m | m = "when" or m = "otherwise" | result = routeProviderRef().getAMethodCall(m)) + exists(string m | m = ["when", "otherwise"] | result = routeProviderRef().getAMethodCall(m)) } /** diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll index a984ec0c9e9..7eb1f760a46 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll @@ -277,24 +277,11 @@ private module Lexer { override string getPattern() { result = concat(string op | - op = "===" or - op = "!==" or - op = "==" or - op = "!=" or - op = "<=" or - op = ">=" or - op = "&&" or - op = "||" or - op = "*" or - op = "!" or - op = "=" or - op = "<" or - op = ">" or - op = "+" or - op = "-" or - op = "/" or - op = "%" or - op = "|" + op = + [ + "===", "!==", "==", "!=", "<=", ">=", "&&", "||", "*", "!", "=", "<", ">", "+", "-", + "/", "%", "|" + ] | "\\Q" + op + "\\E", "|" order by op.length() desc ) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll index 49cacd08aac..a0608d45253 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll @@ -103,25 +103,12 @@ module AsyncPackage { IterationCall() { this = memberVariant(name).getACall() and - ( - name = "concat" or - name = "detect" or - name = "each" or - name = "eachOf" or - name = "forEach" or - name = "forEachOf" or - name = "every" or - name = "filter" or - name = "groupBy" or - name = "map" or - name = "mapValues" or - name = "reduce" or - name = "reduceRight" or - name = "reject" or - name = "some" or - name = "sortBy" or - name = "transform" - ) + name = + [ + "concat", "detect", "each", "eachOf", "forEach", "forEachOf", "every", "filter", + "groupBy", "map", "mapValues", "reduce", "reduceRight", "reject", "some", "sortBy", + "transform" + ] } /** @@ -176,10 +163,7 @@ module AsyncPackage { pred = getLastParameter(iteratee).getACall().getArgument(i) and succ = final.getParameter(i) and exists(string name | name = call.getName() | - name = "concat" or - name = "map" or - name = "reduce" or - name = "reduceRight" + name = ["concat", "map", "reduce", "reduceRight"] ) ) } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll index 94f9c4245b1..742b4855bcc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll @@ -81,29 +81,12 @@ module HTTP { */ class RequestMethodName extends string { RequestMethodName() { - this = "CHECKOUT" or - this = "COPY" or - this = "DELETE" or - this = "GET" or - this = "HEAD" or - this = "LOCK" or - this = "MERGE" or - this = "MKACTIVITY" or - this = "MKCOL" or - this = "MOVE" or - this = "M-SEARCH" or - this = "NOTIFY" or - this = "OPTIONS" or - this = "PATCH" or - this = "POST" or - this = "PURGE" or - this = "PUT" or - this = "REPORT" or - this = "SEARCH" or - this = "SUBSCRIBE" or - this = "TRACE" or - this = "UNLOCK" or - this = "UNSUBSCRIBE" + this = + [ + "CHECKOUT", "COPY", "DELETE", "GET", "HEAD", "LOCK", "MERGE", "MKACTIVITY", "MKCOL", + "MOVE", "M-SEARCH", "NOTIFY", "OPTIONS", "PATCH", "POST", "PURGE", "PUT", "REPORT", + "SEARCH", "SUBSCRIBE", "TRACE", "UNLOCK", "UNSUBSCRIBE" + ] } /** @@ -111,14 +94,7 @@ module HTTP { * such as for `GET` and `HEAD` requests. */ predicate isSafe() { - this = "GET" or - this = "HEAD" or - this = "OPTIONS" or - this = "PRI" or - this = "PROPFIND" or - this = "REPORT" or - this = "SEARCH" or - this = "TRACE" + this = ["GET", "HEAD", "OPTIONS", "PRI", "PROPFIND", "REPORT", "SEARCH", "TRACE"] } } @@ -477,13 +453,7 @@ module HTTP { * Headers are never considered third-party controllable by this predicate, although the * third party does have some control over the the Referer and Origin headers. */ - predicate isThirdPartyControllable() { - exists(string kind | kind = getKind() | - kind = "parameter" or - kind = "url" or - kind = "body" - ) - } + predicate isThirdPartyControllable() { getKind() = ["parameter", "url", "body"] } } /** diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll index c05dbc3a8d6..467b2f5b18a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll @@ -47,312 +47,50 @@ module LodashUnderscore { */ private predicate isLodashMember(string name) { // Can be generated using Object.keys(require('lodash')) - name = "templateSettings" or - name = "after" or - name = "ary" or - name = "assign" or - name = "assignIn" or - name = "assignInWith" or - name = "assignWith" or - name = "at" or - name = "before" or - name = "bind" or - name = "bindAll" or - name = "bindKey" or - name = "castArray" or - name = "chain" or - name = "chunk" or - name = "compact" or - name = "concat" or - name = "cond" or - name = "conforms" or - name = "constant" or - name = "countBy" or - name = "create" or - name = "curry" or - name = "curryRight" or - name = "debounce" or - name = "defaults" or - name = "defaultsDeep" or - name = "defer" or - name = "delay" or - name = "difference" or - name = "differenceBy" or - name = "differenceWith" or - name = "drop" or - name = "dropRight" or - name = "dropRightWhile" or - name = "dropWhile" or - name = "fill" or - name = "filter" or - name = "flatMap" or - name = "flatMapDeep" or - name = "flatMapDepth" or - name = "flatten" or - name = "flattenDeep" or - name = "flattenDepth" or - name = "flip" or - name = "flow" or - name = "flowRight" or - name = "fromPairs" or - name = "functions" or - name = "functionsIn" or - name = "groupBy" or - name = "initial" or - name = "intersection" or - name = "intersectionBy" or - name = "intersectionWith" or - name = "invert" or - name = "invertBy" or - name = "invokeMap" or - name = "iteratee" or - name = "keyBy" or - name = "keys" or - name = "keysIn" or - name = "map" or - name = "mapKeys" or - name = "mapValues" or - name = "matches" or - name = "matchesProperty" or - name = "memoize" or - name = "merge" or - name = "mergeWith" or - name = "method" or - name = "methodOf" or - name = "mixin" or - name = "negate" or - name = "nthArg" or - name = "omit" or - name = "omitBy" or - name = "once" or - name = "orderBy" or - name = "over" or - name = "overArgs" or - name = "overEvery" or - name = "overSome" or - name = "partial" or - name = "partialRight" or - name = "partition" or - name = "pick" or - name = "pickBy" or - name = "property" or - name = "propertyOf" or - name = "pull" or - name = "pullAll" or - name = "pullAllBy" or - name = "pullAllWith" or - name = "pullAt" or - name = "range" or - name = "rangeRight" or - name = "rearg" or - name = "reject" or - name = "remove" or - name = "rest" or - name = "reverse" or - name = "sampleSize" or - name = "set" or - name = "setWith" or - name = "shuffle" or - name = "slice" or - name = "sortBy" or - name = "sortedUniq" or - name = "sortedUniqBy" or - name = "split" or - name = "spread" or - name = "tail" or - name = "take" or - name = "takeRight" or - name = "takeRightWhile" or - name = "takeWhile" or - name = "tap" or - name = "throttle" or - name = "thru" or - name = "toArray" or - name = "toPairs" or - name = "toPairsIn" or - name = "toPath" or - name = "toPlainObject" or - name = "transform" or - name = "unary" or - name = "union" or - name = "unionBy" or - name = "unionWith" or - name = "uniq" or - name = "uniqBy" or - name = "uniqWith" or - name = "unset" or - name = "unzip" or - name = "unzipWith" or - name = "update" or - name = "updateWith" or - name = "values" or - name = "valuesIn" or - name = "without" or - name = "words" or - name = "wrap" or - name = "xor" or - name = "xorBy" or - name = "xorWith" or - name = "zip" or - name = "zipObject" or - name = "zipObjectDeep" or - name = "zipWith" or - name = "entries" or - name = "entriesIn" or - name = "extend" or - name = "extendWith" or - name = "add" or - name = "attempt" or - name = "camelCase" or - name = "capitalize" or - name = "ceil" or - name = "clamp" or - name = "clone" or - name = "cloneDeep" or - name = "cloneDeepWith" or - name = "cloneWith" or - name = "conformsTo" or - name = "deburr" or - name = "defaultTo" or - name = "divide" or - name = "endsWith" or - name = "eq" or - name = "escape" or - name = "escapeRegExp" or - name = "every" or - name = "find" or - name = "findIndex" or - name = "findKey" or - name = "findLast" or - name = "findLastIndex" or - name = "findLastKey" or - name = "floor" or - name = "forEach" or - name = "forEachRight" or - name = "forIn" or - name = "forInRight" or - name = "forOwn" or - name = "forOwnRight" or - name = "get" or - name = "gt" or - name = "gte" or - name = "has" or - name = "hasIn" or - name = "head" or - name = "identity" or - name = "includes" or - name = "indexOf" or - name = "inRange" or - name = "invoke" or - name = "isArguments" or - name = "isArray" or - name = "isArrayBuffer" or - name = "isArrayLike" or - name = "isArrayLikeObject" or - name = "isBoolean" or - name = "isBuffer" or - name = "isDate" or - name = "isElement" or - name = "isEmpty" or - name = "isEqual" or - name = "isEqualWith" or - name = "isError" or - name = "isFinite" or - name = "isFunction" or - name = "isInteger" or - name = "isLength" or - name = "isMap" or - name = "isMatch" or - name = "isMatchWith" or - name = "isNaN" or - name = "isNative" or - name = "isNil" or - name = "isNull" or - name = "isNumber" or - name = "isObject" or - name = "isObjectLike" or - name = "isPlainObject" or - name = "isRegExp" or - name = "isSafeInteger" or - name = "isSet" or - name = "isString" or - name = "isSymbol" or - name = "isTypedArray" or - name = "isUndefined" or - name = "isWeakMap" or - name = "isWeakSet" or - name = "join" or - name = "kebabCase" or - name = "last" or - name = "lastIndexOf" or - name = "lowerCase" or - name = "lowerFirst" or - name = "lt" or - name = "lte" or - name = "max" or - name = "maxBy" or - name = "mean" or - name = "meanBy" or - name = "min" or - name = "minBy" or - name = "stubArray" or - name = "stubFalse" or - name = "stubObject" or - name = "stubString" or - name = "stubTrue" or - name = "multiply" or - name = "nth" or - name = "noConflict" or - name = "noop" or - name = "now" or - name = "pad" or - name = "padEnd" or - name = "padStart" or - name = "parseInt" or - name = "random" or - name = "reduce" or - name = "reduceRight" or - name = "repeat" or - name = "replace" or - name = "result" or - name = "round" or - name = "runInContext" or - name = "sample" or - name = "size" or - name = "snakeCase" or - name = "some" or - name = "sortedIndex" or - name = "sortedIndexBy" or - name = "sortedIndexOf" or - name = "sortedLastIndex" or - name = "sortedLastIndexBy" or - name = "sortedLastIndexOf" or - name = "startCase" or - name = "startsWith" or - name = "subtract" or - name = "sum" or - name = "sumBy" or - name = "template" or - name = "times" or - name = "toFinite" or - name = "toInteger" or - name = "toLength" or - name = "toLower" or - name = "toNumber" or - name = "toSafeInteger" or - name = "toString" or - name = "toUpper" or - name = "trim" or - name = "trimEnd" or - name = "trimStart" or - name = "truncate" or - name = "unescape" or - name = "uniqueId" or - name = "upperCase" or - name = "upperFirst" or - name = "each" or - name = "eachRight" or - name = "first" + name = + [ + "templateSettings", "after", "ary", "assign", "assignIn", "assignInWith", "assignWith", + "at", "before", "bind", "bindAll", "bindKey", "castArray", "chain", "chunk", "compact", + "concat", "cond", "conforms", "constant", "countBy", "create", "curry", "curryRight", + "debounce", "defaults", "defaultsDeep", "defer", "delay", "difference", "differenceBy", + "differenceWith", "drop", "dropRight", "dropRightWhile", "dropWhile", "fill", "filter", + "flatMap", "flatMapDeep", "flatMapDepth", "flatten", "flattenDeep", "flattenDepth", "flip", + "flow", "flowRight", "fromPairs", "functions", "functionsIn", "groupBy", "initial", + "intersection", "intersectionBy", "intersectionWith", "invert", "invertBy", "invokeMap", + "iteratee", "keyBy", "keys", "keysIn", "map", "mapKeys", "mapValues", "matches", + "matchesProperty", "memoize", "merge", "mergeWith", "method", "methodOf", "mixin", "negate", + "nthArg", "omit", "omitBy", "once", "orderBy", "over", "overArgs", "overEvery", "overSome", + "partial", "partialRight", "partition", "pick", "pickBy", "property", "propertyOf", "pull", + "pullAll", "pullAllBy", "pullAllWith", "pullAt", "range", "rangeRight", "rearg", "reject", + "remove", "rest", "reverse", "sampleSize", "set", "setWith", "shuffle", "slice", "sortBy", + "sortedUniq", "sortedUniqBy", "split", "spread", "tail", "take", "takeRight", + "takeRightWhile", "takeWhile", "tap", "throttle", "thru", "toArray", "toPairs", "toPairsIn", + "toPath", "toPlainObject", "transform", "unary", "union", "unionBy", "unionWith", "uniq", + "uniqBy", "uniqWith", "unset", "unzip", "unzipWith", "update", "updateWith", "values", + "valuesIn", "without", "words", "wrap", "xor", "xorBy", "xorWith", "zip", "zipObject", + "zipObjectDeep", "zipWith", "entries", "entriesIn", "extend", "extendWith", "add", + "attempt", "camelCase", "capitalize", "ceil", "clamp", "clone", "cloneDeep", + "cloneDeepWith", "cloneWith", "conformsTo", "deburr", "defaultTo", "divide", "endsWith", + "eq", "escape", "escapeRegExp", "every", "find", "findIndex", "findKey", "findLast", + "findLastIndex", "findLastKey", "floor", "forEach", "forEachRight", "forIn", "forInRight", + "forOwn", "forOwnRight", "get", "gt", "gte", "has", "hasIn", "head", "identity", "includes", + "indexOf", "inRange", "invoke", "isArguments", "isArray", "isArrayBuffer", "isArrayLike", + "isArrayLikeObject", "isBoolean", "isBuffer", "isDate", "isElement", "isEmpty", "isEqual", + "isEqualWith", "isError", "isFinite", "isFunction", "isInteger", "isLength", "isMap", + "isMatch", "isMatchWith", "isNaN", "isNative", "isNil", "isNull", "isNumber", "isObject", + "isObjectLike", "isPlainObject", "isRegExp", "isSafeInteger", "isSet", "isString", + "isSymbol", "isTypedArray", "isUndefined", "isWeakMap", "isWeakSet", "join", "kebabCase", + "last", "lastIndexOf", "lowerCase", "lowerFirst", "lt", "lte", "max", "maxBy", "mean", + "meanBy", "min", "minBy", "stubArray", "stubFalse", "stubObject", "stubString", "stubTrue", + "multiply", "nth", "noConflict", "noop", "now", "pad", "padEnd", "padStart", "parseInt", + "random", "reduce", "reduceRight", "repeat", "replace", "result", "round", "runInContext", + "sample", "size", "snakeCase", "some", "sortedIndex", "sortedIndexBy", "sortedIndexOf", + "sortedLastIndex", "sortedLastIndexBy", "sortedLastIndexOf", "startCase", "startsWith", + "subtract", "sum", "sumBy", "template", "times", "toFinite", "toInteger", "toLength", + "toLower", "toNumber", "toSafeInteger", "toString", "toUpper", "trim", "trimEnd", + "trimStart", "truncate", "unescape", "uniqueId", "upperCase", "upperFirst", "each", + "eachRight", "first" + ] } /** @@ -363,27 +101,9 @@ module LodashUnderscore { exists(DataFlow::CallNode call, string name | // Members ending with By, With, or While indicate that they are a variant of // another function that takes a callback. - name.matches("%By") or - name.matches("%With") or - name.matches("%While") or + name.matches(["%By", "%With", "%While"]) or // Other members that don't fit the above pattern. - name = "each" or - name = "eachRight" or - name = "every" or - name = "filter" or - name = "find" or - name = "findLast" or - name = "flatMap" or - name = "flatMapDeep" or - name = "flatMapDepth" or - name = "forEach" or - name = "forEachRight" or - name = "partition" or - name = "reduce" or - name = "reduceRight" or - name = "replace" or - name = "some" or - name = "transform" + name = ["each", "eachRight", "every", "filter", "find", "findLast", "flatMap", "flatMapDeep", "flatMapDepth", "forEach", "forEachRight", "partition", "reduce", "reduceRight", "replace", "some", "transform"] | call = member(name).getACall() and pred = call.getAnArgument().(DataFlow::FunctionNode).getExceptionalReturn() and @@ -462,86 +182,72 @@ private class LodashCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode: getNumArgument() = argumentCount | ( - name = "bind" or - name = "callback" or - name = "iteratee" + name = ["bind", "callback", "iteratee"] ) and callbackIndex = 0 and contextIndex = 1 and argumentCount = 2 or ( - name = "all" or - name = "any" or - name = "collect" or - name = "countBy" or - name = "detect" or - name = "dropRightWhile" or - name = "dropWhile" or - name = "each" or - name = "eachRight" or - name = "every" or - name = "filter" or - name = "find" or - name = "findIndex" or - name = "findKey" or - name = "findLast" or - name = "findLastIndex" or - name = "findLastKey" or - name = "forEach" or - name = "forEachRight" or - name = "forIn" or - name = "forInRight" or - name = "groupBy" or - name = "indexBy" or - name = "map" or - name = "mapKeys" or - name = "mapValues" or - name = "max" or - name = "min" or - name = "omit" or - name = "partition" or - name = "pick" or - name = "reject" or - name = "remove" or - name = "select" or - name = "some" or - name = "sortBy" or - name = "sum" or - name = "takeRightWhile" or - name = "takeWhile" or - name = "tap" or - name = "thru" or - name = "times" or - name = "unzipWith" or - name = "zipWith" + name = [ + "all", + "any", + "collect", + "countBy", + "detect", + "dropRightWhile", + "dropWhile", + "each", + "eachRight", + "every", + "filter", + "find", + "findIndex", + "findKey", + "findLast", + "findLastIndex", + "findLastKey", + "forEach", + "forEachRight", + "forIn", + "forInRight", + "groupBy", + "indexBy", + "map", + "mapKeys", + "mapValues", + "max", + "min", + "omit", + "partition", + "pick", + "reject", + "remove", + "select", + "some", + "sortBy", + "sum", + "takeRightWhile", + "takeWhile", + "tap", + "thru", + "times", + "unzipWith", + "zipWith"] ) and callbackIndex = 1 and contextIndex = 2 and argumentCount = 3 or ( - name = "foldl" or - name = "foldr" or - name = "inject" or - name = "reduce" or - name = "reduceRight" or - name = "transform" + name = ["foldl", "foldr", "inject", "reduce", "reduceRight", "transform"] ) and callbackIndex = 1 and contextIndex = 3 and argumentCount = 4 or ( - name = "sortedlastIndex" - or - name = "assign" - or - name = "eq" - or - name = "extend" - or - name = "merge" + name = ["sortedlastIndex", "assign", "eq", "extend", "merge"] or name = "sortedIndex" and name = "uniq" diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll index a8151180f9b..c83a3bf85af 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll @@ -29,20 +29,11 @@ module TaintedUrlSuffix { /** Holds for `pred -> succ` is a step of form `x -> x.p` */ private predicate isSafeLocationProp(DataFlow::PropRead read) { // Ignore properties that refer to the scheme, domain, port, auth, or path. - exists(string name | name = read.getPropertyName() | - name = "protocol" or - name = "scheme" or - name = "host" or - name = "hostname" or - name = "domain" or - name = "origin" or - name = "port" or - name = "path" or - name = "pathname" or - name = "username" or - name = "password" or - name = "auth" - ) + read.getPropertyName() = + [ + "protocol", "scheme", "host", "hostname", "domain", "origin", "port", "path", "pathname", + "username", "password", "auth" + ] } /** diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll index 65d3b44dafa..f426dd050c8 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll @@ -88,12 +88,7 @@ module ClientSideUrlRedirect { class LocationSink extends Sink, DataFlow::ValueNode { LocationSink() { // A call to a `window.navigate` or `window.open` - exists(string name | - name = "navigate" or - name = "open" or - name = "openDialog" or - name = "showModalDialog" - | + exists(string name | name = ["navigate", "open", "openDialog", "showModalDialog"] | this = DataFlow::globalVarRef(name).getACall().getArgument(0) ) or @@ -102,7 +97,7 @@ module ClientSideUrlRedirect { locationCall = DOM::locationRef().getAMethodCall(name) and this = locationCall.getArgument(0) | - name = "replace" or name = "assign" + name = ["replace", "assign"] ) or // An assignment to `location` @@ -113,7 +108,7 @@ module ClientSideUrlRedirect { pw = DOM::locationRef().getAPropertyWrite(propName) and this = pw.getRhs() | - propName = "href" or propName = "protocol" or propName = "hostname" + propName = ["href", "protocol", "hostname"] ) or // A redirection using the AngularJS `$location` service @@ -153,9 +148,8 @@ module ClientSideUrlRedirect { */ class SrcAttributeUrlSink extends ScriptUrlSink, DataFlow::ValueNode { SrcAttributeUrlSink() { - exists(DOM::AttributeDefinition attr, string eltName | - attr.getElement().getName() = eltName and - (eltName = "script" or eltName = "iframe") and + exists(DOM::AttributeDefinition attr | + attr.getElement().getName() = ["script", "iframe"] and attr.getName() = "src" and this = attr.getValueNode() ) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll index 8e3857d049b..9a44bf2d41f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll @@ -115,66 +115,18 @@ module LoopBoundInjection { * Holds if `name` is a method from lodash vulnerable to a DoS attack if called with a tainted object. */ predicate loopableLodashMethod(string name) { - name = "chunk" or - name = "compact" or - name = "difference" or - name = "differenceBy" or - name = "differenceWith" or - name = "drop" or - name = "dropRight" or - name = "dropRightWhile" or - name = "dropWhile" or - name = "fill" or - name = "findIndex" or - name = "findLastIndex" or - name = "flatten" or - name = "flattenDeep" or - name = "flattenDepth" or - name = "initial" or - name = "intersection" or - name = "intersectionBy" or - name = "intersectionWith" or - name = "join" or - name = "remove" or - name = "reverse" or - name = "slice" or - name = "sortedUniq" or - name = "sortedUniqBy" or - name = "tail" or - name = "union" or - name = "unionBy" or - name = "unionWith" or - name = "uniqBy" or - name = "unzip" or - name = "unzipWith" or - name = "without" or - name = "zip" or - name = "zipObject" or - name = "zipObjectDeep" or - name = "zipWith" or - name = "countBy" or - name = "each" or - name = "forEach" or - name = "eachRight" or - name = "forEachRight" or - name = "filter" or - name = "find" or - name = "findLast" or - name = "flatMap" or - name = "flatMapDeep" or - name = "flatMapDepth" or - name = "forEach" or - name = "forEachRight" or - name = "groupBy" or - name = "invokeMap" or - name = "keyBy" or - name = "map" or - name = "orderBy" or - name = "partition" or - name = "reduce" or - name = "reduceRight" or - name = "reject" or - name = "sortBy" + name = + [ + "chunk", "compact", "difference", "differenceBy", "differenceWith", "drop", "dropRight", + "dropRightWhile", "dropWhile", "fill", "findIndex", "findLastIndex", "flatten", + "flattenDeep", "flattenDepth", "initial", "intersection", "intersectionBy", + "intersectionWith", "join", "remove", "reverse", "slice", "sortedUniq", "sortedUniqBy", + "tail", "union", "unionBy", "unionWith", "uniqBy", "unzip", "unzipWith", "without", "zip", + "zipObject", "zipObjectDeep", "zipWith", "countBy", "each", "forEach", "eachRight", + "forEachRight", "filter", "find", "findLast", "flatMap", "flatMapDeep", "flatMapDepth", + "forEach", "forEachRight", "groupBy", "invokeMap", "keyBy", "map", "orderBy", "partition", + "reduce", "reduceRight", "reject", "sortBy" + ] } /** diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 117e22eb867..08928946eb5 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -111,16 +111,11 @@ predicate callToVoidFunction(DataFlow::CallNode call, Function func) { * and the callback is expected to return a value. */ predicate hasNonVoidCallbackMethod(string name) { - name = "every" or - name = "filter" or - name = "find" or - name = "findIndex" or - name = "flatMap" or - name = "map" or - name = "reduce" or - name = "reduceRight" or - name = "some" or - name = "sort" + name = + [ + "every", "filter", "find", "findIndex", "flatMap", "map", "reduce", "reduceRight", "some", + "sort" + ] } DataFlow::SourceNode array(DataFlow::TypeTracker t) { diff --git a/javascript/ql/src/meta/Consistency.ql b/javascript/ql/src/meta/Consistency.ql index b87c256f609..3e2ec0c412a 100644 --- a/javascript/ql/src/meta/Consistency.ql +++ b/javascript/ql/src/meta/Consistency.ql @@ -37,22 +37,12 @@ predicate exprWithoutEnclosingStmt(Expr e) { * `"3 results for toString()"`. */ predicate uniqueness_error(int number, string what, string problem) { - ( - what = "toString" or - what = "getLocation" or - what = "getTopLevel" or - what = "getEnclosingStmt" or - what = "getContainer" or - what = "getEnclosingContainer" or - what = "getEntry" or - what = "getExit" or - what = "getFirstControlFlowNode" or - what = "getOuterScope" or - what = "getScopeElement" or - what = "getBaseName" or - what = "getOperator" or - what = "getTest" - ) and + what = + [ + "toString", "getLocation", "getTopLevel", "getEnclosingStmt", "getContainer", + "getEnclosingContainer", "getEntry", "getExit", "getFirstControlFlowNode", "getOuterScope", + "getScopeElement", "getBaseName", "getOperator", "getTest" + ] and ( number = 0 and problem = "no results for " + what + "()" or From b9cce57db49ba5d5aa77bb5b077c07646358546d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 13 Oct 2021 16:39:36 +0100 Subject: [PATCH 286/361] JS: Fix mistake. --- .../frameworks/LodashUnderscore.qll | 81 +++++-------------- 1 file changed, 20 insertions(+), 61 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll index 467b2f5b18a..714eeab3135 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll @@ -101,9 +101,15 @@ module LodashUnderscore { exists(DataFlow::CallNode call, string name | // Members ending with By, With, or While indicate that they are a variant of // another function that takes a callback. - name.matches(["%By", "%With", "%While"]) or + name.matches(["%By", "%With", "%While"]) + or // Other members that don't fit the above pattern. - name = ["each", "eachRight", "every", "filter", "find", "findLast", "flatMap", "flatMapDeep", "flatMapDepth", "forEach", "forEachRight", "partition", "reduce", "reduceRight", "replace", "some", "transform"] + name = + [ + "each", "eachRight", "every", "filter", "find", "findLast", "flatMap", "flatMapDeep", + "flatMapDepth", "forEach", "forEachRight", "partition", "reduce", "reduceRight", + "replace", "some", "transform" + ] | call = member(name).getACall() and pred = call.getAnArgument().(DataFlow::FunctionNode).getExceptionalReturn() and @@ -181,77 +187,30 @@ private class LodashCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode: this = LodashUnderscore::member(name).getACall() and getNumArgument() = argumentCount | - ( - name = ["bind", "callback", "iteratee"] - ) and + name = ["bind", "callback", "iteratee"] and callbackIndex = 0 and contextIndex = 1 and argumentCount = 2 or - ( - name = [ - "all", - "any", - "collect", - "countBy", - "detect", - "dropRightWhile", - "dropWhile", - "each", - "eachRight", - "every", - "filter", - "find", - "findIndex", - "findKey", - "findLast", - "findLastIndex", - "findLastKey", - "forEach", - "forEachRight", - "forIn", - "forInRight", - "groupBy", - "indexBy", - "map", - "mapKeys", - "mapValues", - "max", - "min", - "omit", - "partition", - "pick", - "reject", - "remove", - "select", - "some", - "sortBy", - "sum", - "takeRightWhile", - "takeWhile", - "tap", - "thru", - "times", - "unzipWith", - "zipWith"] - ) and + name = + [ + "all", "any", "collect", "countBy", "detect", "dropRightWhile", "dropWhile", "each", + "eachRight", "every", "filter", "find", "findIndex", "findKey", "findLast", + "findLastIndex", "findLastKey", "forEach", "forEachRight", "forIn", "forInRight", + "groupBy", "indexBy", "map", "mapKeys", "mapValues", "max", "min", "omit", "partition", + "pick", "reject", "remove", "select", "some", "sortBy", "sum", "takeRightWhile", + "takeWhile", "tap", "thru", "times", "unzipWith", "zipWith" + ] and callbackIndex = 1 and contextIndex = 2 and argumentCount = 3 or - ( - name = ["foldl", "foldr", "inject", "reduce", "reduceRight", "transform"] - ) and + name = ["foldl", "foldr", "inject", "reduce", "reduceRight", "transform"] and callbackIndex = 1 and contextIndex = 3 and argumentCount = 4 or - ( - name = ["sortedlastIndex", "assign", "eq", "extend", "merge"] - or - name = "sortedIndex" and - name = "uniq" - ) and + name = ["sortedlastIndex", "assign", "eq", "extend", "merge", "sortedIndex", "uniq"] and callbackIndex = 2 and contextIndex = 3 and argumentCount = 4 From 9d63efe495353ed31283260c3c8e666a6bdb24ec Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 13 Oct 2021 17:47:01 +0100 Subject: [PATCH 287/361] Python: Set literals. --- .../python/concepts/CryptoAlgorithms.qll | 71 +++++-------------- .../ql/lib/semmle/python/objects/TObject.qll | 29 +++----- .../lib/semmle/python/security/ClearText.qll | 6 +- .../python/security/injection/Command.qll | 12 +--- 4 files changed, 29 insertions(+), 89 deletions(-) diff --git a/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll index a5bfd6696be..4b3c5f2a49f 100644 --- a/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll +++ b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll @@ -15,72 +15,35 @@ */ private module AlgorithmNames { predicate isStrongHashingAlgorithm(string name) { - name = "DSA" or - name = "ED25519" or - name = "ES256" or - name = "ECDSA256" or - name = "ES384" or - name = "ECDSA384" or - name = "ES512" or - name = "ECDSA512" or - name = "SHA2" or - name = "SHA224" or - name = "SHA256" or - name = "SHA384" or - name = "SHA512" or - name = "SHA3" or - name = "SHA3224" or - name = "SHA3256" or - name = "SHA3384" or - name = "SHA3512" + name = + [ + "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", + "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512" + ] } predicate isWeakHashingAlgorithm(string name) { - name = "HAVEL128" or - name = "MD2" or - name = "MD4" or - name = "MD5" or - name = "PANAMA" or - name = "RIPEMD" or - name = "RIPEMD128" or - name = "RIPEMD256" or - name = "RIPEMD160" or - name = "RIPEMD320" or - name = "SHA0" or - name = "SHA1" + name = + [ + "HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD", "RIPEMD128", "RIPEMD256", "RIPEMD160", + "RIPEMD320", "SHA0", "SHA1" + ] } predicate isStrongEncryptionAlgorithm(string name) { - name = "AES" or - name = "AES128" or - name = "AES192" or - name = "AES256" or - name = "AES512" or - name = "RSA" or - name = "RABBIT" or - name = "BLOWFISH" + name = ["AES", "AES128", "AES192", "AES256", "AES512", "RSA", "RABBIT", "BLOWFISH"] } predicate isWeakEncryptionAlgorithm(string name) { - name = "DES" or - name = "3DES" or - name = "TRIPLEDES" or - name = "TDEA" or - name = "TRIPLEDEA" or - name = "ARC2" or - name = "RC2" or - name = "ARC4" or - name = "RC4" or - name = "ARCFOUR" or - name = "ARC5" or - name = "RC5" + name = + [ + "DES", "3DES", "TRIPLEDES", "TDEA", "TRIPLEDEA", "ARC2", "RC2", "ARC4", "RC4", "ARCFOUR", + "ARC5", "RC5" + ] } predicate isStrongPasswordHashingAlgorithm(string name) { - name = "ARGON2" or - name = "PBKDF2" or - name = "BCRYPT" or - name = "SCRYPT" + name = ["ARGON2", "PBKDF2", "BCRYPT", "SCRYPT"] } predicate isWeakPasswordHashingAlgorithm(string name) { none() } diff --git a/python/ql/lib/semmle/python/objects/TObject.qll b/python/ql/lib/semmle/python/objects/TObject.qll index d83d47af1ee..99eb05aa795 100644 --- a/python/ql/lib/semmle/python/objects/TObject.qll +++ b/python/ql/lib/semmle/python/objects/TObject.qll @@ -387,7 +387,7 @@ private predicate concrete_class(PythonClassObjectInternal cls) { not exists(Raise r, Name ex | r.getScope() = f and (r.getException() = ex or r.getException().(Call).getFunc() = ex) and - (ex.getId() = "NotImplementedError" or ex.getId() = "NotImplemented") + ex.getId() = ["NotImplementedError", "NotImplemented"] ) ) ) @@ -437,11 +437,7 @@ predicate missing_imported_module(ControlFlowNode imp, Context ctx, string name) * Helper for missing modules to determine if name `x.y` is a module `x.y` or * an attribute `y` of module `x`. This list should be added to as required. */ -predicate common_module_name(string name) { - name = "zope.interface" - or - name = "six.moves" -} +predicate common_module_name(string name) { name = ["zope.interface", "six.moves"] } /** * A declaration of a class, either a built-in class or a source definition @@ -482,16 +478,11 @@ library class ClassDecl extends @py_object { */ predicate isSpecial() { exists(string name | this = Builtin::special(name) | - name = "type" or - name = "super" or - name = "bool" or - name = "NoneType" or - name = "tuple" or - name = "property" or - name = "ClassMethod" or - name = "StaticMethod" or - name = "MethodType" or - name = "ModuleType" + name = + [ + "type", "super", "bool", "NoneType", "tuple", "property", "ClassMethod", "StaticMethod", + "MethodType", "ModuleType" + ] ) } @@ -514,11 +505,7 @@ library class ClassDecl extends @py_object { /** Holds if this class is the abstract base class */ predicate isAbstractBaseClass(string name) { - exists(Module m | - m.getName() = "_abcoll" - or - m.getName() = "_collections_abc" - | + exists(Module m | m.getName() = ["_abcoll", "_collections_abc"] | this.getClass().getScope() = m and this.getName() = name ) diff --git a/python/ql/lib/semmle/python/security/ClearText.qll b/python/ql/lib/semmle/python/security/ClearText.qll index 8e964d19386..9905040da18 100644 --- a/python/ql/lib/semmle/python/security/ClearText.qll +++ b/python/ql/lib/semmle/python/security/ClearText.qll @@ -47,11 +47,7 @@ module ClearTextLogging { meth.getObject(name).(NameNode).getId().matches("logg%") and call.getAnArg() = this | - name = "error" or - name = "warn" or - name = "warning" or - name = "debug" or - name = "info" + name = ["error", "warn", "warning", "debug", "info"] ) } } diff --git a/python/ql/lib/semmle/python/security/injection/Command.qll b/python/ql/lib/semmle/python/security/injection/Command.qll index 3ed453268ee..6e4bb490fa4 100644 --- a/python/ql/lib/semmle/python/security/injection/Command.qll +++ b/python/ql/lib/semmle/python/security/injection/Command.qll @@ -14,17 +14,12 @@ import semmle.python.security.strings.Untrusted abstract class CommandSink extends TaintSink { } private ModuleObject osOrPopenModule() { - result.getName() = "os" or - result.getName() = "popen2" + result.getName() = ["os", "popen2"] } private Object makeOsCall() { exists(string name | result = ModuleObject::named("subprocess").attr(name) | - name = "Popen" or - name = "call" or - name = "check_call" or - name = "check_output" or - name = "run" + name = ["Popen", "call", "check_call", "check_output", "run"] ) } @@ -65,8 +60,7 @@ class ShellCommand extends CommandSink { call.getAnArg() = this and call.getFunction().refersTo(osOrPopenModule().attr(name)) | - name = "system" or - name = "popen" or + name = ["system", "popen"] or name.matches("popen_") ) or From cb5f2559ea97e82efa23ac014432f11da915153c Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Thu, 14 Oct 2021 15:54:54 +0200 Subject: [PATCH 288/361] Java: Fix performance problem due to transitive step. --- java/ql/lib/semmle/code/java/frameworks/spring/SpringHttp.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringHttp.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringHttp.qll index 2d313cc8584..d03cea80850 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringHttp.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringHttp.qll @@ -280,7 +280,7 @@ private DataFlow::Node getABodyBuilderWithExplicitContentType(Expr contentType) .hasQualifiedName("org.springframework.http", "ResponseEntity$BodyBuilder") ) or - DataFlow::localFlow(getABodyBuilderWithExplicitContentType(contentType), result) + DataFlow::localFlowStep(getABodyBuilderWithExplicitContentType(contentType), result) } private DataFlow::Node getASanitizedBodyBuilder() { From 310eec07c1e64717a27850b55d3493d1f15c7843 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Thu, 14 Oct 2021 16:10:00 +0200 Subject: [PATCH 289/361] Java/Python: Fix some potential performance problems due to transitive deltas. --- java/ql/lib/semmle/code/java/frameworks/Rmi.qll | 2 +- python/ql/lib/semmle/python/Exprs.qll | 2 +- python/ql/lib/semmle/python/pointsto/PointsTo.qll | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/Rmi.qll b/java/ql/lib/semmle/code/java/frameworks/Rmi.qll index 80243b3ddf8..74a449086cf 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Rmi.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Rmi.qll @@ -14,5 +14,5 @@ class RemoteCallableMethod extends Method { private predicate remoteCallableMethod(Method method) { method.getDeclaringType().getASupertype() instanceof TypeRemote or - exists(Method meth | remoteCallableMethod(meth) and method.getAnOverride() = meth) + exists(Method meth | remoteCallableMethod(meth) and method.overrides(meth)) } diff --git a/python/ql/lib/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll index 5a56a704b6f..5afa651de22 100644 --- a/python/ql/lib/semmle/python/Exprs.qll +++ b/python/ql/lib/semmle/python/Exprs.qll @@ -17,7 +17,7 @@ class Expr extends Expr_, AstNode { * Whether this expression defines variable `v` * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. */ - predicate defines(Variable v) { this.getASubExpression+().defines(v) } + predicate defines(Variable v) { this.getASubExpression().defines(v) } /** Whether this expression may have a side effect (as determined purely from its syntax) */ predicate hasSideEffects() { diff --git a/python/ql/lib/semmle/python/pointsto/PointsTo.qll b/python/ql/lib/semmle/python/pointsto/PointsTo.qll index 48bbb283d07..548b25115ae 100644 --- a/python/ql/lib/semmle/python/pointsto/PointsTo.qll +++ b/python/ql/lib/semmle/python/pointsto/PointsTo.qll @@ -300,7 +300,7 @@ module PointsToInternal { ssa_definition_points_to(var.getDefinition(), context, value, origin) or exists(EssaVariable prev | - ssaShortCut+(prev, var) and + ssaShortCut(prev, var) and variablePointsTo(prev, context, value, origin) ) } From 75066813eeab9862cef5d7a49ebcd2608e6ea366 Mon Sep 17 00:00:00 2001 From: hubwriter <hubwriter@github.com> Date: Thu, 14 Oct 2021 15:51:28 +0100 Subject: [PATCH 290/361] Add more Ruby refs as per CD plan --- docs/codeql/codeql-cli/about-ql-packs.rst | 2 +- .../codeql-cli/creating-codeql-databases.rst | 21 ++++++++++++++----- .../getting-started-with-the-codeql-cli.rst | 2 +- ...etting-up-codeql-in-visual-studio-code.rst | 2 +- .../codeql/query-help/codeql-cwe-coverage.rst | 2 ++ docs/codeql/query-help/index.rst | 3 ++- docs/codeql/reusables/extractors.rst | 4 +++- docs/codeql/reusables/ruby-beta-note.rst | 4 ++++ .../creating-path-queries.rst | 2 +- 9 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 docs/codeql/reusables/ruby-beta-note.rst diff --git a/docs/codeql/codeql-cli/about-ql-packs.rst b/docs/codeql/codeql-cli/about-ql-packs.rst index dc47f2a023b..fb5a1d8a8a0 100644 --- a/docs/codeql/codeql-cli/about-ql-packs.rst +++ b/docs/codeql/codeql-cli/about-ql-packs.rst @@ -7,7 +7,7 @@ QL packs are used to organize the files used in CodeQL analysis. They contain queries, library files, query suites, and important metadata. The `CodeQL repository <https://github.com/github/codeql>`__ contains QL packs for -C/C++, C#, Java, JavaScript, and Python. The `CodeQL for Go +C/C++, C#, Java, JavaScript, Python, and Ruby. The `CodeQL for Go <https://github.com/github/codeql-go/>`__ repository contains a QL pack for Go analysis. You can also make custom QL packs to contain your own queries and libraries. diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index 52bd076e636..93a2471793a 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -88,15 +88,15 @@ Creating databases for non-compiled languages --------------------------------------------- The CodeQL CLI includes extractors to create databases for non-compiled -languages---specifically, JavaScript (and TypeScript) and Python. These -extractors are automatically invoked when you specify JavaScript or Python as +languages---specifically, JavaScript (and TypeScript), Python, and Ruby. These +extractors are automatically invoked when you specify JavaScript, Python, or Ruby as the ``--language`` option when executing ``database create``. When creating databases for these languages you must ensure that all additional dependencies are available. .. pull-quote:: Important - When you run ``database create`` for JavaScript, TypeScript, and Python, you should not + When you run ``database create`` for JavaScript, TypeScript, Python, and Ruby, you should not specify a ``--command`` option. Otherwise this overrides the normal extractor invocation, which will create an empty database. If you create databases for multiple languages and one of them is a compiled language, @@ -127,14 +127,25 @@ When creating databases for Python you must ensure: packages that the codebase depends on. - You have installed the `virtualenv <https://pypi.org/project/virtualenv/>`__ pip module. -In the command line you must specify ``--language=python``. For example +In the command line you must specify ``--language=python``. For example:: :: codeql database create --language=python <output-folder>/python-database -executes the ``database create`` subcommand from the code's checkout root, +This executes the ``database create`` subcommand from the code's checkout root, generating a new Python database at ``<output-folder>/python-database``. +Ruby +~~~~ + +Creating databases for Ruby requires no additional dependencies. +In the command line you must specify ``--language=ruby``. For example:: + + codeql database create --language=ruby --source-root <folder-to-extract> <output-folder>/ruby-database + +Here, we have specified a ``--source-root`` path, which is the location where +database creation is executed, but is not necessarily the checkout root of the +codebase. Creating databases for compiled languages ----------------------------------------- diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index 1144c1c3e6c..a8ef822a628 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -100,7 +100,7 @@ further options on the command line. The `CodeQL repository <https://github.com/github/codeql>`__ contains the queries and libraries required for CodeQL analysis of C/C++, C#, Java, -JavaScript/TypeScript, and Python. +JavaScript/TypeScript, Python, and Ruby. Clone a copy of this repository into ``codeql-home``. By default, the root of the cloned repository will be called ``codeql``. diff --git a/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst b/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst index 0075826d421..a43c69edecb 100644 --- a/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst +++ b/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst @@ -78,7 +78,7 @@ Using the starter workspace ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The starter workspace is a Git repository. It contains: -* The `repository of CodeQL libraries and queries <https://github.com/github/codeql>`__ for C/C++, C#, Java, JavaScript, and Python. This is included as a submodule, so it can be updated without affecting your custom queries. +* The `repository of CodeQL libraries and queries <https://github.com/github/codeql>`__ for C/C++, C#, Java, JavaScript, Python, and Ruby. This is included as a submodule, so it can be updated without affecting your custom queries. * The `repository of CodeQL libraries and queries <https://github.com/github/codeql-go>`__ for Go. This is also included as a submodule. * A series of folders named ``codeql-custom-queries-<language>``. These are ready for you to start developing your own custom queries for each language, using the standard libraries. There are some example queries to get you started. diff --git a/docs/codeql/query-help/codeql-cwe-coverage.rst b/docs/codeql/query-help/codeql-cwe-coverage.rst index b333053a1c8..cc538196b4f 100644 --- a/docs/codeql/query-help/codeql-cwe-coverage.rst +++ b/docs/codeql/query-help/codeql-cwe-coverage.rst @@ -33,3 +33,5 @@ Note that the CWE coverage includes both "`supported queries <https://github.com java-cwe javascript-cwe python-cwe + +.. include:: ../reusables/ruby-beta-note.rst diff --git a/docs/codeql/query-help/index.rst b/docs/codeql/query-help/index.rst index 10e4b0dff20..7c987cc09ec 100644 --- a/docs/codeql/query-help/index.rst +++ b/docs/codeql/query-help/index.rst @@ -10,7 +10,6 @@ View the query help for the queries included in the ``code-scanning``, ``securit - :doc:`CodeQL query help for JavaScript <javascript>` - :doc:`CodeQL query help for Python <python>` - .. pull-quote:: Information Each query help article includes: @@ -23,6 +22,8 @@ View the query help for the queries included in the ``code-scanning``, ``securit For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE coverage <codeql-cwe-coverage>`." +.. include:: ../reusables/ruby-beta-note.rst + .. toctree:: :hidden: :titlesonly: diff --git a/docs/codeql/reusables/extractors.rst b/docs/codeql/reusables/extractors.rst index 9076f7a768d..a3a4952811d 100644 --- a/docs/codeql/reusables/extractors.rst +++ b/docs/codeql/reusables/extractors.rst @@ -15,4 +15,6 @@ * - JavaScript/TypeScript - ``javascript`` * - Python - - ``python`` \ No newline at end of file + - ``python`` + * - Ruby + - ``ruby`` \ No newline at end of file diff --git a/docs/codeql/reusables/ruby-beta-note.rst b/docs/codeql/reusables/ruby-beta-note.rst new file mode 100644 index 00000000000..761381777c0 --- /dev/null +++ b/docs/codeql/reusables/ruby-beta-note.rst @@ -0,0 +1,4 @@ + .. pull-quote:: Note + + CodeQL analysis for Ruby is currently in beta. During the beta, analysis of Ruby code, + and the accompanying documentation, will not be as comprehensive as for other languages. diff --git a/docs/codeql/writing-codeql-queries/creating-path-queries.rst b/docs/codeql/writing-codeql-queries/creating-path-queries.rst index 60723f488e1..3eb67207ccd 100644 --- a/docs/codeql/writing-codeql-queries/creating-path-queries.rst +++ b/docs/codeql/writing-codeql-queries/creating-path-queries.rst @@ -116,7 +116,7 @@ Declaring sources and sinks You must provide information about the ``source`` and ``sink`` in your path query. These are objects that correspond to the nodes of the paths that you are exploring. The name and the type of the ``source`` and the ``sink`` must be declared in the ``from`` statement of the query, and the types must be compatible with the nodes of the graph computed by the ``edges`` predicate. -If you are querying C/C++, C#, Java, or JavaScript code (and you have used ``import DataFlow::PathGraph`` in your query), the definitions of the ``source`` and ``sink`` are accessed via the ``Configuration`` class in the data flow library. You should declare all three of these objects in the ``from`` statement. +If you are querying C/C++, C#, Java, JavaScript, or Ruby code (and you have used ``import DataFlow::PathGraph`` in your query), the definitions of the ``source`` and ``sink`` are accessed via the ``Configuration`` class in the data flow library. You should declare all three of these objects in the ``from`` statement. For example: .. code-block:: ql From 8f30b8b5860dcc94f479b305ff3159ec7e98c024 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 14 Oct 2021 16:00:23 +0100 Subject: [PATCH 291/361] Autoformat. --- cpp/ql/lib/semmle/code/cpp/Specifier.qll | 12 +++--------- .../csharp/security/dataflow/flowsources/Remote.qll | 3 ++- .../lib/semmle/javascript/DynamicPropertyAccess.qll | 2 +- .../lib/semmle/python/security/injection/Command.qll | 4 +--- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/Specifier.qll b/cpp/ql/lib/semmle/code/cpp/Specifier.qll index a60726252a1..4fe2fecb32e 100644 --- a/cpp/ql/lib/semmle/code/cpp/Specifier.qll +++ b/cpp/ql/lib/semmle/code/cpp/Specifier.qll @@ -31,9 +31,7 @@ class Specifier extends Element, @specifier { * A C/C++ function specifier: `inline`, `virtual`, or `explicit`. */ class FunctionSpecifier extends Specifier { - FunctionSpecifier() { - this.hasName(["inline", "virtual", "explicit"]) - } + FunctionSpecifier() { this.hasName(["inline", "virtual", "explicit"]) } override string getAPrimaryQlClass() { result = "FunctionSpecifier" } } @@ -43,9 +41,7 @@ class FunctionSpecifier extends Specifier { * or `mutable". */ class StorageClassSpecifier extends Specifier { - StorageClassSpecifier() { - this.hasName(["auto", "register", "static", "extern", "mutable"]) - } + StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) } override string getAPrimaryQlClass() { result = "StorageClassSpecifier" } } @@ -54,9 +50,7 @@ class StorageClassSpecifier extends Specifier { * A C++ access specifier: `public`, `protected`, or `private`. */ class AccessSpecifier extends Specifier { - AccessSpecifier() { - this.hasName(["public", "protected", "private"]) - } + AccessSpecifier() { this.hasName(["public", "protected", "private"]) } /** * Gets the visibility of a field with access specifier `this` if it is diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll index 6b3746f36f0..2448f80e8ba 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll @@ -43,7 +43,8 @@ class AspNetQueryStringMember extends Member { * request. */ private string getHttpRequestFlowPropertyNames() { - result = ["QueryString", "Headers", "RawUrl", "Url", "Cookies", "Form", "Params", "Path", "PathInfo"] + result = + ["QueryString", "Headers", "RawUrl", "Url", "Cookies", "Form", "Params", "Path", "PathInfo"] } /** A data flow source of remote user input (ASP.NET query string). */ diff --git a/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll index 89a65b13ebd..b7308ca5ad4 100644 --- a/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll +++ b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll @@ -14,7 +14,7 @@ private import semmle.javascript.dataflow.internal.FlowSteps SourceNode getAnEnumeratedArrayElement(SourceNode array) { exists(MethodCallNode call, string name | call = array.getAMethodCall(name) and - (name = ["forEach", "map"]) and + name = ["forEach", "map"] and result = call.getCallback(0).getParameter(0) ) or diff --git a/python/ql/lib/semmle/python/security/injection/Command.qll b/python/ql/lib/semmle/python/security/injection/Command.qll index 6e4bb490fa4..2bb4d275938 100644 --- a/python/ql/lib/semmle/python/security/injection/Command.qll +++ b/python/ql/lib/semmle/python/security/injection/Command.qll @@ -13,9 +13,7 @@ import semmle.python.security.strings.Untrusted /** Abstract taint sink that is potentially vulnerable to malicious shell commands. */ abstract class CommandSink extends TaintSink { } -private ModuleObject osOrPopenModule() { - result.getName() = ["os", "popen2"] -} +private ModuleObject osOrPopenModule() { result.getName() = ["os", "popen2"] } private Object makeOsCall() { exists(string name | result = ModuleObject::named("subprocess").attr(name) | From a9c5fd2cc0a50dc2934e49d0e766421496f399b1 Mon Sep 17 00:00:00 2001 From: Taus <tausbn@github.com> Date: Thu, 14 Oct 2021 15:51:56 +0000 Subject: [PATCH 292/361] Java: Fix import order in `SignAnalysisSpecific` --- .../dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 8c4eb2a1144..2b90b128dd3 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -2,10 +2,10 @@ * Provides Java-specific definitions for use in sign analysis. */ module Private { + private import java as J import semmle.code.java.dataflow.RangeUtils as RU private import semmle.code.java.dataflow.SSA as Ssa private import semmle.code.java.controlflow.Guards as G - private import java as J private import Sign import Impl From 4f247bab4e221f5a23fb5872b3be47ef28671b03 Mon Sep 17 00:00:00 2001 From: hubwriter <hubwriter@github.com> Date: Thu, 14 Oct 2021 17:13:42 +0100 Subject: [PATCH 293/361] Add Ruby to language table --- docs/codeql/support/reusables/versions-compilers.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst index 42c830ea665..8726d878bf9 100644 --- a/docs/codeql/support/reusables/versions-compilers.rst +++ b/docs/codeql/support/reusables/versions-compilers.rst @@ -22,6 +22,7 @@ Eclipse compiler for Java (ECJ) [5]_",``.java`` JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9",Not applicable,``.py`` + Ruby,"up to 3.02",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" TypeScript [7]_,"2.6-4.4",Standard TypeScript compiler,"``.ts``, ``.tsx``" .. container:: footnote-group From 888a1b38aa9ebd42709f75d6bb17f6a2eee7ae12 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 15 Oct 2021 14:23:18 +0200 Subject: [PATCH 294/361] C#: Handle `Nullable<T>` default parameter values in assemblies --- .../Semmle.Extraction.CSharp/Entities/Expression.cs | 12 +++++++++--- .../Entities/Expressions/Factory.cs | 2 +- .../Entities/Expressions/Literal.cs | 12 +++++++----- csharp/extractor/Semmle.Extraction/Context.cs | 10 ++++++++++ csharp/extractor/Semmle.Extraction/InternalError.cs | 7 +++++++ 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs index a478047ac7b..123bc315bfa 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs @@ -178,7 +178,13 @@ namespace Semmle.Extraction.CSharp.Entities var defaultValue = parameter.ExplicitDefaultValue; - if (parameter.Type is INamedTypeSymbol nt && nt.EnumUnderlyingType is not null) + var type = parameter.Type; + if (type.IsBoundNullable() && type is INamedTypeSymbol named) + { + type = named.TypeArguments[0]; + } + + if (type is INamedTypeSymbol nt && nt.EnumUnderlyingType is not null) { // = (MyEnum)1, = MyEnum.Value1, = default(MyEnum), = new MyEnum() // we're generating a (MyEnum)value cast expression: @@ -194,7 +200,7 @@ namespace Semmle.Extraction.CSharp.Entities return Default.CreateGenerated(cx, parent, childIndex, location, parameter.Type.IsReferenceType ? ValueAsString(null) : null); } - if (parameter.Type.SpecialType == SpecialType.System_Object) + if (parameter.Type.SpecialType is SpecialType.System_Object) { // this can happen in VB.NET cx.ExtractionError($"Extracting default argument value 'object {parameter.Name} = default' instead of 'object {parameter.Name} = {defaultValue}'. The latter is not supported in C#.", @@ -205,7 +211,7 @@ namespace Semmle.Extraction.CSharp.Entities } // const literal: - return Literal.CreateGenerated(cx, parent, childIndex, parameter.Type, defaultValue, location); + return Literal.CreateGenerated(cx, parent, childIndex, type, defaultValue, location); } /// <summary> diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs index 63389822cad..a92715c4e1c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs @@ -14,7 +14,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { if (info.Node is null) { - info.Context.ModelError("Attempt to create a null expression"); + info.Context.ModelError(info.Location, "Attempt to create a null expression"); return new Unknown(info); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs index bac257e9e34..387e8074f5f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs @@ -32,10 +32,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions } var type = info.Type?.Symbol; - return GetExprKind(type, info.Node, info.Context); + return GetExprKind(type, info.Node, info.Location, info.Context); } - private static ExprKind GetExprKind(ITypeSymbol? type, ExpressionSyntax? expr, Context context) + private static ExprKind GetExprKind(ITypeSymbol? type, ExpressionSyntax? expr, Extraction.Entities.Location loc, Context context) { switch (type?.SpecialType) { @@ -75,10 +75,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case null: default: + var kind = type?.SpecialType.ToString() ?? "null"; if (expr is not null) - context.ModelError(expr, "Unhandled literal type"); + context.ModelError(expr, $"Unhandled literal type {kind}"); else - context.ModelError("Unhandled literal type"); + context.ModelError(loc, $"Unhandled literal type {kind}"); return ExprKind.UNKNOWN; } } @@ -86,11 +87,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, object? value, Extraction.Entities.Location location) { + var kind = value is null ? ExprKind.NULL_LITERAL : GetExprKind(type, null, location, cx); var info = new ExpressionInfo( cx, AnnotatedTypeSymbol.CreateNotAnnotated(type), location, - GetExprKind(type, null, cx), + kind, parent, childIndex, true, diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index abbabcdd198..99da916d294 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -426,6 +426,16 @@ namespace Semmle.Extraction ReportError(new InternalError(symbol, msg)); } + /// <summary> + /// Signal an error in the program model. + /// </summary> + /// <param name="loc">The location of the error.</param> + /// <param name="msg">The error message.</param> + public void ModelError(Entities.Location loc, string msg) + { + ReportError(new InternalError(loc.ReportingLocation, msg)); + } + /// <summary> /// Signal an error in the program model. /// </summary> diff --git a/csharp/extractor/Semmle.Extraction/InternalError.cs b/csharp/extractor/Semmle.Extraction/InternalError.cs index a90685e068f..fe9701488c7 100644 --- a/csharp/extractor/Semmle.Extraction/InternalError.cs +++ b/csharp/extractor/Semmle.Extraction/InternalError.cs @@ -23,6 +23,13 @@ namespace Semmle.Extraction Location = node.GetLocation(); } + public InternalError(Location? loc, string msg) + { + Text = msg; + EntityText = ""; + Location = loc; + } + public InternalError(string msg) { Text = msg; From caeeebf572f84f428476ec36745c832f21c8e5c0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 15 Oct 2021 15:27:37 +0200 Subject: [PATCH 295/361] add explicit this qualifier on all of java --- java/ql/lib/external/ExternalArtifact.qll | 19 +-- java/ql/lib/semmle/code/FileSystem.qll | 34 ++++-- java/ql/lib/semmle/code/Location.qll | 6 +- java/ql/lib/semmle/code/java/Annotation.qll | 10 +- .../lib/semmle/code/java/ControlFlowGraph.qll | 10 +- java/ql/lib/semmle/code/java/Conversions.qll | 2 +- java/ql/lib/semmle/code/java/Element.qll | 4 +- java/ql/lib/semmle/code/java/Expr.qll | 90 +++++++------- java/ql/lib/semmle/code/java/Generics.qll | 30 ++--- java/ql/lib/semmle/code/java/JDK.qll | 63 +++++----- .../lib/semmle/code/java/JDKAnnotations.qll | 4 +- java/ql/lib/semmle/code/java/JMX.qll | 20 +-- java/ql/lib/semmle/code/java/Javadoc.qll | 12 +- java/ql/lib/semmle/code/java/Maps.qll | 6 +- java/ql/lib/semmle/code/java/Member.qll | 54 ++++----- java/ql/lib/semmle/code/java/Modifier.qll | 20 +-- .../lib/semmle/code/java/PrettyPrintAst.qll | 58 ++++----- java/ql/lib/semmle/code/java/PrintAst.qll | 14 +-- java/ql/lib/semmle/code/java/Reflection.qll | 56 ++++----- java/ql/lib/semmle/code/java/Statement.qll | 62 +++++----- java/ql/lib/semmle/code/java/StringFormat.qll | 36 +++--- java/ql/lib/semmle/code/java/Type.qll | 33 ++--- java/ql/lib/semmle/code/java/UnitTests.qll | 40 +++--- java/ql/lib/semmle/code/java/Variable.qll | 10 +- .../semmle/code/java/arithmetic/Overflow.qll | 4 +- .../code/java/controlflow/BasicBlocks.qll | 10 +- .../java/controlflow/UnreachableBlocks.qll | 34 +++--- .../semmle/code/java/dataflow/FlowSources.qll | 4 +- java/ql/lib/semmle/code/java/dataflow/SSA.qll | 53 ++++---- .../code/java/dataflow/internal/BaseSSA.qll | 25 ++-- .../java/dataflow/internal/DataFlowImpl.qll | 16 +-- .../java/dataflow/internal/DataFlowImpl2.qll | 16 +-- .../java/dataflow/internal/DataFlowImpl3.qll | 16 +-- .../java/dataflow/internal/DataFlowImpl4.qll | 16 +-- .../java/dataflow/internal/DataFlowImpl5.qll | 16 +-- .../java/dataflow/internal/DataFlowImpl6.qll | 16 +-- .../DataFlowImplForSerializability.qll | 16 +-- .../java/dataflow/internal/DataFlowNodes.qll | 10 +- .../dataflow/internal/TaintTrackingUtil.qll | 32 ++--- .../semmle/code/java/deadcode/DeadCode.qll | 30 +++-- .../semmle/code/java/deadcode/DeadField.qll | 32 ++--- .../semmle/code/java/deadcode/EntryPoints.qll | 34 +++--- .../code/java/deadcode/TestEntryPoints.qll | 20 +-- .../code/java/deadcode/WebEntryPoints.qll | 4 +- .../lib/semmle/code/java/frameworks/Camel.qll | 2 +- .../lib/semmle/code/java/frameworks/Guice.qll | 2 +- .../lib/semmle/code/java/frameworks/JAXB.qll | 40 +++--- .../code/java/frameworks/JUnitAnnotations.qll | 2 +- .../semmle/code/java/frameworks/Jackson.qll | 12 +- .../lib/semmle/code/java/frameworks/Jndi.qll | 20 +-- .../lib/semmle/code/java/frameworks/Kryo.qll | 26 ++-- .../semmle/code/java/frameworks/Mockito.qll | 100 +++++++-------- .../code/java/frameworks/Networking.qll | 20 +-- .../semmle/code/java/frameworks/Protobuf.qll | 2 +- .../semmle/code/java/frameworks/SnakeYaml.qll | 8 +- .../code/java/frameworks/SpringLdap.qll | 48 ++++---- .../semmle/code/java/frameworks/Thrift.qll | 2 +- .../semmle/code/java/frameworks/UnboundId.qll | 40 +++--- .../code/java/frameworks/android/Android.qll | 14 ++- .../code/java/frameworks/android/Intent.qll | 22 ++-- .../code/java/frameworks/android/WebView.qll | 6 +- .../frameworks/google/GoogleHttpClientApi.qll | 4 +- .../semmle/code/java/frameworks/gwt/GWT.qll | 4 +- .../code/java/frameworks/gwt/GwtUiBinder.qll | 33 ++--- .../java/frameworks/gwt/GwtUiBinderXml.qll | 4 +- .../code/java/frameworks/gwt/GwtXml.qll | 28 ++--- .../code/java/frameworks/j2objc/J2ObjC.qll | 8 +- .../jackson/JacksonSerializability.qll | 46 +++---- .../java/frameworks/javaee/Persistence.qll | 12 +- .../java/frameworks/javaee/PersistenceXML.qll | 4 +- .../code/java/frameworks/javaee/ejb/EJB.qll | 30 ++--- .../java/frameworks/javaee/ejb/EJBJarXML.qll | 8 +- .../javaee/jsf/JSFFacesContextXML.qll | 18 +-- .../frameworks/javaee/jsf/JSFRenderer.qll | 12 +- .../code/java/frameworks/javase/Http.qll | 4 +- .../semmle/code/java/frameworks/play/Play.qll | 2 +- .../java/frameworks/spring/SpringAutowire.qll | 104 ++++++++-------- .../java/frameworks/spring/SpringBean.qll | 10 +- .../java/frameworks/spring/SpringBeanFile.qll | 7 +- .../frameworks/spring/SpringComponentScan.qll | 39 +++--- .../frameworks/spring/SpringController.qll | 114 ++++++++++-------- .../frameworks/spring/SpringExpression.qll | 8 +- .../java/frameworks/spring/SpringFlex.qll | 20 +-- .../java/frameworks/spring/SpringProfile.qll | 8 +- .../code/java/frameworks/spring/SpringWeb.qll | 6 +- .../java/frameworks/struts/StrutsActions.qll | 8 +- .../frameworks/struts/StrutsAnnotations.qll | 2 +- .../frameworks/struts/StrutsConventions.qll | 8 +- .../code/java/frameworks/struts/StrutsXML.qll | 38 +++--- .../code/java/metrics/MetricRefType.qll | 20 +-- .../code/java/security/CommandArguments.qll | 30 ++--- .../semmle/code/java/security/Encryption.qll | 36 +++--- .../code/java/security/ExternalAPIs.qll | 43 +++---- .../code/java/security/JexlInjectionQuery.qll | 35 +++--- .../code/java/security/MvelInjection.qll | 24 ++-- .../code/java/security/RequestForgery.qll | 2 +- .../code/java/security/SpelInjectionQuery.qll | 4 +- .../security/UnsafeDeserializationQuery.qll | 8 +- java/ql/lib/semmle/code/java/security/XSS.qll | 2 +- .../lib/semmle/code/xml/AndroidManifest.qll | 23 ++-- java/ql/lib/semmle/code/xml/MavenPom.qll | 110 +++++++++-------- java/ql/lib/semmle/code/xml/WebXML.qll | 46 +++---- .../CWE-016/InsecureSpringActuatorConfig.ql | 4 +- java/ql/src/external/Clover.qll | 2 +- 104 files changed, 1269 insertions(+), 1172 deletions(-) diff --git a/java/ql/lib/external/ExternalArtifact.qll b/java/ql/lib/external/ExternalArtifact.qll index 5359b99c7c8..2e782a6a4da 100644 --- a/java/ql/lib/external/ExternalArtifact.qll +++ b/java/ql/lib/external/ExternalArtifact.qll @@ -3,24 +3,25 @@ import java class ExternalData extends @externalDataElement { string getDataPath() { externalData(this, result, _, _) } - string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } + string getQueryPath() { result = this.getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) } string getField(int index) { externalData(this, _, index, result) } - int getFieldAsInt(int index) { result = getField(index).toInt() } + int getFieldAsInt(int index) { result = this.getField(index).toInt() } - float getFieldAsFloat(int index) { result = getField(index).toFloat() } + float getFieldAsFloat(int index) { result = this.getField(index).toFloat() } - date getFieldAsDate(int index) { result = getField(index).toDate() } + date getFieldAsDate(int index) { result = this.getField(index).toDate() } - string toString() { result = getQueryPath() + ": " + buildTupleString(0) } + string toString() { result = this.getQueryPath() + ": " + this.buildTupleString(0) } private string buildTupleString(int start) { - start = getNumFields() - 1 and result = getField(start) + start = this.getNumFields() - 1 and result = this.getField(start) or - start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1) + start < this.getNumFields() - 1 and + result = this.getField(start) + "," + this.buildTupleString(start + 1) } } @@ -33,7 +34,7 @@ class DefectExternalData extends ExternalData { this.getNumFields() = 2 } - string getURL() { result = getField(0) } + string getURL() { result = this.getField(0) } - string getMessage() { result = getField(1) } + string getMessage() { result = this.getField(1) } } diff --git a/java/ql/lib/semmle/code/FileSystem.qll b/java/ql/lib/semmle/code/FileSystem.qll index 6c252d569e9..cace20f63e1 100755 --- a/java/ql/lib/semmle/code/FileSystem.qll +++ b/java/ql/lib/semmle/code/FileSystem.qll @@ -47,7 +47,7 @@ class Container extends @container, Top { */ string getRelativePath() { exists(string absPath, string pref | - absPath = getAbsolutePath() and sourceLocationPrefix(pref) + absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) | absPath = pref and result = "" or @@ -74,7 +74,7 @@ class Container extends @container, Top { * </table> */ string getBaseName() { - result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) + result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) } /** @@ -100,7 +100,9 @@ class Container extends @container, Top { * <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr> * </table> */ - string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } + string getExtension() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) + } /** * Gets the stem of this container, that is, the prefix of its base name up to @@ -119,7 +121,9 @@ class Container extends @container, Top { * <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr> * </table> */ - string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } + string getStem() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) + } /** Gets the parent container of this file or folder, if any. */ Container getParentContainer() { containerparent(result, this) } @@ -128,20 +132,20 @@ class Container extends @container, Top { Container getAChildContainer() { this = result.getParentContainer() } /** Gets a file in this container. */ - File getAFile() { result = getAChildContainer() } + File getAFile() { result = this.getAChildContainer() } /** Gets the file in this container that has the given `baseName`, if any. */ File getFile(string baseName) { - result = getAFile() and + result = this.getAFile() and result.getBaseName() = baseName } /** Gets a sub-folder in this container. */ - Folder getAFolder() { result = getAChildContainer() } + Folder getAFolder() { result = this.getAChildContainer() } /** Gets the sub-folder in this container that has the given `baseName`, if any. */ Folder getFolder(string baseName) { - result = getAFolder() and + result = this.getAFolder() and result.getBaseName() = baseName } @@ -152,7 +156,7 @@ class Container extends @container, Top { * to provide a different result. To get the absolute path of any `Container`, call * `Container.getAbsolutePath()` directly. */ - override string toString() { result = getAbsolutePath() } + override string toString() { result = this.getAbsolutePath() } } /** A folder. */ @@ -160,7 +164,7 @@ class Folder extends Container, @folder { override string getAbsolutePath() { folders(this, result) } /** Gets the URL of this folder. */ - override string getURL() { result = "folder://" + getAbsolutePath() } + override string getURL() { result = "folder://" + this.getAbsolutePath() } override string getAPrimaryQlClass() { result = "Folder" } } @@ -183,7 +187,7 @@ class File extends Container, @file { * A Java archive file with a ".jar" extension. */ class JarFile extends File { - JarFile() { getExtension() = "jar" } + JarFile() { this.getExtension() = "jar" } /** * Gets the main attribute with the specified `key` @@ -195,13 +199,17 @@ class JarFile extends File { * Gets the "Specification-Version" main attribute * from this JAR file's manifest. */ - string getSpecificationVersion() { result = getManifestMainAttribute("Specification-Version") } + string getSpecificationVersion() { + result = this.getManifestMainAttribute("Specification-Version") + } /** * Gets the "Implementation-Version" main attribute * from this JAR file's manifest. */ - string getImplementationVersion() { result = getManifestMainAttribute("Implementation-Version") } + string getImplementationVersion() { + result = this.getManifestMainAttribute("Implementation-Version") + } /** * Gets the per-entry attribute for the specified `entry` and `key` diff --git a/java/ql/lib/semmle/code/Location.qll b/java/ql/lib/semmle/code/Location.qll index 2af4f8712e0..d90a189acb7 100755 --- a/java/ql/lib/semmle/code/Location.qll +++ b/java/ql/lib/semmle/code/Location.qll @@ -63,10 +63,10 @@ class Top extends @top { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - hasLocationInfoAux(filepath, startline, startcolumn, endline, endcolumn) + this.hasLocationInfoAux(filepath, startline, startcolumn, endline, endcolumn) or exists(string outFilepath, int outStartline, int outEndline | - hasLocationInfoAux(outFilepath, outStartline, _, outEndline, _) and + this.hasLocationInfoAux(outFilepath, outStartline, _, outEndline, _) and hasSmapLocationInfo(filepath, startline, startcolumn, endline, endcolumn, outFilepath, outStartline, outEndline) ) @@ -103,7 +103,7 @@ class Top extends @top { /** * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */ - final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") } + final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") } /** * Gets the name of a primary CodeQL class to which this element belongs. diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll index 2ee7c6403b4..342a2bd6e0d 100755 --- a/java/ql/lib/semmle/code/java/Annotation.qll +++ b/java/ql/lib/semmle/code/java/Annotation.qll @@ -51,7 +51,7 @@ class Annotation extends @annotation, Expr { Expr getValue(string name) { filteredAnnotValue(this, this.getAnnotationElement(name), result) } /** Gets the element being annotated. */ - Element getTarget() { result = getAnnotatedElement() } + Element getTarget() { result = this.getAnnotatedElement() } override string toString() { result = this.getType().getName() } @@ -67,8 +67,8 @@ class Annotation extends @annotation, Expr { * expression defined for the value. */ Expr getAValue(string name) { - getType().getAnnotationElement(name).getType() instanceof Array and - exists(Expr value | value = getValue(name) | + this.getType().getAnnotationElement(name).getType() instanceof Array and + exists(Expr value | value = this.getValue(name) | if value instanceof ArrayInit then result = value.(ArrayInit).getAnInit() else result = value ) } @@ -104,7 +104,7 @@ class Annotatable extends Element { /** Holds if this element has the specified annotation. */ predicate hasAnnotation(string package, string name) { - exists(AnnotationType at | at = getAnAnnotation().getType() | + exists(AnnotationType at | at = this.getAnAnnotation().getType() | at.nestedName() = name and at.getPackage().getName() = package ) } @@ -118,7 +118,7 @@ class Annotatable extends Element { * annotation attached to it for the specified `category`. */ predicate suppressesWarningsAbout(string category) { - category = getAnAnnotation().(SuppressWarningsAnnotation).getASuppressedWarning() + category = this.getAnAnnotation().(SuppressWarningsAnnotation).getASuppressedWarning() or this.(Member).getDeclaringType().suppressesWarningsAbout(category) or diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index ff60abb4e73..8e5325902dd 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -528,13 +528,13 @@ private module ControlFlowGraphImpl { /** Gets the first child node, if any. */ ControlFlowNode firstChild() { - result = getChildNode(-1) + result = this.getChildNode(-1) or - result = getChildNode(0) and not exists(getChildNode(-1)) + result = this.getChildNode(0) and not exists(this.getChildNode(-1)) } /** Holds if this CFG node has any child nodes. */ - predicate isLeafNode() { not exists(getChildNode(_)) } + predicate isLeafNode() { not exists(this.getChildNode(_)) } /** Holds if this node can finish with a `normalCompletion`. */ predicate mayCompleteNormally() { @@ -1222,10 +1222,10 @@ class ConditionNode extends ControlFlowNode { ControlFlowNode getABranchSuccessor(boolean branch) { result = branchSuccessor(this, branch) } /** Gets a true-successor of the `ConditionNode`. */ - ControlFlowNode getATrueSuccessor() { result = getABranchSuccessor(true) } + ControlFlowNode getATrueSuccessor() { result = this.getABranchSuccessor(true) } /** Gets a false-successor of the `ConditionNode`. */ - ControlFlowNode getAFalseSuccessor() { result = getABranchSuccessor(false) } + ControlFlowNode getAFalseSuccessor() { result = this.getABranchSuccessor(false) } /** Gets the condition of this `ConditionNode`. This is equal to the node itself. */ Expr getCondition() { result = this } diff --git a/java/ql/lib/semmle/code/java/Conversions.qll b/java/ql/lib/semmle/code/java/Conversions.qll index 9d55f1297fc..b7cd80c4906 100644 --- a/java/ql/lib/semmle/code/java/Conversions.qll +++ b/java/ql/lib/semmle/code/java/Conversions.qll @@ -27,7 +27,7 @@ abstract class ConversionSite extends Expr { /** * Whether this conversion site actually induces a conversion. */ - predicate isTrivial() { getConversionTarget() = getConversionSource() } + predicate isTrivial() { this.getConversionTarget() = this.getConversionSource() } /** * Whether this conversion is implicit. diff --git a/java/ql/lib/semmle/code/java/Element.qll b/java/ql/lib/semmle/code/java/Element.qll index 12a08f8eb9d..14e48fc0d40 100755 --- a/java/ql/lib/semmle/code/java/Element.qll +++ b/java/ql/lib/semmle/code/java/Element.qll @@ -34,10 +34,10 @@ class Element extends @element, Top { * Elements pertaining to source files may include generated elements * not visible in source code, such as implicit default constructors. */ - predicate fromSource() { getCompilationUnit().getExtension() = "java" } + predicate fromSource() { this.getCompilationUnit().getExtension() = "java" } /** Gets the compilation unit that this element belongs to. */ - CompilationUnit getCompilationUnit() { result = getFile() } + CompilationUnit getCompilationUnit() { result = this.getFile() } /** Cast this element to a `Documentable`. */ Documentable getDoc() { result = this } diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index b83f5332756..b95f7e8232f 100755 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -86,13 +86,15 @@ class Expr extends ExprParent, @expr { * explicit constructor invocation statement. */ - getEnclosingCallable().isStatic() + this.getEnclosingCallable().isStatic() or - getParent+() instanceof ThisConstructorInvocationStmt + this.getParent+() instanceof ThisConstructorInvocationStmt or - getParent+() instanceof SuperConstructorInvocationStmt + this.getParent+() instanceof SuperConstructorInvocationStmt or - exists(LambdaExpr lam | lam.asMethod() = getEnclosingCallable() and lam.isInStaticContext()) + exists(LambdaExpr lam | + lam.asMethod() = this.getEnclosingCallable() and lam.isInStaticContext() + ) } /** Holds if this expression is parenthesized. */ @@ -116,7 +118,7 @@ private predicate primitiveOrString(Type t) { */ class CompileTimeConstantExpr extends Expr { CompileTimeConstantExpr() { - primitiveOrString(getType()) and + primitiveOrString(this.getType()) and ( // Literals of primitive type and literals of type `String`. this instanceof Literal @@ -425,9 +427,9 @@ class ArrayCreationExpr extends Expr, @arraycreationexpr { * Gets the size of the first dimension, if it can be statically determined. */ int getFirstDimensionSize() { - if exists(getInit()) - then result = getInit().getSize() - else result = getDimension(0).(CompileTimeConstantExpr).getIntValue() + if exists(this.getInit()) + then result = this.getInit().getSize() + else result = this.getDimension(0).(CompileTimeConstantExpr).getIntValue() } /** Gets a printable representation of this expression. */ @@ -463,7 +465,7 @@ class ArrayInit extends Expr, @arrayinit { * Gets the number of expressions in this initializer, that is, the size the * created array will have. */ - int getSize() { result = count(getAnInit()) } + int getSize() { result = count(this.getAnInit()) } /** Gets a printable representation of this expression. */ override string toString() { result = "{...}" } @@ -632,9 +634,9 @@ class Literal extends Expr, @literal { class BooleanLiteral extends Literal, @booleanliteral { /** Gets the boolean representation of this literal. */ boolean getBooleanValue() { - result = true and getValue() = "true" + result = true and this.getValue() = "true" or - result = false and getValue() = "false" + result = false and this.getValue() = "false" } override string getAPrimaryQlClass() { result = "BooleanLiteral" } @@ -657,7 +659,7 @@ class BooleanLiteral extends Literal, @booleanliteral { */ class IntegerLiteral extends Literal, @integerliteral { /** Gets the int representation of this literal. */ - int getIntValue() { result = getValue().toInt() } + int getIntValue() { result = this.getValue().toInt() } override string getAPrimaryQlClass() { result = "IntegerLiteral" } } @@ -693,7 +695,7 @@ class FloatingPointLiteral extends Literal, @floatingpointliteral { * Gets the value of this literal as CodeQL 64-bit `float`. The value will * be parsed as Java 32-bit `float` and then converted to a CodeQL `float`. */ - float getFloatValue() { result = getValue().toFloat() } + float getFloatValue() { result = this.getValue().toFloat() } override string getAPrimaryQlClass() { result = "FloatingPointLiteral" } } @@ -709,7 +711,7 @@ class DoubleLiteral extends Literal, @doubleliteral { * Gets the value of this literal as CodeQL 64-bit `float`. The result will * have the same effective value as the Java `double` literal. */ - float getDoubleValue() { result = getValue().toFloat() } + float getDoubleValue() { result = this.getValue().toFloat() } override string getAPrimaryQlClass() { result = "DoubleLiteral" } } @@ -732,10 +734,10 @@ class StringLiteral extends Literal, @stringliteral { /** * Gets the literal string without the quotes. */ - string getRepresentedString() { result = getValue() } + string getRepresentedString() { result = this.getValue() } /** Holds if this string literal is a text block (`""" ... """`). */ - predicate isTextBlock() { getLiteral().matches("\"\"\"%") } + predicate isTextBlock() { this.getLiteral().matches("\"\"\"%") } override string getAPrimaryQlClass() { result = "StringLiteral" } } @@ -1184,7 +1186,7 @@ class LambdaExpr extends FunctionalExpr, @lambdaexpr { * Gets the implicit method corresponding to this lambda expression. * The parameters of the lambda expression are the parameters of this method. */ - override Method asMethod() { result = getAnonymousClass().getAMethod() } + override Method asMethod() { result = this.getAnonymousClass().getAMethod() } /** Holds if the body of this lambda is an expression. */ predicate hasExprBody() { lambdaKind(this, 0) } @@ -1194,11 +1196,11 @@ class LambdaExpr extends FunctionalExpr, @lambdaexpr { /** Gets the body of this lambda expression, if it is an expression. */ Expr getExprBody() { - hasExprBody() and result = asMethod().getBody().getAChild().(ReturnStmt).getResult() + this.hasExprBody() and result = this.asMethod().getBody().getAChild().(ReturnStmt).getResult() } /** Gets the body of this lambda expression, if it is a statement. */ - BlockStmt getStmtBody() { hasStmtBody() and result = asMethod().getBody() } + BlockStmt getStmtBody() { this.hasStmtBody() and result = this.asMethod().getBody() } /** Gets a printable representation of this expression. */ override string toString() { result = "...->..." } @@ -1223,7 +1225,7 @@ class MemberRefExpr extends FunctionalExpr, @memberref { * (if the reference is to a constructor) or an array creation expression (if the reference * is to an array constructor). */ - override Method asMethod() { result = getAnonymousClass().getAMethod() } + override Method asMethod() { result = this.getAnonymousClass().getAMethod() } /** * Gets the method or constructor referenced by this member reference expression. @@ -1274,16 +1276,16 @@ class ConditionalExpr extends Expr, @conditionalexpr { * it is `getFalseExpr()`. */ Expr getBranchExpr(boolean branch) { - branch = true and result = getTrueExpr() + branch = true and result = this.getTrueExpr() or - branch = false and result = getFalseExpr() + branch = false and result = this.getFalseExpr() } /** * Gets the expressions that is evaluated by one of the branches (`true` * or `false` branch) of this conditional expression. */ - Expr getABranchExpr() { result = getBranchExpr(_) } + Expr getABranchExpr() { result = this.getBranchExpr(_) } /** Gets a printable representation of this expression. */ override string toString() { result = "...?...:..." } @@ -1308,7 +1310,7 @@ class SwitchExpr extends Expr, StmtParent, @switchexpr { * Gets a case of this `switch` expression, * which may be either a normal `case` or a `default`. */ - SwitchCase getACase() { result = getAConstCase() or result = getDefaultCase() } + SwitchCase getACase() { result = this.getAConstCase() or result = this.getDefaultCase() } /** Gets a (non-default) `case` of this `switch` expression. */ ConstCase getAConstCase() { result.getParent() = this } @@ -1321,7 +1323,7 @@ class SwitchExpr extends Expr, StmtParent, @switchexpr { /** Gets a result expression of this `switch` expression. */ Expr getAResult() { - result = getACase().getRuleExpression() + result = this.getACase().getRuleExpression() or exists(YieldStmt yield | yield.(JumpStmt).getTarget() = this and result = yield.getValue()) } @@ -1336,8 +1338,8 @@ class SwitchExpr extends Expr, StmtParent, @switchexpr { class InstanceOfExpr extends Expr, @instanceofexpr { /** Gets the expression on the left-hand side of the `instanceof` operator. */ Expr getExpr() { - if isPattern() - then result = getLocalVariableDeclExpr().getInit() + if this.isPattern() + then result = this.getLocalVariableDeclExpr().getInit() else result.isNthChildOf(this, 0) } @@ -1346,7 +1348,7 @@ class InstanceOfExpr extends Expr, @instanceofexpr { * * Holds if this `instanceof` expression uses pattern matching. */ - predicate isPattern() { exists(getLocalVariableDeclExpr()) } + predicate isPattern() { exists(this.getLocalVariableDeclExpr()) } /** * PREVIEW FEATURE in Java 14. Subject to removal in a future release. @@ -1359,7 +1361,7 @@ class InstanceOfExpr extends Expr, @instanceofexpr { Expr getTypeName() { result.isNthChildOf(this, 1) } /** Gets the type this `instanceof` expression checks for. */ - RefType getCheckedType() { result = getTypeName().getType() } + RefType getCheckedType() { result = this.getTypeName().getType() } /** Gets a printable representation of this expression. */ override string toString() { result = "...instanceof..." } @@ -1457,7 +1459,7 @@ class TypeLiteral extends Expr, @typeliteral { * Gets the type this type literal refers to. For example for `String.class` the * result is the type representing `String`. */ - Type getReferencedType() { result = getTypeName().getType() } + Type getReferencedType() { result = this.getTypeName().getType() } /** Gets a printable representation of this expression. */ override string toString() { result = this.getTypeName().toString() + ".class" } @@ -1482,15 +1484,15 @@ abstract class InstanceAccess extends Expr { * This never holds for accesses in lambda expressions as they cannot access * their own instance directly. */ - predicate isOwnInstanceAccess() { not isEnclosingInstanceAccess(_) } + predicate isOwnInstanceAccess() { not this.isEnclosingInstanceAccess(_) } /** Holds if this instance access is to an enclosing instance of type `t`. */ predicate isEnclosingInstanceAccess(RefType t) { - t = getQualifier().getType().(RefType).getSourceDeclaration() and - t != getEnclosingCallable().getDeclaringType() + t = this.getQualifier().getType().(RefType).getSourceDeclaration() and + t != this.getEnclosingCallable().getDeclaringType() or - not exists(getQualifier()) and - exists(LambdaExpr lam | lam.asMethod() = getEnclosingCallable() | + not exists(this.getQualifier()) and + exists(LambdaExpr lam | lam.asMethod() = this.getEnclosingCallable() | t = lam.getAnonymousClass().getEnclosingType() ) } @@ -1538,7 +1540,7 @@ class VarAccess extends Expr, @varaccess { Expr getQualifier() { result.getParent() = this } /** Holds if this variable access has a qualifier. */ - predicate hasQualifier() { exists(getQualifier()) } + predicate hasQualifier() { exists(this.getQualifier()) } /** Gets the variable accessed by this variable access. */ Variable getVariable() { variableBinding(this, result) } @@ -1580,11 +1582,11 @@ class VarAccess extends Expr, @varaccess { */ predicate isLocal() { // The access has no qualifier, or... - not hasQualifier() + not this.hasQualifier() or // the qualifier is either `this` or `A.this`, where `A` is the enclosing type, or // the qualifier is either `super` or `A.super`, where `A` is the enclosing type. - getQualifier().(InstanceAccess).isOwnInstanceAccess() + this.getQualifier().(InstanceAccess).isOwnInstanceAccess() } override string getAPrimaryQlClass() { result = "VarAccess" } @@ -1626,7 +1628,7 @@ class MethodAccess extends Expr, Call, @methodaccess { override Expr getQualifier() { result.isNthChildOf(this, -1) } /** Holds if this method access has a qualifier. */ - predicate hasQualifier() { exists(getQualifier()) } + predicate hasQualifier() { exists(this.getQualifier()) } /** Gets an argument supplied to the method that is invoked using this method access. */ override Expr getAnArgument() { result.getIndex() >= 0 and result.getParent() = this } @@ -1663,9 +1665,9 @@ class MethodAccess extends Expr, Call, @methodaccess { * the enclosing type if there is no qualifier. */ RefType getReceiverType() { - result = getQualifier().getType() + result = this.getQualifier().getType() or - not hasQualifier() and result = getEnclosingCallable().getDeclaringType() + not this.hasQualifier() and result = this.getEnclosingCallable().getDeclaringType() } /** @@ -1841,7 +1843,7 @@ class Call extends ExprParent, @caller { Callable getCallee() { callableBinding(this, result) } /** Gets the callable invoking this call. */ - Callable getCaller() { result = getEnclosingCallable() } + Callable getCaller() { result = this.getEnclosingCallable() } } /** A polymorphic call to an instance method. */ @@ -2042,14 +2044,14 @@ class Argument extends Expr { } /** Holds if this argument is part of an implicit varargs array. */ - predicate isVararg() { isNthVararg(_) } + predicate isVararg() { this.isNthVararg(_) } /** * Holds if this argument is part of an implicit varargs array at the * given array index. */ predicate isNthVararg(int arrayindex) { - not isExplicitVarargsArray() and + not this.isExplicitVarargsArray() and exists(Callable tgt | call.getCallee() = tgt and tgt.isVarargs() and diff --git a/java/ql/lib/semmle/code/java/Generics.qll b/java/ql/lib/semmle/code/java/Generics.qll index a15c47b1f8f..d023c7c15a3 100755 --- a/java/ql/lib/semmle/code/java/Generics.qll +++ b/java/ql/lib/semmle/code/java/Generics.qll @@ -69,12 +69,12 @@ class GenericType extends RefType { /** * Gets a type parameter of this generic type. */ - TypeVariable getATypeParameter() { result = getTypeParameter(_) } + TypeVariable getATypeParameter() { result = this.getTypeParameter(_) } /** * Gets the number of type parameters of this generic type. */ - int getNumberOfTypeParameters() { result = strictcount(getATypeParameter()) } + int getNumberOfTypeParameters() { result = strictcount(this.getATypeParameter()) } override string getAPrimaryQlClass() { result = "GenericType" } } @@ -107,7 +107,7 @@ abstract class BoundedType extends RefType, @boundedtype { TypeBound getATypeBound() { result.getBoundedType() = this } /** Gets the first type bound for this type, if any. */ - TypeBound getFirstTypeBound() { result = getATypeBound() and result.getPosition() = 0 } + TypeBound getFirstTypeBound() { result = this.getATypeBound() and result.getPosition() = 0 } /** * Gets an upper type bound of this type, or `Object` @@ -123,9 +123,9 @@ abstract class BoundedType extends RefType, @boundedtype { /** Gets a transitive upper bound for this type that is not itself a bounded type. */ RefType getAnUltimateUpperBoundType() { - result = getUpperBoundType() and not result instanceof BoundedType + result = this.getUpperBoundType() and not result instanceof BoundedType or - result = getUpperBoundType().(BoundedType).getAnUltimateUpperBoundType() + result = this.getUpperBoundType().(BoundedType).getAnUltimateUpperBoundType() } override string getAPrimaryQlClass() { result = "BoundedType" } @@ -168,8 +168,8 @@ class TypeVariable extends BoundedType, @typevariable { /** Gets the lexically enclosing package of this type parameter, if any. */ override Package getPackage() { - result = getGenericType().getPackage() or - result = getGenericCallable().getDeclaringType().getPackage() + result = this.getGenericType().getPackage() or + result = this.getGenericCallable().getDeclaringType().getPackage() } /** Finds a type that was supplied for this parameter. */ @@ -190,9 +190,9 @@ class TypeVariable extends BoundedType, @typevariable { /** Finds a non-typevariable type that was transitively supplied for this parameter. */ RefType getAnUltimatelySuppliedType() { - result = getASuppliedType() and not result instanceof TypeVariable + result = this.getASuppliedType() and not result instanceof TypeVariable or - result = getASuppliedType().(TypeVariable).getAnUltimatelySuppliedType() + result = this.getASuppliedType().(TypeVariable).getAnUltimatelySuppliedType() } override string getAPrimaryQlClass() { result = "TypeVariable" } @@ -261,7 +261,7 @@ class Wildcard extends BoundedType, @wildcard { * Holds if this is the unconstrained wildcard `?`. */ predicate isUnconstrained() { - not hasLowerBound() and + not this.hasLowerBound() and wildcards(this, "?", _) } @@ -451,12 +451,12 @@ class GenericCallable extends Callable { /** * Gets a type parameter of this generic callable. */ - TypeVariable getATypeParameter() { result = getTypeParameter(_) } + TypeVariable getATypeParameter() { result = this.getTypeParameter(_) } /** * Gets the number of type parameters of this generic callable. */ - int getNumberOfTypeParameters() { result = strictcount(getATypeParameter()) } + int getNumberOfTypeParameters() { result = strictcount(this.getATypeParameter()) } } /** @@ -484,10 +484,10 @@ class GenericCall extends Call { /** Gets a type argument of the call for the given `TypeVariable`. */ RefType getATypeArgument(TypeVariable v) { - result = getAnExplicitTypeArgument(v) + result = this.getAnExplicitTypeArgument(v) or - not exists(getAnExplicitTypeArgument(v)) and - result = getAnInferredTypeArgument(v) + not exists(this.getAnExplicitTypeArgument(v)) and + result = this.getAnInferredTypeArgument(v) } } diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll index 2e14ab7b898..e497740a489 100644 --- a/java/ql/lib/semmle/code/java/JDK.qll +++ b/java/ql/lib/semmle/code/java/JDK.qll @@ -19,12 +19,12 @@ class TypeCloneable extends Interface { /** The class `java.lang.ProcessBuilder`. */ class TypeProcessBuilder extends Class { - TypeProcessBuilder() { hasQualifiedName("java.lang", "ProcessBuilder") } + TypeProcessBuilder() { this.hasQualifiedName("java.lang", "ProcessBuilder") } } /** The class `java.lang.Runtime`. */ class TypeRuntime extends Class { - TypeRuntime() { hasQualifiedName("java.lang", "Runtime") } + TypeRuntime() { this.hasQualifiedName("java.lang", "Runtime") } } /** The class `java.lang.String`. */ @@ -143,22 +143,22 @@ class ImmutableType extends Type { // --- Java IO --- /** The interface `java.io.Serializable`. */ class TypeSerializable extends Interface { - TypeSerializable() { hasQualifiedName("java.io", "Serializable") } + TypeSerializable() { this.hasQualifiedName("java.io", "Serializable") } } /** The interface `java.io.ObjectOutput`. */ class TypeObjectOutput extends Interface { - TypeObjectOutput() { hasQualifiedName("java.io", "ObjectOutput") } + TypeObjectOutput() { this.hasQualifiedName("java.io", "ObjectOutput") } } /** The type `java.io.ObjectOutputStream`. */ class TypeObjectOutputStream extends RefType { - TypeObjectOutputStream() { hasQualifiedName("java.io", "ObjectOutputStream") } + TypeObjectOutputStream() { this.hasQualifiedName("java.io", "ObjectOutputStream") } } /** The type `java.io.ObjectInputStream`. */ class TypeObjectInputStream extends RefType { - TypeObjectInputStream() { hasQualifiedName("java.io", "ObjectInputStream") } + TypeObjectInputStream() { this.hasQualifiedName("java.io", "ObjectInputStream") } } /** The class `java.nio.file.Paths`. */ @@ -196,8 +196,8 @@ class ProcessBuilderConstructor extends Constructor, ExecCallable { */ class MethodProcessBuilderCommand extends Method, ExecCallable { MethodProcessBuilderCommand() { - hasName("command") and - getDeclaringType() instanceof TypeProcessBuilder + this.hasName("command") and + this.getDeclaringType() instanceof TypeProcessBuilder } override int getAnExecutedArgument() { result = 0 } @@ -208,8 +208,8 @@ class MethodProcessBuilderCommand extends Method, ExecCallable { */ class MethodRuntimeExec extends Method, ExecCallable { MethodRuntimeExec() { - hasName("exec") and - getDeclaringType() instanceof TypeRuntime + this.hasName("exec") and + this.getDeclaringType() instanceof TypeRuntime } override int getAnExecutedArgument() { result = 0 } @@ -220,8 +220,8 @@ class MethodRuntimeExec extends Method, ExecCallable { */ class MethodSystemGetenv extends Method { MethodSystemGetenv() { - hasName("getenv") and - getDeclaringType() instanceof TypeSystem + this.hasName("getenv") and + this.getDeclaringType() instanceof TypeSystem } } @@ -230,8 +230,8 @@ class MethodSystemGetenv extends Method { */ class MethodSystemGetProperty extends Method { MethodSystemGetProperty() { - hasName("getProperty") and - getDeclaringType() instanceof TypeSystem + this.hasName("getProperty") and + this.getDeclaringType() instanceof TypeSystem } } @@ -239,7 +239,7 @@ class MethodSystemGetProperty extends Method { * An access to a method named `getProperty` on class `java.lang.System`. */ class MethodAccessSystemGetProperty extends MethodAccess { - MethodAccessSystemGetProperty() { getMethod() instanceof MethodSystemGetProperty } + MethodAccessSystemGetProperty() { this.getMethod() instanceof MethodSystemGetProperty } /** * Holds if this call has a compile-time constant first argument with the value `propertyName`. @@ -255,8 +255,11 @@ class MethodAccessSystemGetProperty extends MethodAccess { */ class MethodExit extends Method { MethodExit() { - hasName("exit") and - (getDeclaringType() instanceof TypeRuntime or getDeclaringType() instanceof TypeSystem) + this.hasName("exit") and + ( + this.getDeclaringType() instanceof TypeRuntime or + this.getDeclaringType() instanceof TypeSystem + ) } } @@ -266,10 +269,10 @@ class MethodExit extends Method { */ class WriteObjectMethod extends Method { WriteObjectMethod() { - hasName("writeObject") and + this.hasName("writeObject") and ( - getDeclaringType() instanceof TypeObjectOutputStream or - getDeclaringType() instanceof TypeObjectOutput + this.getDeclaringType() instanceof TypeObjectOutputStream or + this.getDeclaringType() instanceof TypeObjectOutput ) } } @@ -293,16 +296,16 @@ class ReadObjectMethod extends Method { /** The method `Class.getName()`. */ class ClassNameMethod extends Method { ClassNameMethod() { - hasName("getName") and - getDeclaringType() instanceof TypeClass + this.hasName("getName") and + this.getDeclaringType() instanceof TypeClass } } /** The method `Class.getSimpleName()`. */ class ClassSimpleNameMethod extends Method { ClassSimpleNameMethod() { - hasName("getSimpleName") and - getDeclaringType() instanceof TypeClass + this.hasName("getSimpleName") and + this.getDeclaringType() instanceof TypeClass } } @@ -334,24 +337,24 @@ class MethodMathMax extends Method { /** The field `System.in`. */ class SystemIn extends Field { SystemIn() { - hasName("in") and - getDeclaringType() instanceof TypeSystem + this.hasName("in") and + this.getDeclaringType() instanceof TypeSystem } } /** The field `System.out`. */ class SystemOut extends Field { SystemOut() { - hasName("out") and - getDeclaringType() instanceof TypeSystem + this.hasName("out") and + this.getDeclaringType() instanceof TypeSystem } } /** The field `System.err`. */ class SystemErr extends Field { SystemErr() { - hasName("err") and - getDeclaringType() instanceof TypeSystem + this.hasName("err") and + this.getDeclaringType() instanceof TypeSystem } } diff --git a/java/ql/lib/semmle/code/java/JDKAnnotations.qll b/java/ql/lib/semmle/code/java/JDKAnnotations.qll index 49776a570f2..0b56599caa2 100644 --- a/java/ql/lib/semmle/code/java/JDKAnnotations.qll +++ b/java/ql/lib/semmle/code/java/JDKAnnotations.qll @@ -25,7 +25,9 @@ class SuppressWarningsAnnotation extends Annotation { } /** Gets the name of a warning suppressed by this annotation. */ - string getASuppressedWarning() { result = getASuppressedWarningLiteral().getRepresentedString() } + string getASuppressedWarning() { + result = this.getASuppressedWarningLiteral().getRepresentedString() + } } /** A `@Target` annotation. */ diff --git a/java/ql/lib/semmle/code/java/JMX.qll b/java/ql/lib/semmle/code/java/JMX.qll index 77194d24767..16c8736059f 100644 --- a/java/ql/lib/semmle/code/java/JMX.qll +++ b/java/ql/lib/semmle/code/java/JMX.qll @@ -26,27 +26,27 @@ class MXBean extends ManagedBean { */ class RegisteredManagedBeanImpl extends Class { RegisteredManagedBeanImpl() { - getAnAncestor() instanceof ManagedBean and + this.getAnAncestor() instanceof ManagedBean and exists(JMXRegistrationCall registerCall | registerCall.getObjectArgument().getType() = this) } /** * Gets a managed bean that this registered bean class implements. */ - ManagedBean getAnImplementedManagedBean() { result = getAnAncestor() } + ManagedBean getAnImplementedManagedBean() { result = this.getAnAncestor() } } /** * A call that registers an object with the `MBeanServer`, directly or indirectly. */ class JMXRegistrationCall extends MethodAccess { - JMXRegistrationCall() { getCallee() instanceof JMXRegistrationMethod } + JMXRegistrationCall() { this.getCallee() instanceof JMXRegistrationMethod } /** * Gets the argument that represents the object in the registration call. */ Expr getObjectArgument() { - result = getArgument(getCallee().(JMXRegistrationMethod).getObjectPosition()) + result = this.getArgument(this.getCallee().(JMXRegistrationMethod).getObjectPosition()) } } @@ -59,15 +59,15 @@ class JMXRegistrationCall extends MethodAccess { class JMXRegistrationMethod extends Method { JMXRegistrationMethod() { // A direct registration with the `MBeanServer`. - getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and - getName() = "registerMBean" + this.getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and + this.getName() = "registerMBean" or // The `MBeanServer` is often wrapped by an application specific management class, so identify // methods that wrap a call to another `JMXRegistrationMethod`. exists(JMXRegistrationCall c | // This must be a call to another JMX registration method, where the object argument is an access // of one of the parameters of this method. - c.getObjectArgument().(VarAccess).getVariable() = getAParameter() + c.getObjectArgument().(VarAccess).getVariable() = this.getAParameter() ) } @@ -76,13 +76,13 @@ class JMXRegistrationMethod extends Method { */ int getObjectPosition() { // Passed as the first argument to `registerMBean`. - getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and - getName() = "registerMBean" and + this.getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and + this.getName() = "registerMBean" and result = 0 or // Identify the position in this method where the object parameter should be passed. exists(JMXRegistrationCall c | - c.getObjectArgument().(VarAccess).getVariable() = getParameter(result) + c.getObjectArgument().(VarAccess).getVariable() = this.getParameter(result) ) } } diff --git a/java/ql/lib/semmle/code/java/Javadoc.qll b/java/ql/lib/semmle/code/java/Javadoc.qll index 61d978fbd35..8f7b1dbf580 100755 --- a/java/ql/lib/semmle/code/java/Javadoc.qll +++ b/java/ql/lib/semmle/code/java/Javadoc.qll @@ -14,7 +14,7 @@ class JavadocParent extends @javadocParent, Top { JavadocElement getChild(int index) { result = this.getAChild() and result.getIndex() = index } /** Gets the number of documentation elements attached to this parent. */ - int getNumChild() { result = count(getAChild()) } + int getNumChild() { result = count(this.getAChild()) } /** Gets a documentation element with the specified Javadoc tag name. */ JavadocTag getATag(string name) { result = this.getAChild() and result.getTagName() = name } @@ -33,7 +33,9 @@ class Javadoc extends JavadocParent, @javadoc { /** Gets the value of the `@author` tag, if any. */ string getAuthor() { result = this.getATag("@author").getChild(0).toString() } - override string toString() { result = toStringPrefix() + getChild(0) + toStringPostfix() } + override string toString() { + result = this.toStringPrefix() + this.getChild(0) + this.toStringPostfix() + } private string toStringPrefix() { if isEolComment(this) @@ -47,7 +49,7 @@ class Javadoc extends JavadocParent, @javadoc { if isEolComment(this) then result = "" else ( - if strictcount(getAChild()) = 1 then result = " */" else result = " ... */" + if strictcount(this.getAChild()) = 1 then result = " */" else result = " ... */" ) } @@ -119,10 +121,10 @@ class ThrowsTag extends JavadocTag { /** A Javadoc `@see` tag. */ class SeeTag extends JavadocTag { - SeeTag() { getTagName() = "@see" } + SeeTag() { this.getTagName() = "@see" } /** Gets the name of the entity referred to. */ - string getReference() { result = getChild(0).toString() } + string getReference() { result = this.getChild(0).toString() } } /** A Javadoc `@author` tag. */ diff --git a/java/ql/lib/semmle/code/java/Maps.qll b/java/ql/lib/semmle/code/java/Maps.qll index c86cb0ef47a..784db84fb98 100644 --- a/java/ql/lib/semmle/code/java/Maps.qll +++ b/java/ql/lib/semmle/code/java/Maps.qll @@ -76,11 +76,11 @@ class FreshMap extends ClassInstanceExpr { * A call to `Map.put(key, value)`. */ class MapPutCall extends MethodAccess { - MapPutCall() { getCallee().(MapMethod).hasName("put") } + MapPutCall() { this.getCallee().(MapMethod).hasName("put") } /** Gets the key argument of this call. */ - Expr getKey() { result = getArgument(0) } + Expr getKey() { result = this.getArgument(0) } /** Gets the value argument of this call. */ - Expr getValue() { result = getArgument(1) } + Expr getValue() { result = this.getArgument(1) } } diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index da136c577f8..fee8d3f24ee 100755 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -21,7 +21,7 @@ class Member extends Element, Annotatable, Modifiable, @member { RefType getDeclaringType() { declaresMember(result, this) } /** Gets the qualified name of this member. */ - string getQualifiedName() { result = getDeclaringType().getName() + "." + getName() } + string getQualifiedName() { result = this.getDeclaringType().getName() + "." + this.getName() } /** * Holds if this member has the specified name and is declared in the @@ -33,9 +33,9 @@ class Member extends Element, Annotatable, Modifiable, @member { /** Holds if this member is package protected, that is, neither public nor private nor protected. */ predicate isPackageProtected() { - not isPrivate() and - not isProtected() and - not isPublic() + not this.isPrivate() and + not this.isProtected() and + not this.isPublic() } /** @@ -78,7 +78,7 @@ class Callable extends StmtParent, Member, @callable { */ string getMethodDescriptor() { exists(string return | return = this.getReturnType().getTypeDescriptor() | - result = "(" + descriptorUpTo(this.getNumberOfParameters()) + ")" + return + result = "(" + this.descriptorUpTo(this.getNumberOfParameters()) + ")" + return ) } @@ -86,19 +86,19 @@ class Callable extends StmtParent, Member, @callable { n = 0 and result = "" or exists(Parameter p | p = this.getParameter(n - 1) | - result = descriptorUpTo(n - 1) + p.getType().getTypeDescriptor() + result = this.descriptorUpTo(n - 1) + p.getType().getTypeDescriptor() ) } /** Holds if this callable calls `target`. */ - predicate calls(Callable target) { exists(getACallSite(target)) } + predicate calls(Callable target) { exists(this.getACallSite(target)) } /** * Holds if this callable calls `target` * using a `super(...)` constructor call. */ predicate callsSuperConstructor(Constructor target) { - getACallSite(target) instanceof SuperConstructorInvocationStmt + this.getACallSite(target) instanceof SuperConstructorInvocationStmt } /** @@ -106,14 +106,14 @@ class Callable extends StmtParent, Member, @callable { * using a `this(...)` constructor call. */ predicate callsThis(Constructor target) { - getACallSite(target) instanceof ThisConstructorInvocationStmt + this.getACallSite(target) instanceof ThisConstructorInvocationStmt } /** * Holds if this callable calls `target` * using a `super` method call. */ - predicate callsSuper(Method target) { getACallSite(target) instanceof SuperMethodAccess } + predicate callsSuper(Method target) { this.getACallSite(target) instanceof SuperMethodAccess } /** * Holds if this callable calls `c` using @@ -165,13 +165,13 @@ class Callable extends StmtParent, Member, @callable { Field getAnAccessedField() { this.accesses(result) } /** Gets the type of a formal parameter of this callable. */ - Type getAParamType() { result = getParameterType(_) } + Type getAParamType() { result = this.getParameterType(_) } /** Holds if this callable does not have any formal parameters. */ - predicate hasNoParameters() { not exists(getAParameter()) } + predicate hasNoParameters() { not exists(this.getAParameter()) } /** Gets the number of formal parameters of this callable. */ - int getNumberOfParameters() { result = count(getAParameter()) } + int getNumberOfParameters() { result = count(this.getAParameter()) } /** Gets a formal parameter of this callable. */ Parameter getAParameter() { result.getCallable() = this } @@ -205,7 +205,7 @@ class Callable extends StmtParent, Member, @callable { */ pragma[nomagic] string paramsString() { - exists(int n | n = getNumberOfParameters() | + exists(int n | n = this.getNumberOfParameters() | n = 0 and result = "()" or n > 0 and result = "(" + this.paramUpTo(n - 1) + ")" @@ -217,9 +217,9 @@ class Callable extends StmtParent, Member, @callable { * from left to right, up to (and including) the `n`-th parameter. */ private string paramUpTo(int n) { - n = 0 and result = getParameterType(0).toString() + n = 0 and result = this.getParameterType(0).toString() or - n > 0 and result = paramUpTo(n - 1) + ", " + getParameterType(n) + n > 0 and result = this.paramUpTo(n - 1) + ", " + this.getParameterType(n) } /** @@ -234,7 +234,7 @@ class Callable extends StmtParent, Member, @callable { Exception getAnException() { exceptions(result, _, this) } /** Gets an exception type that occurs in the `throws` clause of this callable. */ - RefType getAThrownExceptionType() { result = getAnException().getType() } + RefType getAThrownExceptionType() { result = this.getAnException().getType() } /** Gets a call site that references this callable. */ Call getAReference() { result.getCallee() = this } @@ -392,7 +392,7 @@ class Method extends Callable, @method { or // JLS 9.4: Every method declaration in the body of an interface without an // access modifier is implicitly public. - getDeclaringType() instanceof Interface and + this.getDeclaringType() instanceof Interface and not this.isPrivate() or exists(FunctionalExpr func | func.asMethod() = this) @@ -413,7 +413,7 @@ class Method extends Callable, @method { Callable.super.isStrictfp() or // JLS 8.1.1.3, JLS 9.1.1.2 - getDeclaringType().isStrictfp() + this.getDeclaringType().isStrictfp() } /** @@ -421,8 +421,8 @@ class Method extends Callable, @method { * nor an initializer method, and hence could be inherited. */ predicate isInheritable() { - not isPrivate() and - not (isStatic() and getDeclaringType() instanceof Interface) and + not this.isPrivate() and + not (this.isStatic() and this.getDeclaringType() instanceof Interface) and not this instanceof InitializerMethod } @@ -430,13 +430,13 @@ class Method extends Callable, @method { * Holds if this method is neither private nor static, and hence * uses dynamic dispatch. */ - predicate isVirtual() { not isPrivate() and not isStatic() } + predicate isVirtual() { not this.isPrivate() and not this.isStatic() } /** Holds if this method can be overridden. */ predicate isOverridable() { - isVirtual() and - not isFinal() and - not getDeclaringType().isFinal() + this.isVirtual() and + not this.isFinal() and + not this.getDeclaringType().isFinal() } override string getAPrimaryQlClass() { result = "Method" } @@ -549,7 +549,7 @@ abstract class InitializerMethod extends Method { } * field initializations and static initializer blocks. */ class StaticInitializer extends InitializerMethod { - StaticInitializer() { hasName("<clinit>") } + StaticInitializer() { this.hasName("<clinit>") } } /** @@ -629,7 +629,7 @@ class Field extends Member, ExprParent, @field, Variable { or // JLS 9.3: Every field declaration in the body of an interface is // implicitly public, static, and final - getDeclaringType() instanceof Interface + this.getDeclaringType() instanceof Interface } override predicate isStatic() { diff --git a/java/ql/lib/semmle/code/java/Modifier.qll b/java/ql/lib/semmle/code/java/Modifier.qll index 39cbe5a3c29..11317ef8537 100755 --- a/java/ql/lib/semmle/code/java/Modifier.qll +++ b/java/ql/lib/semmle/code/java/Modifier.qll @@ -25,7 +25,7 @@ abstract class Modifiable extends Element { * abstract, so `isAbstract()` will hold for them even if `hasModifier("abstract")` * does not. */ - predicate hasModifier(string m) { modifiers(getAModifier(), m) } + predicate hasModifier(string m) { modifiers(this.getAModifier(), m) } /** Holds if this element has no modifier. */ predicate hasNoModifier() { not hasModifier(this, _) } @@ -34,31 +34,31 @@ abstract class Modifiable extends Element { Modifier getAModifier() { this = result.getElement() } /** Holds if this element has an `abstract` modifier or is implicitly abstract. */ - predicate isAbstract() { hasModifier("abstract") } + predicate isAbstract() { this.hasModifier("abstract") } /** Holds if this element has a `static` modifier or is implicitly static. */ - predicate isStatic() { hasModifier("static") } + predicate isStatic() { this.hasModifier("static") } /** Holds if this element has a `final` modifier or is implicitly final. */ - predicate isFinal() { hasModifier("final") } + predicate isFinal() { this.hasModifier("final") } /** Holds if this element has a `public` modifier or is implicitly public. */ - predicate isPublic() { hasModifier("public") } + predicate isPublic() { this.hasModifier("public") } /** Holds if this element has a `protected` modifier. */ - predicate isProtected() { hasModifier("protected") } + predicate isProtected() { this.hasModifier("protected") } /** Holds if this element has a `private` modifier or is implicitly private. */ - predicate isPrivate() { hasModifier("private") } + predicate isPrivate() { this.hasModifier("private") } /** Holds if this element has a `volatile` modifier. */ - predicate isVolatile() { hasModifier("volatile") } + predicate isVolatile() { this.hasModifier("volatile") } /** Holds if this element has a `synchronized` modifier. */ - predicate isSynchronized() { hasModifier("synchronized") } + predicate isSynchronized() { this.hasModifier("synchronized") } /** Holds if this element has a `native` modifier. */ - predicate isNative() { hasModifier("native") } + predicate isNative() { this.hasModifier("native") } /** Holds if this element has a `default` modifier. */ predicate isDefault() { this.hasModifier("default") } diff --git a/java/ql/lib/semmle/code/java/PrettyPrintAst.qll b/java/ql/lib/semmle/code/java/PrettyPrintAst.qll index 45e683a2466..6cb5769184a 100644 --- a/java/ql/lib/semmle/code/java/PrettyPrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrettyPrintAst.qll @@ -169,27 +169,27 @@ private class PpArrayCreationExpr extends PpAst, ArrayCreationExpr { override string getPart(int i) { i = 0 and result = "new " or - i = 1 and result = baseType() + i = 1 and result = this.baseType() or - i = 2 + 3 * dimensionIndex() and result = "[" + i = 2 + 3 * this.dimensionIndex() and result = "[" or - i = 4 + 3 * dimensionIndex() and result = "]" + i = 4 + 3 * this.dimensionIndex() and result = "]" or - i = 4 + 3 * exprDims() + [1 .. nonExprDims()] and result = "[]" + i = 4 + 3 * this.exprDims() + [1 .. this.nonExprDims()] and result = "[]" } private string baseType() { result = this.getType().(Array).getElementType().toString() } private int dimensionIndex() { exists(this.getDimension(result)) } - private int exprDims() { result = max(int j | j = 0 or j = 1 + dimensionIndex()) } + private int exprDims() { result = max(int j | j = 0 or j = 1 + this.dimensionIndex()) } - private int nonExprDims() { result = this.getType().(Array).getDimension() - exprDims() } + private int nonExprDims() { result = this.getType().(Array).getDimension() - this.exprDims() } override PpAst getChild(int i) { exists(int j | result = this.getDimension(j) and i = 3 + 3 * j) or - i = 5 + 3 * exprDims() + nonExprDims() and result = this.getInit() + i = 5 + 3 * this.exprDims() + this.nonExprDims() and result = this.getInit() } } @@ -539,27 +539,27 @@ private class PpForStmt extends PpAst, ForStmt { or exists(int j | j > 0 and exists(this.getInit(j)) and i = 2 + 2 * j and result = ", ") or - i = 1 + lastInitIndex() and result = "; " + i = 1 + this.lastInitIndex() and result = "; " or - i = 3 + lastInitIndex() and result = "; " + i = 3 + this.lastInitIndex() and result = "; " or exists(int j | - j > 0 and exists(this.getUpdate(j)) and i = 3 + lastInitIndex() + 2 * j and result = ", " + j > 0 and exists(this.getUpdate(j)) and i = 3 + this.lastInitIndex() + 2 * j and result = ", " ) or - i = 1 + lastUpdateIndex() and result = ")" + i = 1 + this.lastUpdateIndex() and result = ")" or - i = 2 + lastUpdateIndex() and result = " " and this.getStmt() instanceof BlockStmt + i = 2 + this.lastUpdateIndex() and result = " " and this.getStmt() instanceof BlockStmt } private int lastInitIndex() { result = 3 + 2 * max(int j | exists(this.getInit(j))) } private int lastUpdateIndex() { - result = 4 + lastInitIndex() + 2 * max(int j | exists(this.getUpdate(j))) + result = 4 + this.lastInitIndex() + 2 * max(int j | exists(this.getUpdate(j))) } override predicate newline(int i) { - i = 2 + lastUpdateIndex() and not this.getStmt() instanceof BlockStmt + i = 2 + this.lastUpdateIndex() and not this.getStmt() instanceof BlockStmt } override PpAst getChild(int i) { @@ -567,15 +567,15 @@ private class PpForStmt extends PpAst, ForStmt { or exists(int j | result = this.getInit(j) and i = 3 + 2 * j) or - i = 2 + lastInitIndex() and result = this.getCondition() + i = 2 + this.lastInitIndex() and result = this.getCondition() or - exists(int j | result = this.getUpdate(j) and i = 4 + lastInitIndex() + 2 * j) + exists(int j | result = this.getUpdate(j) and i = 4 + this.lastInitIndex() + 2 * j) or - i = 3 + lastUpdateIndex() and result = this.getStmt() + i = 3 + this.lastUpdateIndex() and result = this.getStmt() } override predicate indents(int i) { - i = 3 + lastUpdateIndex() and not this.getStmt() instanceof BlockStmt + i = 3 + this.lastUpdateIndex() and not this.getStmt() instanceof BlockStmt } } @@ -654,9 +654,9 @@ private class PpTryStmt extends PpAst, TryStmt { or exists(int j | exists(this.getResourceExpr(j)) and i = 3 + 2 * j and result = ";") or - i = 2 + lastResourceIndex() and result = ") " and exists(this.getAResource()) + i = 2 + this.lastResourceIndex() and result = ") " and exists(this.getAResource()) or - i = 1 + lastCatchIndex() and result = " finally " and exists(this.getFinally()) + i = 1 + this.lastCatchIndex() and result = " finally " and exists(this.getFinally()) } private int lastResourceIndex() { @@ -664,17 +664,17 @@ private class PpTryStmt extends PpAst, TryStmt { } private int lastCatchIndex() { - result = 4 + lastResourceIndex() + max(int j | exists(this.getCatchClause(j)) or j = 0) + result = 4 + this.lastResourceIndex() + max(int j | exists(this.getCatchClause(j)) or j = 0) } override PpAst getChild(int i) { exists(int j | i = 2 + 2 * j and result = this.getResource(j)) or - i = 3 + lastResourceIndex() and result = this.getBlock() + i = 3 + this.lastResourceIndex() and result = this.getBlock() or - exists(int j | i = 4 + lastResourceIndex() + j and result = this.getCatchClause(j)) + exists(int j | i = 4 + this.lastResourceIndex() + j and result = this.getCatchClause(j)) or - i = 2 + lastCatchIndex() and result = this.getFinally() + i = 2 + this.lastCatchIndex() and result = this.getFinally() } } @@ -728,11 +728,11 @@ private class PpSwitchCase extends PpAst, SwitchCase { or exists(int j | i = 2 * j and j != 0 and result = ", " and exists(this.(ConstCase).getValue(j))) or - i = 1 + lastConstCaseValueIndex() and result = ":" and not this.isRule() + i = 1 + this.lastConstCaseValueIndex() and result = ":" and not this.isRule() or - i = 1 + lastConstCaseValueIndex() and result = " -> " and this.isRule() + i = 1 + this.lastConstCaseValueIndex() and result = " -> " and this.isRule() or - i = 3 + lastConstCaseValueIndex() and result = ";" and exists(this.getRuleExpression()) + i = 3 + this.lastConstCaseValueIndex() and result = ";" and exists(this.getRuleExpression()) } private int lastConstCaseValueIndex() { @@ -742,9 +742,9 @@ private class PpSwitchCase extends PpAst, SwitchCase { override PpAst getChild(int i) { exists(int j | i = 1 + 2 * j and result = this.(ConstCase).getValue(j)) or - i = 2 + lastConstCaseValueIndex() and result = this.getRuleExpression() + i = 2 + this.lastConstCaseValueIndex() and result = this.getRuleExpression() or - i = 2 + lastConstCaseValueIndex() and result = this.getRuleStatement() + i = 2 + this.lastConstCaseValueIndex() and result = this.getRuleStatement() } } diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index d22065177bc..0d785e9ee28 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -151,7 +151,7 @@ class PrintAstNode extends TPrintAstNode { /** * Gets a child of this node. */ - final PrintAstNode getAChild() { result = getChild(_) } + final PrintAstNode getAChild() { result = this.getChild(_) } /** * Gets the parent of this node, if any. @@ -169,7 +169,7 @@ class PrintAstNode extends TPrintAstNode { */ string getProperty(string key) { key = "semmle.label" and - result = toString() + result = this.toString() } /** @@ -178,7 +178,7 @@ class PrintAstNode extends TPrintAstNode { * this. */ string getChildEdgeLabel(int childIndex) { - exists(getChild(childIndex)) and + exists(this.getChild(childIndex)) and result = childIndex.toString() } } @@ -259,7 +259,7 @@ final class AnnotationPartNode extends ExprStmtNode { override ElementNode getChild(int childIndex) { result.getElement() = rank[childIndex](Element ch, string file, int line, int column | - ch = getAnAnnotationChild() and locationSortKeys(ch, file, line, column) + ch = this.getAnAnnotationChild() and locationSortKeys(ch, file, line, column) | ch order by file, line, column ) @@ -352,7 +352,7 @@ private class SingleLocalVarDeclParent extends ExprOrStmt { LocalVariableDeclExpr getVariable() { result.getParent() = this } /** Gets the type access of the variable */ - Expr getTypeAccess() { result = getVariable().getTypeAccess() } + Expr getTypeAccess() { result = this.getVariable().getTypeAccess() } } /** @@ -460,7 +460,7 @@ final class ClassInterfaceNode extends ElementNode { childIndex >= 0 and result.(ElementNode).getElement() = rank[childIndex](Element e, string file, int line, int column | - e = getADeclaration() and locationSortKeys(e, file, line, column) + e = this.getADeclaration() and locationSortKeys(e, file, line, column) | e order by file, line, column ) @@ -507,7 +507,7 @@ final class CompilationUnitNode extends ElementNode { childIndex >= 0 and result.(ElementNode).getElement() = rank[childIndex](Element e, string file, int line, int column | - e = getADeclaration() and locationSortKeys(e, file, line, column) + e = this.getADeclaration() and locationSortKeys(e, file, line, column) | e order by file, line, column ) diff --git a/java/ql/lib/semmle/code/java/Reflection.qll b/java/ql/lib/semmle/code/java/Reflection.qll index ac6046824f6..71864c5cfe9 100644 --- a/java/ql/lib/semmle/code/java/Reflection.qll +++ b/java/ql/lib/semmle/code/java/Reflection.qll @@ -55,7 +55,7 @@ abstract private class ReflectiveClassIdentifier extends Expr { private class ReflectiveClassIdentifierLiteral extends ReflectiveClassIdentifier, TypeLiteral { override RefType getReflectivelyIdentifiedClass() { - result = getReferencedType().(RefType).getSourceDeclaration() + result = this.getReferencedType().(RefType).getSourceDeclaration() } } @@ -65,21 +65,21 @@ private class ReflectiveClassIdentifierLiteral extends ReflectiveClassIdentifier class ReflectiveClassIdentifierMethodAccess extends ReflectiveClassIdentifier, MethodAccess { ReflectiveClassIdentifierMethodAccess() { // A call to `Class.forName(...)`, from which we can infer `T` in the returned type `Class<T>`. - getCallee().getDeclaringType() instanceof TypeClass and getCallee().hasName("forName") + this.getCallee().getDeclaringType() instanceof TypeClass and this.getCallee().hasName("forName") or // A call to `ClassLoader.loadClass(...)`, from which we can infer `T` in the returned type `Class<T>`. - getCallee().getDeclaringType().hasQualifiedName("java.lang", "ClassLoader") and - getCallee().hasName("loadClass") + this.getCallee().getDeclaringType().hasQualifiedName("java.lang", "ClassLoader") and + this.getCallee().hasName("loadClass") } /** * If the argument to this call is a `StringLiteral`, then return that string. */ - string getTypeName() { result = getArgument(0).(StringLiteral).getRepresentedString() } + string getTypeName() { result = this.getArgument(0).(StringLiteral).getRepresentedString() } override RefType getReflectivelyIdentifiedClass() { // We only handle cases where the class is specified as a string literal to this call. - result.getQualifiedName() = getTypeName() + result.getQualifiedName() = this.getTypeName() } } @@ -214,10 +214,10 @@ private predicate expectsEnclosingInstance(RefType r) { class NewInstance extends MethodAccess { NewInstance() { ( - getCallee().getDeclaringType() instanceof TypeClass or - getCallee().getDeclaringType() instanceof TypeConstructor + this.getCallee().getDeclaringType() instanceof TypeClass or + this.getCallee().getDeclaringType() instanceof TypeConstructor ) and - getCallee().hasName("newInstance") + this.getCallee().hasName("newInstance") } /** @@ -225,26 +225,26 @@ class NewInstance extends MethodAccess { * called. */ Constructor getInferredConstructor() { - result = getInferredConstructedType().getAConstructor() and - if getCallee().getDeclaringType() instanceof TypeClass + result = this.getInferredConstructedType().getAConstructor() and + if this.getCallee().getDeclaringType() instanceof TypeClass then result.getNumberOfParameters() = 0 else - if getNumArgument() = 1 and getArgument(0).getType() instanceof Array + if this.getNumArgument() = 1 and this.getArgument(0).getType() instanceof Array then // This is a var-args array argument. If array argument is initialized inline, then identify // the number of arguments specified in the array. - if exists(getArgument(0).(ArrayCreationExpr).getInit()) + if exists(this.getArgument(0).(ArrayCreationExpr).getInit()) then // Count the number of elements in the initializer, and find the matching constructors. - matchConstructorArguments(result, - count(getArgument(0).(ArrayCreationExpr).getInit().getAnInit())) + this.matchConstructorArguments(result, + count(this.getArgument(0).(ArrayCreationExpr).getInit().getAnInit())) else // Could be any of the constructors on this class. any() else // No var-args in play, just use the number of arguments to the `newInstance(..)` to determine // which constructors may be called. - matchConstructorArguments(result, getNumArgument()) + this.matchConstructorArguments(result, this.getNumArgument()) } /** @@ -273,13 +273,13 @@ class NewInstance extends MethodAccess { not result instanceof TypeVariable and ( // If this is called on a `Class<T>` instance, return the inferred type `T`. - result = inferClassParameterType(getQualifier()) + result = inferClassParameterType(this.getQualifier()) or // If this is called on a `Constructor<T>` instance, return the inferred type `T`. - result = inferConstructorParameterType(getQualifier()) + result = inferConstructorParameterType(this.getQualifier()) or // If the result of this is cast to a particular type, then use that type. - result = getCastInferredConstructedTypes() + result = this.getCastInferredConstructedTypes() ) } @@ -313,7 +313,7 @@ class ClassMethodAccess extends MethodAccess { // `TypeVariable`s do not have methods themselves. not result instanceof TypeVariable and // If this is called on a `Class<T>` instance, return the inferred type `T`. - result = inferClassParameterType(getQualifier()) + result = inferClassParameterType(this.getQualifier()) } } @@ -354,13 +354,13 @@ class ReflectiveMethodAccess extends ClassMethodAccess { if this.getCallee().hasName("getDeclaredMethod") then // The method must be declared on the type itself. - result.getDeclaringType() = getInferredClassType() + result.getDeclaringType() = this.getInferredClassType() else // The method may be declared on an inferred type or a super-type. - getInferredClassType().inherits(result) + this.getInferredClassType().inherits(result) ) and // Only consider instances where the method name is provided as a `StringLiteral`. - result.hasName(getArgument(0).(StringLiteral).getRepresentedString()) + result.hasName(this.getArgument(0).(StringLiteral).getRepresentedString()) } } @@ -373,7 +373,9 @@ class ReflectiveAnnotationAccess extends ClassMethodAccess { /** * Gets a possible annotation type for this reflective annotation access. */ - AnnotationType getAPossibleAnnotationType() { result = inferClassParameterType(getArgument(0)) } + AnnotationType getAPossibleAnnotationType() { + result = inferClassParameterType(this.getArgument(0)) + } } /** @@ -391,13 +393,13 @@ class ReflectiveFieldAccess extends ClassMethodAccess { if this.getCallee().hasName("getDeclaredField") then // Declared fields must be on the type itself. - result.getDeclaringType() = getInferredClassType() + result.getDeclaringType() = this.getInferredClassType() else ( // This field must be public, and be inherited by one of the inferred class types. result.isPublic() and - getInferredClassType().inherits(result) + this.getInferredClassType().inherits(result) ) ) and - result.hasName(getArgument(0).(StringLiteral).getRepresentedString()) + result.hasName(this.getArgument(0).(StringLiteral).getRepresentedString()) } } diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index a5f9eb81080..c3b4deef6a3 100755 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -71,7 +71,7 @@ class BlockStmt extends Stmt, @block { int getNumStmt() { result = count(this.getAStmt()) } /** Gets the last statement in this block. */ - Stmt getLastStmt() { result = getStmt(getNumStmt() - 1) } + Stmt getLastStmt() { result = this.getStmt(this.getNumStmt() - 1) } override string pp() { result = "{ ... }" } @@ -93,7 +93,7 @@ class SingletonBlock extends BlockStmt { SingletonBlock() { this.getNumStmt() = 1 } /** Gets the single statement in this block. */ - Stmt getStmt() { result = getStmt(0) } + Stmt getStmt() { result = this.getStmt(0) } } /** @@ -125,7 +125,7 @@ class IfStmt extends ConditionalStmt, @ifstmt { * Gets the statement that is executed whenever the condition * of this branch statement evaluates to `true`. */ - deprecated override Stmt getTrueSuccessor() { result = getThen() } + deprecated override Stmt getTrueSuccessor() { result = this.getThen() } /** Gets the `else` branch of this `if` statement. */ Stmt getElse() { result.isNthChildOf(this, 2) } @@ -155,7 +155,7 @@ class ForStmt extends ConditionalStmt, @forstmt { /** Gets the initializer expression of the loop at the specified (zero-based) position. */ Expr getInit(int index) { - result = getAnInit() and + result = this.getAnInit() and index = -1 - result.getIndex() } @@ -167,7 +167,7 @@ class ForStmt extends ConditionalStmt, @forstmt { /** Gets the update expression of this loop at the specified (zero-based) position. */ Expr getUpdate(int index) { - result = getAnUpdate() and + result = this.getAnUpdate() and index = result.getIndex() - 3 } @@ -178,7 +178,7 @@ class ForStmt extends ConditionalStmt, @forstmt { * Gets the statement that is executed whenever the condition * of this branch statement evaluates to true. */ - deprecated override Stmt getTrueSuccessor() { result = getStmt() } + deprecated override Stmt getTrueSuccessor() { result = this.getStmt() } /** * Gets a variable that is used as an iteration variable: it is defined, @@ -193,12 +193,12 @@ class ForStmt extends ConditionalStmt, @forstmt { */ Variable getAnIterationVariable() { // Check that the variable is assigned to, incremented or decremented in the update expression, and... - exists(Expr update | update = getAnUpdate().getAChildExpr*() | + exists(Expr update | update = this.getAnUpdate().getAChildExpr*() | update.(UnaryAssignExpr).getExpr() = result.getAnAccess() or update = result.getAnAssignedValue() ) and // ...that it is checked or used in the condition. - getCondition().getAChildExpr*() = result.getAnAccess() + this.getCondition().getAChildExpr*() = result.getAnAccess() } override string pp() { result = "for (...;...;...) " + this.getStmt().pp() } @@ -242,7 +242,7 @@ class WhileStmt extends ConditionalStmt, @whilestmt { * Gets the statement that is executed whenever the condition * of this branch statement evaluates to true. */ - deprecated override Stmt getTrueSuccessor() { result = getStmt() } + deprecated override Stmt getTrueSuccessor() { result = this.getStmt() } override string pp() { result = "while (...) " + this.getStmt().pp() } @@ -265,7 +265,7 @@ class DoStmt extends ConditionalStmt, @dostmt { * Gets the statement that is executed whenever the condition * of this branch statement evaluates to `true`. */ - deprecated override Stmt getTrueSuccessor() { result = getStmt() } + deprecated override Stmt getTrueSuccessor() { result = this.getStmt() } override string pp() { result = "do " + this.getStmt().pp() + " while (...)" } @@ -343,17 +343,17 @@ class TryStmt extends Stmt, @trystmt { } /** Gets a resource in this `try` statement, if any. */ - ExprParent getAResource() { result = getAResourceDecl() or result = getAResourceExpr() } + ExprParent getAResource() { result = this.getAResourceDecl() or result = this.getAResourceExpr() } /** Gets the resource at the specified position in this `try` statement. */ ExprParent getResource(int index) { - result = getResourceDecl(index) or result = getResourceExpr(index) + result = this.getResourceDecl(index) or result = this.getResourceExpr(index) } /** Gets a resource variable, if any, either from a resource variable declaration or resource expression. */ Variable getAResourceVariable() { - result = getAResourceDecl().getAVariable().getVariable() or - result = getAResourceExpr().getVariable() + result = this.getAResourceDecl().getAVariable().getVariable() or + result = this.getAResourceExpr().getVariable() } override string pp() { result = "try " + this.getBlock().pp() + " catch (...)" } @@ -381,7 +381,7 @@ class CatchClause extends Stmt, @catchclause { /** Gets a type caught by this `catch` clause. */ RefType getACaughtType() { - exists(Expr ta | ta = getVariable().getTypeAccess() | + exists(Expr ta | ta = this.getVariable().getTypeAccess() | result = ta.(TypeAccess).getType() or result = ta.(UnionTypeAccess).getAnAlternative().getType() ) @@ -411,7 +411,7 @@ class SwitchStmt extends Stmt, @switchstmt { * Gets a case of this `switch` statement, * which may be either a normal `case` or a `default`. */ - SwitchCase getACase() { result = getAConstCase() or result = getDefaultCase() } + SwitchCase getACase() { result = this.getAConstCase() or result = this.getDefaultCase() } /** Gets a (non-default) `case` of this `switch` statement. */ ConstCase getAConstCase() { result.getParent() = this } @@ -550,7 +550,7 @@ class ThrowStmt extends Stmt, @throwstmt { override string getHalsteadID() { result = "ThrowStmt" } /** Gets the type of the expression thrown by this `throw` statement. */ - RefType getThrownExceptionType() { result = getExpr().getType() } + RefType getThrownExceptionType() { result = this.getExpr().getType() } /** * Gets the `catch` clause that catches the exception @@ -559,14 +559,14 @@ class ThrowStmt extends Stmt, @throwstmt { * provided such a `catch` exists. */ CatchClause getLexicalCatchIfAny() { - exists(TryStmt try | try = findEnclosing() and result = catchClauseForThis(try)) + exists(TryStmt try | try = this.findEnclosing() and result = this.catchClauseForThis(try)) } private Stmt findEnclosing() { - result = getEnclosingStmt() + result = this.getEnclosingStmt() or exists(Stmt mid | - mid = findEnclosing() and + mid = this.findEnclosing() and not exists(this.catchClauseForThis(mid.(TryStmt))) and result = mid.getEnclosingStmt() ) @@ -575,7 +575,7 @@ class ThrowStmt extends Stmt, @throwstmt { private CatchClause catchClauseForThis(TryStmt try) { result = try.getACatchClause() and result.getEnclosingCallable() = this.getEnclosingCallable() and - getExpr().getType().(RefType).hasSupertype*(result.getVariable().getType().(RefType)) and + this.getExpr().getType().(RefType).hasSupertype*(result.getVariable().getType().(RefType)) and not this.getEnclosingStmt+() = result } @@ -599,7 +599,7 @@ class JumpStmt extends Stmt { namestrings(result.getLabel(), _, this) } - private Stmt getLabelTarget() { result = getTargetLabel().getStmt() } + private Stmt getLabelTarget() { result = this.getTargetLabel().getStmt() } private Stmt getAPotentialTarget() { this.getEnclosingStmt+() = result and @@ -613,20 +613,20 @@ class JumpStmt extends Stmt { private SwitchExpr getSwitchExprTarget() { result = this.(YieldStmt).getParent+() } private StmtParent getEnclosingTarget() { - result = getSwitchExprTarget() + result = this.getSwitchExprTarget() or - not exists(getSwitchExprTarget()) and - result = getAPotentialTarget() and - not exists(Stmt other | other = getAPotentialTarget() | other.getEnclosingStmt+() = result) + not exists(this.getSwitchExprTarget()) and + result = this.getAPotentialTarget() and + not exists(Stmt other | other = this.getAPotentialTarget() | other.getEnclosingStmt+() = result) } /** * Gets the statement or `switch` expression that this `break`, `yield` or `continue` jumps to. */ StmtParent getTarget() { - result = getLabelTarget() + result = this.getLabelTarget() or - not exists(getLabelTarget()) and result = getEnclosingTarget() + not exists(this.getLabelTarget()) and result = this.getEnclosingTarget() } } @@ -714,9 +714,9 @@ class ExprStmt extends Stmt, @exprstmt { /** Holds if this statement represents a field declaration with an initializer. */ predicate isFieldDecl() { - getEnclosingCallable() instanceof InitializerMethod and + this.getEnclosingCallable() instanceof InitializerMethod and exists(FieldDeclaration fd, Location fdl, Location sl | - fdl = fd.getLocation() and sl = getLocation() + fdl = fd.getLocation() and sl = this.getLocation() | fdl.getFile() = sl.getFile() and fdl.getStartLine() = sl.getStartLine() and @@ -775,7 +775,7 @@ class LocalVariableDeclStmt extends Stmt, @localvariabledeclstmt { } /** Gets an index of a variable declared in this local variable declaration statement. */ - int getAVariableIndex() { exists(getVariable(result)) } + int getAVariableIndex() { exists(this.getVariable(result)) } override string pp() { result = "var ...;" } diff --git a/java/ql/lib/semmle/code/java/StringFormat.qll b/java/ql/lib/semmle/code/java/StringFormat.qll index cc37ee8212a..c6f9a7814db 100644 --- a/java/ql/lib/semmle/code/java/StringFormat.qll +++ b/java/ql/lib/semmle/code/java/StringFormat.qll @@ -152,15 +152,15 @@ class FormattingCall extends Call { private Expr getLastArg() { exists(Expr last | last = this.getArgument(this.getNumArgument() - 1) | if this.hasExplicitVarargsArray() - then result = last.(ArrayCreationExpr).getInit().getInit(getVarargsCount() - 1) + then result = last.(ArrayCreationExpr).getInit().getInit(this.getVarargsCount() - 1) else result = last ) } /** Holds if this uses the "logger ({})" format syntax and the last argument is a `Throwable`. */ predicate hasTrailingThrowableArgument() { - getSyntax() = TFmtLogger() and - getLastArg().getType().(RefType).getASourceSupertype*() instanceof TypeThrowable + this.getSyntax() = TFmtLogger() and + this.getLastArg().getType().(RefType).getASourceSupertype*() instanceof TypeThrowable } /** Gets the argument to this call in the position of the format string */ @@ -171,7 +171,7 @@ class FormattingCall extends Call { exists(int i | result = this.getArgument(i) and i > this.getFormatStringIndex() and - not hasExplicitVarargsArray() + not this.hasExplicitVarargsArray() ) } @@ -433,15 +433,15 @@ private class PrintfFormatString extends FormatString { override int getMaxFmtSpecIndex() { result = max(int ix | - ix = fmtSpecRefersToSpecificIndex(_) or - ix = count(int i | fmtSpecRefersToSequentialIndex(i)) + ix = this.fmtSpecRefersToSpecificIndex(_) or + ix = count(int i | this.fmtSpecRefersToSequentialIndex(i)) ) } override int getASkippedFmtSpecIndex() { - result in [1 .. getMaxFmtSpecIndex()] and - result > count(int i | fmtSpecRefersToSequentialIndex(i)) and - not result = fmtSpecRefersToSpecificIndex(_) + result in [1 .. this.getMaxFmtSpecIndex()] and + result > count(int i | this.fmtSpecRefersToSequentialIndex(i)) and + not result = this.fmtSpecRefersToSpecificIndex(_) } private int getFmtSpecRank(int specOffset) { @@ -449,14 +449,14 @@ private class PrintfFormatString extends FormatString { } override int getAnArgUsageOffset(int argNo) { - argNo = fmtSpecRefersToSpecificIndex(result) + argNo = this.fmtSpecRefersToSpecificIndex(result) or - result = rank[argNo](int i | fmtSpecRefersToSequentialIndex(i)) + result = rank[argNo](int i | this.fmtSpecRefersToSequentialIndex(i)) or - fmtSpecRefersToPrevious(result) and + this.fmtSpecRefersToPrevious(result) and exists(int previousOffset | - getFmtSpecRank(previousOffset) = getFmtSpecRank(result) - 1 and - previousOffset = getAnArgUsageOffset(argNo) + this.getFmtSpecRank(previousOffset) = this.getFmtSpecRank(result) - 1 and + previousOffset = this.getAnArgUsageOffset(argNo) ) } } @@ -479,10 +479,12 @@ private class LoggerFormatString extends FormatString { private predicate fmtPlaceholder(int i) { this.charAt(i) = "{" and this.charAt(i + 1) = "}" and - not true = isUnescapedBackslash(i - 1) + not true = this.isUnescapedBackslash(i - 1) } - override int getMaxFmtSpecIndex() { result = count(int i | fmtPlaceholder(i)) } + override int getMaxFmtSpecIndex() { result = count(int i | this.fmtPlaceholder(i)) } - override int getAnArgUsageOffset(int argNo) { result = rank[argNo](int i | fmtPlaceholder(i)) } + override int getAnArgUsageOffset(int argNo) { + result = rank[argNo](int i | this.fmtPlaceholder(i)) + } } diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index 492d1b546cb..1d0658595b2 100755 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -379,7 +379,7 @@ class RefType extends Type, Annotatable, Modifiable, @reftype { } /** Holds if this type declares any members. */ - predicate hasMember() { exists(getAMember()) } + predicate hasMember() { exists(this.getAMember()) } /** Gets a member declared in this type. */ Member getAMember() { this = result.getDeclaringType() } @@ -545,8 +545,10 @@ class RefType extends Type, Annotatable, Modifiable, @reftype { * `java.lang.Thread$State`. */ string getQualifiedName() { - exists(string pkgName | pkgName = getPackage().getName() | - if pkgName = "" then result = nestedName() else result = pkgName + "." + nestedName() + exists(string pkgName | pkgName = this.getPackage().getName() | + if pkgName = "" + then result = this.nestedName() + else result = pkgName + "." + this.nestedName() ) } @@ -656,7 +658,7 @@ class IntersectionType extends RefType, @class { /** Gets a textual representation of this type that includes all the intersected types. */ string getLongName() { - result = superType().toString() + concat(" & " + superInterface().toString()) + result = this.superType().toString() + concat(" & " + this.superInterface().toString()) } /** Gets the first bound of this intersection type. */ @@ -690,7 +692,8 @@ class AnonymousClass extends NestedClass { override string getTypeDescriptor() { exists(RefType parent | parent = this.getEnclosingType() | exists(int num | - num = 1 + count(AnonymousClass other | other.rankInParent(parent) < rankInParent(parent)) + num = + 1 + count(AnonymousClass other | other.rankInParent(parent) < this.rankInParent(parent)) | exists(string parentWithSemi | parentWithSemi = parent.getTypeDescriptor() | result = parentWithSemi.prefix(parentWithSemi.length() - 1) + "$" + num + ";" @@ -760,8 +763,8 @@ class NestedType extends RefType { /** Gets the nesting depth of this nested type. Top-level types have nesting depth 0. */ int getNestingDepth() { - if getEnclosingType() instanceof NestedType - then result = getEnclosingType().(NestedType).getNestingDepth() + 1 + if this.getEnclosingType() instanceof NestedType + then result = this.getEnclosingType().(NestedType).getNestingDepth() + 1 else result = 1 } @@ -776,7 +779,7 @@ class NestedType extends RefType { super.isStrictfp() or // JLS 8.1.1.3, JLS 9.1.1.2 - getEnclosingType().isStrictfp() + this.getEnclosingType().isStrictfp() } override predicate isStatic() { @@ -860,9 +863,9 @@ class ClassOrInterface extends RefType, @classorinterface { /** Holds if this class or interface is package protected, that is, neither public nor private nor protected. */ predicate isPackageProtected() { - not isPrivate() and - not isProtected() and - not isPublic() + not this.isPrivate() and + not this.isProtected() and + not this.isPublic() } } @@ -948,12 +951,12 @@ class PrimitiveType extends Type, @primitive { * require an explicit cast. */ Literal getADefaultValue() { - getName() = "boolean" and result.getLiteral() = "false" + this.getName() = "boolean" and result.getLiteral() = "false" or - getName() = "char" and + this.getName() = "char" and (result.getLiteral() = "'\\0'" or result.getLiteral() = "'\\u0000'") or - getName().regexpMatch("(float|double|int|short|byte|long)") and + this.getName().regexpMatch("(float|double|int|short|byte|long)") and result.getLiteral().regexpMatch("0(\\.0)?+[lLfFdD]?+") } @@ -1047,7 +1050,7 @@ class EnumType extends Class { override predicate isFinal() { // JLS 8.9: An enum declaration is implicitly `final` unless it contains // at least one enum constant that has a class body. - not getAnEnumConstant().getAnAssignedValue().getType() instanceof AnonymousClass + not this.getAnEnumConstant().getAnAssignedValue().getType() instanceof AnonymousClass } } diff --git a/java/ql/lib/semmle/code/java/UnitTests.qll b/java/ql/lib/semmle/code/java/UnitTests.qll index 1adc88d35f7..e8a0c02accc 100644 --- a/java/ql/lib/semmle/code/java/UnitTests.qll +++ b/java/ql/lib/semmle/code/java/UnitTests.qll @@ -115,7 +115,7 @@ class JUnitJupiterTestMethod extends Method { * A JUnit `@Ignore` annotation. */ class JUnitIgnoreAnnotation extends Annotation { - JUnitIgnoreAnnotation() { getType().hasQualifiedName("org.junit", "Ignore") } + JUnitIgnoreAnnotation() { this.getType().hasQualifiedName("org.junit", "Ignore") } } /** @@ -124,7 +124,7 @@ class JUnitIgnoreAnnotation extends Annotation { */ class JUnitIgnoredMethod extends Method { JUnitIgnoredMethod() { - getAnAnnotation() instanceof JUnitIgnoreAnnotation + this.getAnAnnotation() instanceof JUnitIgnoreAnnotation or exists(Class c | c = this.getDeclaringType() | c.getAnAnnotation() instanceof JUnitIgnoreAnnotation @@ -136,14 +136,14 @@ class JUnitIgnoredMethod extends Method { * An annotation in TestNG. */ class TestNGAnnotation extends Annotation { - TestNGAnnotation() { getType().getPackage().hasName("org.testng.annotations") } + TestNGAnnotation() { this.getType().getPackage().hasName("org.testng.annotations") } } /** * An annotation of type `org.test.ng.annotations.Test`. */ class TestNGTestAnnotation extends TestNGAnnotation { - TestNGTestAnnotation() { getType().hasName("Test") } + TestNGTestAnnotation() { this.getType().hasName("Test") } } /** @@ -158,13 +158,13 @@ class TestNGTestMethod extends Method { */ TestNGDataProviderMethod getADataProvider() { exists(TestNGTestAnnotation testAnnotation | - testAnnotation = getAnAnnotation() and + testAnnotation = this.getAnAnnotation() and // The data provider must have the same name as the referenced data provider result.getDataProviderName() = testAnnotation.getValue("dataProvider").(StringLiteral).getRepresentedString() | // Either the data provider should be on the current class, or a supertype - getDeclaringType().getAnAncestor() = result.getDeclaringType() + this.getDeclaringType().getAnAncestor() = result.getDeclaringType() or // Or the data provider class should be declared result.getDeclaringType() = @@ -190,14 +190,14 @@ class TestMethod extends Method { * A TestNG annotation used to mark a method that runs "before". */ class TestNGBeforeAnnotation extends TestNGAnnotation { - TestNGBeforeAnnotation() { getType().getName().matches("Before%") } + TestNGBeforeAnnotation() { this.getType().getName().matches("Before%") } } /** * A TestNG annotation used to mark a method that runs "after". */ class TestNGAfterAnnotation extends TestNGAnnotation { - TestNGAfterAnnotation() { getType().getName().matches("After%") } + TestNGAfterAnnotation() { this.getType().getName().matches("After%") } } /** @@ -205,7 +205,7 @@ class TestNGAfterAnnotation extends TestNGAnnotation { * them as data provider methods for TestNG. */ class TestNGDataProviderAnnotation extends TestNGAnnotation { - TestNGDataProviderAnnotation() { getType().hasName("DataProvider") } + TestNGDataProviderAnnotation() { this.getType().hasName("DataProvider") } } /** @@ -213,7 +213,7 @@ class TestNGDataProviderAnnotation extends TestNGAnnotation { * them as factory methods for TestNG. */ class TestNGFactoryAnnotation extends TestNGAnnotation { - TestNGFactoryAnnotation() { getType().hasName("Factory") } + TestNGFactoryAnnotation() { this.getType().hasName("Factory") } } /** @@ -221,13 +221,13 @@ class TestNGFactoryAnnotation extends TestNGAnnotation { * which listeners apply to them. */ class TestNGListenersAnnotation extends TestNGAnnotation { - TestNGListenersAnnotation() { getType().hasName("Listeners") } + TestNGListenersAnnotation() { this.getType().hasName("Listeners") } /** * Gets a listener defined in this annotation. */ TestNGListenerImpl getAListener() { - result = getAValue("value").(TypeLiteral).getReferencedType() + result = this.getAValue("value").(TypeLiteral).getReferencedType() } } @@ -235,7 +235,7 @@ class TestNGListenersAnnotation extends TestNGAnnotation { * A concrete implementation class of one or more of the TestNG listener interfaces. */ class TestNGListenerImpl extends Class { - TestNGListenerImpl() { getAnAncestor().hasQualifiedName("org.testng", "ITestNGListener") } + TestNGListenerImpl() { this.getAnAncestor().hasQualifiedName("org.testng", "ITestNGListener") } } /** @@ -246,14 +246,14 @@ class TestNGListenerImpl extends Class { * an instance of a particular value when running a test method. */ class TestNGDataProviderMethod extends Method { - TestNGDataProviderMethod() { getAnAnnotation() instanceof TestNGDataProviderAnnotation } + TestNGDataProviderMethod() { this.getAnAnnotation() instanceof TestNGDataProviderAnnotation } /** * Gets the name associated with this data provider. */ string getDataProviderName() { result = - getAnAnnotation() + this.getAnAnnotation() .(TestNGDataProviderAnnotation) .getValue("name") .(StringLiteral) @@ -268,7 +268,7 @@ class TestNGDataProviderMethod extends Method { * This factory callable is used to generate instances of parameterized test classes. */ class TestNGFactoryCallable extends Callable { - TestNGFactoryCallable() { getAnAnnotation() instanceof TestNGFactoryAnnotation } + TestNGFactoryCallable() { this.getAnAnnotation() instanceof TestNGFactoryAnnotation } } /** @@ -276,7 +276,7 @@ class TestNGFactoryCallable extends Callable { */ class ParameterizedJUnitTest extends Class { ParameterizedJUnitTest() { - getAnAnnotation() + this.getAnAnnotation() .(RunWithAnnotation) .getRunner() .(Class) @@ -289,7 +289,7 @@ class ParameterizedJUnitTest extends Class { */ class JUnitCategoryAnnotation extends Annotation { JUnitCategoryAnnotation() { - getType().hasQualifiedName("org.junit.experimental.categories", "Category") + this.getType().hasQualifiedName("org.junit.experimental.categories", "Category") } /** @@ -297,7 +297,7 @@ class JUnitCategoryAnnotation extends Annotation { */ Type getACategory() { exists(TypeLiteral literal, Expr value | - value = getValue("value") and + value = this.getValue("value") and ( literal = value or literal = value.(ArrayCreationExpr).getInit().getAnInit() @@ -313,7 +313,7 @@ class JUnitCategoryAnnotation extends Annotation { */ class JUnitTheoryTest extends Class { JUnitTheoryTest() { - getAnAnnotation() + this.getAnAnnotation() .(RunWithAnnotation) .getRunner() .(Class) diff --git a/java/ql/lib/semmle/code/java/Variable.qll b/java/ql/lib/semmle/code/java/Variable.qll index 439ee5d3f6b..530ddd4eae7 100755 --- a/java/ql/lib/semmle/code/java/Variable.qll +++ b/java/ql/lib/semmle/code/java/Variable.qll @@ -47,12 +47,12 @@ class LocalVariableDecl extends @localvar, LocalScopeVariable { override Callable getCallable() { result = this.getParent().getEnclosingCallable() } /** Gets the callable in which this declaration occurs. */ - Callable getEnclosingCallable() { result = getCallable() } + Callable getEnclosingCallable() { result = this.getCallable() } override string toString() { result = this.getType().getName() + " " + this.getName() } /** Gets the initializer expression of this local variable declaration. */ - override Expr getInitializer() { result = getDeclExpr().getInit() } + override Expr getInitializer() { result = this.getDeclExpr().getInit() } override string getAPrimaryQlClass() { result = "LocalVariableDecl" } } @@ -63,7 +63,7 @@ class Parameter extends Element, @param, LocalScopeVariable { override Type getType() { params(this, result, _, _, _) } /** Holds if the parameter is never assigned a value in the body of the callable. */ - predicate isEffectivelyFinal() { not exists(getAnAssignedValue()) } + predicate isEffectivelyFinal() { not exists(this.getAnAssignedValue()) } /** Gets the (zero-based) index of this formal parameter. */ int getPosition() { params(this, _, result, _, _) } @@ -87,8 +87,8 @@ class Parameter extends Element, @param, LocalScopeVariable { * Varargs parameters will have no results for this method. */ Expr getAnArgument() { - not isVarargs() and - result = getACallArgument(getPosition()) + not this.isVarargs() and + result = this.getACallArgument(this.getPosition()) } pragma[noinline] diff --git a/java/ql/lib/semmle/code/java/arithmetic/Overflow.qll b/java/ql/lib/semmle/code/java/arithmetic/Overflow.qll index 7227c6da398..4e9eb75ec13 100644 --- a/java/ql/lib/semmle/code/java/arithmetic/Overflow.qll +++ b/java/ql/lib/semmle/code/java/arithmetic/Overflow.qll @@ -2,9 +2,9 @@ import java /** A subclass of `PrimitiveType` with width-based ordering methods. */ class OrdPrimitiveType extends PrimitiveType { - predicate widerThan(OrdPrimitiveType that) { getWidthRank() > that.getWidthRank() } + predicate widerThan(OrdPrimitiveType that) { this.getWidthRank() > that.getWidthRank() } - predicate widerThanOrEqualTo(OrdPrimitiveType that) { getWidthRank() >= that.getWidthRank() } + predicate widerThanOrEqualTo(OrdPrimitiveType that) { this.getWidthRank() >= that.getWidthRank() } OrdPrimitiveType maxType(OrdPrimitiveType that) { this.widerThan(that) and result = this diff --git a/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll b/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll index c0b227ba9ba..5f1ed3438b5 100644 --- a/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll +++ b/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll @@ -25,13 +25,13 @@ class BasicBlock extends ControlFlowNode { /** Gets an immediate successor of this basic block. */ cached - BasicBlock getABBSuccessor() { result = getLastNode().getASuccessor() } + BasicBlock getABBSuccessor() { result = this.getLastNode().getASuccessor() } /** Gets an immediate predecessor of this basic block. */ BasicBlock getABBPredecessor() { result.getABBSuccessor() = this } /** Gets a control-flow node contained in this basic block. */ - ControlFlowNode getANode() { result = getNode(_) } + ControlFlowNode getANode() { result = this.getNode(_) } /** Gets the control-flow node at a specific (zero-indexed) position in this basic block. */ cached @@ -39,7 +39,7 @@ class BasicBlock extends ControlFlowNode { result = this and pos = 0 or exists(ControlFlowNode mid, int mid_pos | pos = mid_pos + 1 | - getNode(mid_pos) = mid and + this.getNode(mid_pos) = mid and mid.getASuccessor() = result and not result instanceof BasicBlock ) @@ -49,11 +49,11 @@ class BasicBlock extends ControlFlowNode { ControlFlowNode getFirstNode() { result = this } /** Gets the last control-flow node in this basic block. */ - ControlFlowNode getLastNode() { result = getNode(length() - 1) } + ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) } /** Gets the number of control-flow nodes contained in this basic block. */ cached - int length() { result = strictcount(getANode()) } + int length() { result = strictcount(this.getANode()) } /** Holds if this basic block strictly dominates `node`. */ predicate bbStrictlyDominates(BasicBlock node) { bbStrictlyDominates(this, node) } diff --git a/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll b/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll index 5ce27fda434..8e9d90769f3 100644 --- a/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll +++ b/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll @@ -12,13 +12,13 @@ import semmle.code.java.controlflow.Guards */ class ConstantField extends Field { ConstantField() { - getType() instanceof ImmutableType and + this.getType() instanceof ImmutableType and // Assigned once - count(getAnAssignedValue()) = 1 and + count(this.getAnAssignedValue()) = 1 and // And that assignment is either in the appropriate initializer, or, for instance fields on // classes with one constructor, in the constructor. - forall(FieldWrite fa | fa = getAnAccess() | - if isStatic() + forall(FieldWrite fa | fa = this.getAnAccess() | + if this.isStatic() then fa.getEnclosingCallable() instanceof StaticInitializer else ( // Defined in the instance initializer. @@ -26,7 +26,7 @@ class ConstantField extends Field { or // It can be defined in the constructor if there is only one constructor. fa.getEnclosingCallable() instanceof Constructor and - count(getDeclaringType().getAConstructor()) = 1 + count(this.getDeclaringType().getAConstructor()) = 1 ) ) } @@ -36,7 +36,7 @@ class ConstantField extends Field { * * Note: although this value is constant, we may not be able to statically determine the value. */ - ConstantExpr getConstantValue() { result = getAnAssignedValue() } + ConstantExpr getConstantValue() { result = this.getAnAssignedValue() } } /** @@ -162,18 +162,18 @@ class ConstSwitchStmt extends SwitchStmt { /** Gets the `ConstCase` that matches, if any. */ ConstCase getMatchingConstCase() { - result = getAConstCase() and + result = this.getAConstCase() and // Only handle the int case for now - result.getValue().(ConstantExpr).getIntValue() = getExpr().(ConstantExpr).getIntValue() + result.getValue().(ConstantExpr).getIntValue() = this.getExpr().(ConstantExpr).getIntValue() } /** Gets the matching case, if it can be deduced. */ SwitchCase getMatchingCase() { // Must be a value we can deduce - exists(getExpr().(ConstantExpr).getIntValue()) and - if exists(getMatchingConstCase()) - then result = getMatchingConstCase() - else result = getDefaultCase() + exists(this.getExpr().(ConstantExpr).getIntValue()) and + if exists(this.getMatchingConstCase()) + then result = this.getMatchingConstCase() + else result = this.getDefaultCase() } /** @@ -184,8 +184,8 @@ class ConstSwitchStmt extends SwitchStmt { SwitchCase getAFailingCase() { exists(SwitchCase matchingCase | // We must have found the matching case, otherwise we can't deduce which cases are not matched - matchingCase = getMatchingCase() and - result = getACase() and + matchingCase = this.getMatchingCase() and + result = this.getACase() and result != matchingCase ) } @@ -208,7 +208,7 @@ class UnreachableBasicBlock extends BasicBlock { or // This block is not reachable in the CFG, and is not a callable, a body of a callable, an // expression in an annotation, an expression in an assert statement, or a catch clause. - forall(BasicBlock bb | bb = getABBPredecessor() | bb instanceof UnreachableBasicBlock) and + forall(BasicBlock bb | bb = this.getABBPredecessor() | bb instanceof UnreachableBasicBlock) and not exists(Callable c | c.getBody() = this) and not this instanceof Callable and not exists(Annotation a | a.getAChildExpr*() = this) and @@ -231,12 +231,12 @@ class UnreachableBasicBlock extends BasicBlock { * An unreachable expression is an expression contained in an `UnreachableBasicBlock`. */ class UnreachableExpr extends Expr { - UnreachableExpr() { getBasicBlock() instanceof UnreachableBasicBlock } + UnreachableExpr() { this.getBasicBlock() instanceof UnreachableBasicBlock } } /** * An unreachable statement is a statement contained in an `UnreachableBasicBlock`. */ class UnreachableStmt extends Stmt { - UnreachableStmt() { getBasicBlock() instanceof UnreachableBasicBlock } + UnreachableStmt() { this.getBasicBlock() instanceof UnreachableBasicBlock } } diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll index a8f15a103c8..d8d02f995a6 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll @@ -45,8 +45,8 @@ private class RmiMethodParameterSource extends RemoteFlowSource { exists(RemoteCallableMethod method | method.getAParameter() = this.asParameter() and ( - getType() instanceof PrimitiveType or - getType() instanceof TypeString + this.getType() instanceof PrimitiveType or + this.getType() instanceof TypeString ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/SSA.qll b/java/ql/lib/semmle/code/java/dataflow/SSA.qll index 9a2a1df0915..dbcaafd3071 100644 --- a/java/ql/lib/semmle/code/java/dataflow/SSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/SSA.qll @@ -97,7 +97,7 @@ class SsaSourceVariable extends TSsaSourceVariable { else result = c.getName() + "(..)." + v.getName() ) or - result = this.(SsaSourceField).ppQualifier() + "." + getVariable().toString() + result = this.(SsaSourceField).ppQualifier() + "." + this.getVariable().toString() } /** @@ -117,7 +117,7 @@ class SsaSourceVariable extends TSsaSourceVariable { Location getLocation() { exists(LocalScopeVariable v | this = TLocalVar(_, v) and result = v.getLocation()) or - this instanceof SsaSourceField and result = getFirstAccess().getLocation() + this instanceof SsaSourceField and result = this.getFirstAccess().getLocation() } /** Gets the type of this variable. */ @@ -140,7 +140,7 @@ class SsaSourceField extends SsaSourceVariable { } /** Gets the field corresponding to this named field. */ - Field getField() { result = getVariable() } + Field getField() { result = this.getVariable() } /** Gets a string representation of the qualifier. */ string ppQualifier() { @@ -155,8 +155,8 @@ class SsaSourceField extends SsaSourceVariable { /** Holds if the field itself or any of the fields part of the qualifier are volatile. */ predicate isVolatile() { - getField().isVolatile() or - getQualifier().(SsaSourceField).isVolatile() + this.getField().isVolatile() or + this.getQualifier().(SsaSourceField).isVolatile() } } @@ -932,10 +932,10 @@ class SsaVariable extends TSsaVariable { string toString() { none() } /** Gets the source location for this element. */ - Location getLocation() { result = getCFGNode().getLocation() } + Location getLocation() { result = this.getCFGNode().getLocation() } /** Gets the `BasicBlock` in which this SSA variable is defined. */ - BasicBlock getBasicBlock() { result = getCFGNode().getBasicBlock() } + BasicBlock getBasicBlock() { result = this.getCFGNode().getBasicBlock() } /** Gets an access of this SSA variable. */ RValue getAUse() { @@ -989,14 +989,16 @@ class SsaUpdate extends SsaVariable { /** An SSA variable that is defined by a `VariableUpdate`. */ class SsaExplicitUpdate extends SsaUpdate, TSsaCertainUpdate { SsaExplicitUpdate() { - exists(VariableUpdate upd | upd = this.getCFGNode() and getDestVar(upd) = getSourceVariable()) + exists(VariableUpdate upd | + upd = this.getCFGNode() and getDestVar(upd) = this.getSourceVariable() + ) } - override string toString() { result = "SSA def(" + getSourceVariable() + ")" } + override string toString() { result = "SSA def(" + this.getSourceVariable() + ")" } /** Gets the `VariableUpdate` defining the SSA variable. */ VariableUpdate getDefiningExpr() { - result = this.getCFGNode() and getDestVar(result) = getSourceVariable() + result = this.getCFGNode() and getDestVar(result) = this.getSourceVariable() } } @@ -1010,22 +1012,22 @@ class SsaImplicitUpdate extends SsaUpdate { SsaImplicitUpdate() { not this instanceof SsaExplicitUpdate } override string toString() { - result = "SSA impl upd[" + getKind() + "](" + getSourceVariable() + ")" + result = "SSA impl upd[" + this.getKind() + "](" + this.getSourceVariable() + ")" } private string getKind() { this = TSsaUntracked(_, _) and result = "untracked" or - certainVariableUpdate(getSourceVariable().getQualifier(), getCFGNode(), _, _) and + certainVariableUpdate(this.getSourceVariable().getQualifier(), this.getCFGNode(), _, _) and result = "explicit qualifier" or - if uncertainVariableUpdate(getSourceVariable().getQualifier(), getCFGNode(), _, _) + if uncertainVariableUpdate(this.getSourceVariable().getQualifier(), this.getCFGNode(), _, _) then - if exists(getANonLocalUpdate()) + if exists(this.getANonLocalUpdate()) then result = "nonlocal + nonlocal qualifier" else result = "nonlocal qualifier" else ( - exists(getANonLocalUpdate()) and result = "nonlocal" + exists(this.getANonLocalUpdate()) and result = "nonlocal" ) } @@ -1034,9 +1036,9 @@ class SsaImplicitUpdate extends SsaUpdate { */ FieldWrite getANonLocalUpdate() { exists(SsaSourceField f, Callable setter | - f = getSourceVariable() and + f = this.getSourceVariable() and relevantFieldUpdate(setter, f.getField(), result) and - updatesNamedField(getCFGNode(), f, setter) + updatesNamedField(this.getCFGNode(), f, setter) ) } @@ -1049,8 +1051,8 @@ class SsaImplicitUpdate extends SsaUpdate { */ predicate assignsUnknownValue() { this = TSsaUntracked(_, _) or - certainVariableUpdate(getSourceVariable().getQualifier(), getCFGNode(), _, _) or - uncertainVariableUpdate(getSourceVariable().getQualifier(), getCFGNode(), _, _) + certainVariableUpdate(this.getSourceVariable().getQualifier(), this.getCFGNode(), _, _) or + uncertainVariableUpdate(this.getSourceVariable().getQualifier(), this.getCFGNode(), _, _) } } @@ -1072,30 +1074,31 @@ class SsaUncertainImplicitUpdate extends SsaImplicitUpdate, TSsaUncertainUpdate * includes initial values of parameters, fields, and closure variables. */ class SsaImplicitInit extends SsaVariable, TSsaEntryDef { - override string toString() { result = "SSA init(" + getSourceVariable() + ")" } + override string toString() { result = "SSA init(" + this.getSourceVariable() + ")" } /** Holds if this is a closure variable that captures the value of `capturedvar`. */ predicate captures(SsaVariable capturedvar) { - ssaDefReachesCapture(_, capturedvar, getSourceVariable()) + ssaDefReachesCapture(_, capturedvar, this.getSourceVariable()) } /** * Holds if the SSA variable is a parameter defined by its initial value in the callable. */ predicate isParameterDefinition(Parameter p) { - getSourceVariable() = TLocalVar(p.getCallable(), p) and p.getCallable().getBody() = getCFGNode() + this.getSourceVariable() = TLocalVar(p.getCallable(), p) and + p.getCallable().getBody() = this.getCFGNode() } } /** An SSA phi node. */ class SsaPhiNode extends SsaVariable, TSsaPhiNode { - override string toString() { result = "SSA phi(" + getSourceVariable() + ")" } + override string toString() { result = "SSA phi(" + this.getSourceVariable() + ")" } /** Gets an input to the phi node defining the SSA variable. */ SsaVariable getAPhiInput() { exists(BasicBlock phiPred, TrackedVar v | - v = getSourceVariable() and - getCFGNode().(BasicBlock).getABBPredecessor() = phiPred and + v = this.getSourceVariable() and + this.getCFGNode().(BasicBlock).getABBPredecessor() = phiPred and ssaDefReachesEndOfBlock(v, result, phiPred) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll index 8193a33bcb3..e0e6e64321f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll @@ -484,10 +484,10 @@ class BaseSsaVariable extends TBaseSsaVariable { string toString() { none() } - Location getLocation() { result = getCFGNode().getLocation() } + Location getLocation() { result = this.getCFGNode().getLocation() } /** Gets the `BasicBlock` in which this SSA variable is defined. */ - BasicBlock getBasicBlock() { result = getCFGNode().getBasicBlock() } + BasicBlock getBasicBlock() { result = this.getCFGNode().getBasicBlock() } /** Gets an access of this SSA variable. */ RValue getAUse() { ssaDefReachesUse(_, this, result) } @@ -532,14 +532,16 @@ class BaseSsaVariable extends TBaseSsaVariable { /** An SSA variable that is defined by a `VariableUpdate`. */ class BaseSsaUpdate extends BaseSsaVariable, TSsaUpdate { BaseSsaUpdate() { - exists(VariableUpdate upd | upd = this.getCFGNode() and getDestVar(upd) = getSourceVariable()) + exists(VariableUpdate upd | + upd = this.getCFGNode() and getDestVar(upd) = this.getSourceVariable() + ) } - override string toString() { result = "SSA def(" + getSourceVariable() + ")" } + override string toString() { result = "SSA def(" + this.getSourceVariable() + ")" } /** Gets the `VariableUpdate` defining the SSA variable. */ VariableUpdate getDefiningExpr() { - result = this.getCFGNode() and getDestVar(result) = getSourceVariable() + result = this.getCFGNode() and getDestVar(result) = this.getSourceVariable() } } @@ -548,30 +550,31 @@ class BaseSsaUpdate extends BaseSsaVariable, TSsaUpdate { * includes initial values of parameters, fields, and closure variables. */ class BaseSsaImplicitInit extends BaseSsaVariable, TSsaEntryDef { - override string toString() { result = "SSA init(" + getSourceVariable() + ")" } + override string toString() { result = "SSA init(" + this.getSourceVariable() + ")" } /** Holds if this is a closure variable that captures the value of `capturedvar`. */ predicate captures(BaseSsaVariable capturedvar) { - ssaDefReachesCapture(_, capturedvar, getSourceVariable()) + ssaDefReachesCapture(_, capturedvar, this.getSourceVariable()) } /** * Holds if the SSA variable is a parameter defined by its initial value in the callable. */ predicate isParameterDefinition(Parameter p) { - getSourceVariable() = TLocalVar(p.getCallable(), p) and p.getCallable().getBody() = getCFGNode() + this.getSourceVariable() = TLocalVar(p.getCallable(), p) and + p.getCallable().getBody() = this.getCFGNode() } } /** An SSA phi node. */ class BaseSsaPhiNode extends BaseSsaVariable, TSsaPhiNode { - override string toString() { result = "SSA phi(" + getSourceVariable() + ")" } + override string toString() { result = "SSA phi(" + this.getSourceVariable() + ")" } /** Gets an input to the phi node defining the SSA variable. */ BaseSsaVariable getAPhiInput() { exists(BasicBlock phiPred, BaseSsaSourceVariable v | - v = getSourceVariable() and - getCFGNode().(BasicBlock).getABBPredecessor() = phiPred and + v = this.getSourceVariable() and + this.getCFGNode().(BasicBlock).getABBPredecessor() = phiPred and ssaDefReachesEndOfBlock(v, result, phiPred) ) } 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 4ca06c93362..c3b2fc44f14 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll index 622ef595792..5ea421db0c7 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll @@ -117,9 +117,9 @@ module Public { * Gets an upper bound on the type of this node. */ Type getTypeBound() { - result = getImprovedTypeBound() + result = this.getImprovedTypeBound() or - result = getType() and not exists(getImprovedTypeBound()) + result = this.getType() and not exists(this.getImprovedTypeBound()) } /** @@ -132,7 +132,7 @@ module Public { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } } @@ -288,9 +288,9 @@ private class NewExpr extends PostUpdateNode, TExprNode { * A `PostUpdateNode` that is not a `ClassInstanceExpr`. */ abstract private class ImplicitPostUpdateNode extends PostUpdateNode { - override Location getLocation() { result = getPreUpdateNode().getLocation() } + override Location getLocation() { result = this.getPreUpdateNode().getLocation() } - override string toString() { result = getPreUpdateNode().toString() + " [post update]" } + override string toString() { result = this.getPreUpdateNode().toString() + " [post update]" } } private class ExplicitExprPostUpdate extends ImplicitPostUpdateNode, TExplicitExprPostUpdate { diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index e92ad541a51..e4bfaaae1cc 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -285,11 +285,11 @@ private predicate taintPreservingQualifierToMethod(Method m) { private class StringReplaceMethod extends TaintPreservingCallable { StringReplaceMethod() { - getDeclaringType() instanceof TypeString and + this.getDeclaringType() instanceof TypeString and ( - hasName("replace") or - hasName("replaceAll") or - hasName("replaceFirst") + this.hasName("replace") or + this.hasName("replaceAll") or + this.hasName("replaceFirst") ) } @@ -443,7 +443,7 @@ class ObjectOutputStreamVar extends LocalVariableDecl { } MethodAccess getAWriteObjectMethodAccess() { - result.getQualifier() = getAnAccess() and + result.getQualifier() = this.getAnAccess() and result.getMethod().hasName("writeObject") } } @@ -488,7 +488,7 @@ private class FormatterVar extends LocalVariableDecl { } MethodAccess getAFormatMethodAccess() { - result.getQualifier() = getAnAccess() and + result.getQualifier() = this.getAnAccess() and result.getMethod().hasName("format") } } @@ -513,13 +513,13 @@ private class FormatterCallable extends TaintPreservingCallable { } override predicate returnsTaintFrom(int arg) { - if this instanceof Constructor then arg = 0 else arg = [-1 .. getNumberOfParameters()] + if this instanceof Constructor then arg = 0 else arg = [-1 .. this.getNumberOfParameters()] } override predicate transfersTaint(int src, int sink) { this.hasName("format") and sink = -1 and - src = [0 .. getNumberOfParameters()] + src = [0 .. this.getNumberOfParameters()] } } @@ -532,13 +532,13 @@ module StringBuilderVarModule { * build up a query using string concatenation. */ class StringBuilderVar extends LocalVariableDecl { - StringBuilderVar() { getType() instanceof StringBuildingType } + StringBuilderVar() { this.getType() instanceof StringBuildingType } /** * Gets a call that adds something to this string builder, from the argument at the given index. */ MethodAccess getAnInput(int arg) { - result.getQualifier() = getAChainedReference() and + result.getQualifier() = this.getAChainedReference() and ( result.getMethod().getName() = "append" and arg = 0 or @@ -552,20 +552,20 @@ module StringBuilderVarModule { * Gets a call that appends something to this string builder. */ MethodAccess getAnAppend() { - result.getQualifier() = getAChainedReference() and + result.getQualifier() = this.getAChainedReference() and result.getMethod().getName() = "append" } MethodAccess getNextAppend(MethodAccess append) { - result = getAnAppend() and - append = getAnAppend() and + result = this.getAnAppend() and + append = this.getAnAppend() and ( result.getQualifier() = append or not exists(MethodAccess chainAccess | chainAccess.getQualifier() = append) and exists(RValue sbva1, RValue sbva2 | adjacentUseUse(sbva1, sbva2) and - append.getQualifier() = getAChainedReference(sbva1) and + append.getQualifier() = this.getAChainedReference(sbva1) and result.getQualifier() = sbva2 ) ) @@ -575,7 +575,7 @@ module StringBuilderVarModule { * Gets a call that converts this string builder to a string. */ MethodAccess getToStringCall() { - result.getQualifier() = getAChainedReference() and + result.getQualifier() = this.getAChainedReference() and result.getMethod().getName() = "toString" } @@ -590,7 +590,7 @@ module StringBuilderVarModule { /** * Gets an expression that refers to this `StringBuilder`, possibly after some chained calls. */ - Expr getAChainedReference() { result = getAChainedReference(_) } + Expr getAChainedReference() { result = this.getAChainedReference(_) } } } diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll b/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll index 48ee3d5563b..53e0ccc1f35 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll @@ -82,19 +82,19 @@ class SuppressedConstructor extends Constructor { SuppressedConstructor() { // Must be private or protected to suppress it. ( - isPrivate() + this.isPrivate() or // A protected, suppressed constructor only makes sense in a non-abstract class. - isProtected() and not getDeclaringType().isAbstract() + this.isProtected() and not this.getDeclaringType().isAbstract() ) and // Must be no-arg in order to replace the compiler generated default constructor. - getNumberOfParameters() = 0 and + this.getNumberOfParameters() = 0 and // Not the compiler-generated constructor itself. - not isDefaultConstructor() and + not this.isDefaultConstructor() and // Verify that there is only one statement, which is the `super()` call. This exists // even for empty constructors. - getBody().(BlockStmt).getNumStmt() = 1 and - getBody().(BlockStmt).getAStmt().(SuperConstructorInvocationStmt).getNumArgument() = 0 and + this.getBody().(BlockStmt).getNumStmt() = 1 and + this.getBody().(BlockStmt).getAStmt().(SuperConstructorInvocationStmt).getNumArgument() = 0 and // A constructor that is called is not acting to suppress the default constructor. We permit // calls from suppressed and default constructors - in both cases, they can only come from // sub-class constructors. @@ -105,7 +105,9 @@ class SuppressedConstructor extends Constructor { ) and // If other constructors are declared, then no compiler-generated constructor is added, so // this constructor is not acting to suppress the default compiler-generated constructor. - not exists(Constructor other | other = getDeclaringType().getAConstructor() and other != this) + not exists(Constructor other | + other = this.getDeclaringType().getAConstructor() and other != this + ) } } @@ -114,7 +116,7 @@ class SuppressedConstructor extends Constructor { */ class NamespaceClass extends RefType { NamespaceClass() { - fromSource() and + this.fromSource() and // All members, apart from the default constructor and, if present, a "suppressed" constructor // must be static. There must be at least one member apart from the permitted constructors. forex(Member m | @@ -125,7 +127,9 @@ class NamespaceClass extends RefType { m.isStatic() ) and // Must only extend other namespace classes, or `Object`. - forall(RefType r | r = getASupertype() | r instanceof TypeObject or r instanceof NamespaceClass) + forall(RefType r | r = this.getASupertype() | + r instanceof TypeObject or r instanceof NamespaceClass + ) } } @@ -197,7 +201,7 @@ class DeadClass extends SourceClassOrInterface { /** * Identify all the "dead" roots of this dead class. */ - DeadRoot getADeadRoot() { result = getADeadRoot(getACallable()) } + DeadRoot getADeadRoot() { result = getADeadRoot(this.getACallable()) } /** * Holds if this dead class is only used within the class itself. @@ -206,8 +210,8 @@ class DeadClass extends SourceClassOrInterface { // Accessed externally if any callable in the class has a possible liveness cause outside the // class. Only one step is required. not exists(Callable c | - c = possibleLivenessCause(getACallable()) and - not c = getACallable() + c = possibleLivenessCause(this.getACallable()) and + not c = this.getACallable() ) } } @@ -229,7 +233,7 @@ abstract class WhitelistedLiveClass extends RefType { } */ class DeadMethod extends Callable { DeadMethod() { - fromSource() and + this.fromSource() and not isLive(this) and not this.(Constructor).isDefaultConstructor() and // Ignore `SuppressedConstructor`s in `NamespaceClass`es. There is no reason to use a suppressed diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadField.qll b/java/ql/lib/semmle/code/java/deadcode/DeadField.qll index dc6d1dc6dfd..c36b33f6296 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadField.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadField.qll @@ -10,7 +10,7 @@ import semmle.code.java.frameworks.jackson.JacksonSerializability * This defines the set of fields for which we will determine liveness. */ library class SourceField extends Field { - SourceField() { fromSource() } + SourceField() { this.fromSource() } } /** @@ -26,7 +26,7 @@ class DeadField extends SourceField { */ predicate isInDeadScope() { // `EnumConstant`s, and fields in dead classes, are reported in other queries. - getDeclaringType() instanceof DeadClass or + this.getDeclaringType() instanceof DeadClass or this instanceof EnumConstant } } @@ -37,7 +37,7 @@ class DeadField extends SourceField { */ class LiveField extends SourceField { LiveField() { - exists(FieldRead access | access = getAnAccess() | + exists(FieldRead access | access = this.getAnAccess() | isLive(access.getEnclosingCallable()) or exists(Annotation a | @@ -89,11 +89,11 @@ abstract class WhitelistedLiveField extends Field { } */ class SerialVersionUIDField extends ReflectivelyReadField { SerialVersionUIDField() { - hasName("serialVersionUID") and - isStatic() and - isFinal() and - getType().hasName("long") and - getDeclaringType().getASupertype*() instanceof TypeSerializable + this.hasName("serialVersionUID") and + this.isStatic() and + this.isFinal() and + this.getType().hasName("long") and + this.getDeclaringType().getASupertype*() instanceof TypeSerializable } } @@ -104,7 +104,7 @@ class SerialVersionUIDField extends ReflectivelyReadField { class LiveJaxbBoundField extends ReflectivelyReadField, JaxbBoundField { LiveJaxbBoundField() { // If the class is considered live, it must have at least one live constructor. - exists(Constructor c | c = getDeclaringType().getAConstructor() | isLive(c)) + exists(Constructor c | c = this.getDeclaringType().getAConstructor() | isLive(c)) } } @@ -114,11 +114,11 @@ class LiveJaxbBoundField extends ReflectivelyReadField, JaxbBoundField { */ class JUnitAnnotatedField extends ReflectivelyReadField { JUnitAnnotatedField() { - hasAnnotation("org.junit.experimental.theories", "DataPoint") or - hasAnnotation("org.junit.experimental.theories", "DataPoints") or - hasAnnotation("org.junit.runners", "Parameterized$Parameter") or - hasAnnotation("org.junit", "Rule") or - hasAnnotation("org.junit", "ClassRule") + this.hasAnnotation("org.junit.experimental.theories", "DataPoint") or + this.hasAnnotation("org.junit.experimental.theories", "DataPoints") or + this.hasAnnotation("org.junit.runners", "Parameterized$Parameter") or + this.hasAnnotation("org.junit", "Rule") or + this.hasAnnotation("org.junit", "ClassRule") } } @@ -164,8 +164,8 @@ class JPAReadField extends ReflectivelyReadField { ) | not this.hasAnnotation("javax.persistence", "Transient") and - not isStatic() and - not isFinal() + not this.isStatic() and + not this.isFinal() ) } } diff --git a/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll index aef97efd309..0a0dd2d0808 100644 --- a/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll @@ -102,7 +102,7 @@ library class JacksonReflectivelyConstructedClass extends ReflectivelyConstructe override Callable getALiveCallable() { // Constructors may be called by Jackson, if they are a no-arg, they have a suitable annotation, // or inherit a suitable annotation through a mixin. - result = getAConstructor() and + result = this.getAConstructor() and ( result.getNumberOfParameters() = 0 or result.getAnAnnotation() instanceof JacksonAnnotation or @@ -153,7 +153,7 @@ class DeserializedClass extends ReflectivelyConstructedClass { */ class NewInstanceCall extends EntryPoint, NewInstance { override Constructor getALiveCallable() { - result = getInferredConstructor() and + result = this.getInferredConstructor() and // The `newInstance(...)` call must be used in a live context. isLive(this.getEnclosingCallable()) } @@ -164,7 +164,7 @@ class NewInstanceCall extends EntryPoint, NewInstance { */ class ReflectiveMethodAccessEntryPoint extends EntryPoint, ReflectiveMethodAccess { override Method getALiveCallable() { - result = inferAccessedMethod() and + result = this.inferAccessedMethod() and // The `getMethod(...)` call must be used in a live context. isLive(this.getEnclosingCallable()) } @@ -210,8 +210,8 @@ class JaxbXmlEnum extends AnnotationEntryPoint { class JaxbXmlType extends AnnotationEntryPoint, JaxbType { override Callable getALiveCallable() { // Must have a live no-arg constructor for JAXB to perform marshal/unmarshal. - exists(Constructor c | c = getAConstructor() and c.getNumberOfParameters() = 0 | isLive(c)) and - result = getACallable() and + exists(Constructor c | c = this.getAConstructor() and c.getNumberOfParameters() = 0 | isLive(c)) and + result = this.getACallable() and ( // A bound getter or setter. result instanceof JaxbBoundGetterSetter @@ -262,7 +262,7 @@ class ManagedBeanImplEntryPoint extends EntryPoint, RegisteredManagedBeanImpl { // Find the method that will be called for each method on each managed bean that this class // implements. this.inherits(result) and - result.(Method).overrides(getAnImplementedManagedBean().getAMethod()) + result.(Method).overrides(this.getAnImplementedManagedBean().getAMethod()) } } @@ -377,7 +377,7 @@ class JavaxResourceAnnotatedMethod extends CallableEntryPointOnConstructedClass */ class JavaxManagedBeanReflectivelyConstructed extends ReflectivelyConstructedClass { JavaxManagedBeanReflectivelyConstructed() { - getAnAnnotation() instanceof JavaxManagedBeanAnnotation + this.getAnAnnotation() instanceof JavaxManagedBeanAnnotation } } @@ -413,13 +413,13 @@ class PersistencePropertyMethod extends CallableEntryPoint { */ class PersistenceCallbackMethod extends CallableEntryPoint { PersistenceCallbackMethod() { - getAnAnnotation() instanceof PrePersistAnnotation or - getAnAnnotation() instanceof PreRemoveAnnotation or - getAnAnnotation() instanceof PreUpdateAnnotation or - getAnAnnotation() instanceof PostPersistAnnotation or - getAnAnnotation() instanceof PostRemoveAnnotation or - getAnAnnotation() instanceof PostUpdateAnnotation or - getAnAnnotation() instanceof PostLoadAnnotation + this.getAnAnnotation() instanceof PrePersistAnnotation or + this.getAnAnnotation() instanceof PreRemoveAnnotation or + this.getAnAnnotation() instanceof PreUpdateAnnotation or + this.getAnAnnotation() instanceof PostPersistAnnotation or + this.getAnAnnotation() instanceof PostRemoveAnnotation or + this.getAnAnnotation() instanceof PostUpdateAnnotation or + this.getAnAnnotation() instanceof PostLoadAnnotation } } @@ -429,20 +429,20 @@ class PersistenceCallbackMethod extends CallableEntryPoint { */ class ArbitraryXMLEntryPoint extends ReflectivelyConstructedClass { ArbitraryXMLEntryPoint() { - fromSource() and + this.fromSource() and exists(XMLAttribute attribute | attribute.getName() = "className" or attribute.getName().matches("%ClassName") or attribute.getName() = "class" or attribute.getName().matches("%Class") | - attribute.getValue() = getQualifiedName() + attribute.getValue() = this.getQualifiedName() ) } override Callable getALiveCallable() { // Any constructor on these classes, as we don't know which may be called. - result = getAConstructor() + result = this.getAConstructor() } } diff --git a/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll index d9bc8a07997..2d8b28e4de9 100644 --- a/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll @@ -18,7 +18,7 @@ class TestMethodEntry extends CallableEntryPoint { or exists(AnnotationType a | a = this.getAnAnnotation().getType() | a.hasQualifiedName("org.junit.runners", "Parameterized$Parameters") and - getDeclaringType() instanceof ParameterizedJUnitTest + this.getDeclaringType() instanceof ParameterizedJUnitTest ) } } @@ -28,12 +28,12 @@ class TestMethodEntry extends CallableEntryPoint { */ class BeforeOrAfterEntry extends CallableEntryPoint { BeforeOrAfterEntry() { - getAnAnnotation() instanceof TestNGBeforeAnnotation or - getAnAnnotation() instanceof TestNGAfterAnnotation or - getAnAnnotation() instanceof BeforeAnnotation or - getAnAnnotation() instanceof BeforeClassAnnotation or - getAnAnnotation() instanceof AfterAnnotation or - getAnAnnotation() instanceof AfterClassAnnotation + this.getAnAnnotation() instanceof TestNGBeforeAnnotation or + this.getAnAnnotation() instanceof TestNGAfterAnnotation or + this.getAnAnnotation() instanceof BeforeAnnotation or + this.getAnAnnotation() instanceof BeforeClassAnnotation or + this.getAnAnnotation() instanceof AfterAnnotation or + this.getAnAnnotation() instanceof AfterClassAnnotation } } @@ -44,7 +44,7 @@ class JUnitTheories extends CallableEntryPoint { JUnitTheories() { exists(AnnotationType a | a = this.getAnAnnotation().getType() and - getDeclaringType() instanceof JUnitTheoryTest + this.getDeclaringType() instanceof JUnitTheoryTest | a.hasQualifiedName("org.junit.experimental.theories", "Theory") or a.hasQualifiedName("org.junit.experimental.theories", "DataPoint") or @@ -63,7 +63,7 @@ class JUnitDataPointField extends ReflectivelyReadField { a.hasQualifiedName("org.junit.experimental.theories", "DataPoint") or a.hasQualifiedName("org.junit.experimental.theories", "DataPoints") ) and - getDeclaringType() instanceof JUnitTheoryTest + this.getDeclaringType() instanceof JUnitTheoryTest ) } } @@ -152,7 +152,7 @@ class CucumberConstructedClass extends ReflectivelyConstructedClass { // Consider any constructor to be live - Cucumber calls a runtime-specified dependency // injection framework (possibly an in-built one) to construct these instances, so any // constructor could be called. - result = getAConstructor() + result = this.getAConstructor() } } diff --git a/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll index b31a04e11be..b9034600ca3 100644 --- a/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll @@ -29,7 +29,7 @@ class ServletConstructedClass extends ReflectivelyConstructedClass { */ class ServletListenerClass extends ReflectivelyConstructedClass { ServletListenerClass() { - getAnAncestor() instanceof ServletWebXMLListenerType and + this.getAnAncestor() instanceof ServletWebXMLListenerType and // If we have seen any `web.xml` files, this listener will be considered to be live only if it is // referred to as a listener-class in at least one. If no `web.xml` files are found, we assume // that XML extraction was not enabled, and therefore consider all listener classes as live. @@ -47,7 +47,7 @@ class ServletListenerClass extends ReflectivelyConstructedClass { */ class ServletFilterClass extends ReflectivelyConstructedClass { ServletFilterClass() { - getASupertype*().hasQualifiedName("javax.servlet", "Filter") and + this.getASupertype*().hasQualifiedName("javax.servlet", "Filter") and // If we have seen any `web.xml` files, this filter will be considered to be live only if it is // referred to as a filter-class in at least one. If no `web.xml` files are found, we assume // that XML extraction was not enabled, and therefore consider all filter classes as live. diff --git a/java/ql/lib/semmle/code/java/frameworks/Camel.qll b/java/ql/lib/semmle/code/java/frameworks/Camel.qll index cd845d0b33e..09bfa73d460 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Camel.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Camel.qll @@ -48,7 +48,7 @@ class CamelToBeanURI extends CamelToURI { /** * Gets the bean referenced by this URI. */ - SpringBean getRefBean() { result.getBeanIdentifier() = getBeanIdentifier() } + SpringBean getRefBean() { result.getBeanIdentifier() = this.getBeanIdentifier() } } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/Guice.qll b/java/ql/lib/semmle/code/java/frameworks/Guice.qll index f7154df4bd2..8dfb6398398 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Guice.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Guice.qll @@ -31,7 +31,7 @@ class GuiceProvider extends Interface { * A method that overrides the `get` method on the interface `com.google.inject.Provider`. */ Method getAnOverridingGetMethod() { - exists(Method m | m.getSourceDeclaration() = getGetMethod() | result.overrides*(m)) + exists(Method m | m.getSourceDeclaration() = this.getGetMethod() | result.overrides*(m)) } } diff --git a/java/ql/lib/semmle/code/java/frameworks/JAXB.qll b/java/ql/lib/semmle/code/java/frameworks/JAXB.qll index 2b4e3702623..bf5e33cb004 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JAXB.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JAXB.qll @@ -17,11 +17,11 @@ library class JAXBMarshalMethod extends Method { } class JaxbAnnotationType extends AnnotationType { - JaxbAnnotationType() { getPackage().getName() = "javax.xml.bind.annotation" } + JaxbAnnotationType() { this.getPackage().getName() = "javax.xml.bind.annotation" } } class JaxbAnnotated extends Annotatable { - JaxbAnnotated() { getAnAnnotation().getType() instanceof JaxbAnnotationType } + JaxbAnnotated() { this.getAnAnnotation().getType() instanceof JaxbAnnotationType } predicate hasJaxbAnnotation(string name) { hasJaxbAnnotation(this, name) } } @@ -62,8 +62,8 @@ class JaxbType extends Class { * Gets the `XmlAccessType` associated with this class. */ XmlAccessType getXmlAccessType() { - if exists(getDeclaredAccessType()) - then result = getDeclaredAccessType() + if exists(this.getDeclaredAccessType()) + then result = this.getDeclaredAccessType() else // Default access type, if not specified. result.isPublicMember() @@ -81,22 +81,22 @@ class XmlAccessType extends EnumConstant { /** * All public getter/setter pairs and public fields will be bound. */ - predicate isPublicMember() { getName() = "PUBLIC_MEMBER" } + predicate isPublicMember() { this.getName() = "PUBLIC_MEMBER" } /** * All non-static, non-transient fields will be bound. */ - predicate isField() { getName() = "FIELD" } + predicate isField() { this.getName() = "FIELD" } /** * All getter/setter pairs will be bound. */ - predicate isProperty() { getName() = "PROPERTY" } + predicate isProperty() { this.getName() = "PROPERTY" } /** * Nothing will be bound automatically. */ - predicate isNone() { getName() = "NONE" } + predicate isNone() { this.getName() = "NONE" } } /** @@ -105,10 +105,10 @@ class XmlAccessType extends EnumConstant { */ class JaxbMemberAnnotation extends JaxbAnnotationType { JaxbMemberAnnotation() { - hasName("XmlElement") or - hasName("XmlAttribute") or - hasName("XmlElementRefs") or - hasName("XmlElements") + this.hasName("XmlElement") or + this.hasName("XmlAttribute") or + this.hasName("XmlElementRefs") or + this.hasName("XmlElements") } } @@ -121,14 +121,14 @@ private predicate isTransient(Member m) { hasJaxbAnnotation(m, "XmlTransient") } class JaxbBoundField extends Field { JaxbBoundField() { // Fields cannot be static, because JAXB creates instances. - not isStatic() and + not this.isStatic() and // Fields cannot be final, because JAXB instantiates the object, then sets the properties. - not isFinal() and + not this.isFinal() and // No transient fields are ever bound. not isTransient(this) and ( // Explicitly annotated to be bound. - exists(getAnAnnotation().getType().(JaxbMemberAnnotation)) + exists(this.getAnAnnotation().getType().(JaxbMemberAnnotation)) or // Within a JAXB type which has an `XmlAcessType` that binds this field. exists(JaxbType type | this.getDeclaringType() = type | @@ -136,7 +136,7 @@ class JaxbBoundField extends Field { type.getXmlAccessType().isField() or // Only public fields are automatically bound in this access type. - type.getXmlAccessType().isPublicMember() and isPublic() + type.getXmlAccessType().isPublicMember() and this.isPublic() ) ) } @@ -157,7 +157,7 @@ library class GetterOrSetterMethod extends Method { * Holds if this method has a "pair"ed method, e.g. whether there is an equivalent getter if this * is a setter, and vice versa. */ - predicate isProperty() { exists(getPair()) } + predicate isProperty() { exists(this.getPair()) } /** * Gets the "pair" method, if one exists; that is, the getter if this is a setter, and vice versa. @@ -183,16 +183,16 @@ class JaxbBoundGetterSetter extends GetterOrSetterMethod { this.getField() instanceof JaxbBoundField or // An annotation on this method or the pair that indicate that it is a valid setter/getter. - getThisOrPair().getAnAnnotation().getType() instanceof JaxbMemberAnnotation + this.getThisOrPair().getAnAnnotation().getType() instanceof JaxbMemberAnnotation or // Within a JAXB type which has an `XmlAcessType` that binds this method. exists(JaxbType c | this.getDeclaringType() = c | // If this is a "property" - both a setter and getter present for the XML element or attribute // - the `XmlAccessType` of the declaring type may cause this property to be bound. - isProperty() and + this.isProperty() and ( // In the `PUBLIC_MEMBER` case all public properties are considered bound. - c.getXmlAccessType().isPublicMember() and isPublic() + c.getXmlAccessType().isPublicMember() and this.isPublic() or // In "property" all properties are considered bound. c.getXmlAccessType().isProperty() diff --git a/java/ql/lib/semmle/code/java/frameworks/JUnitAnnotations.qll b/java/ql/lib/semmle/code/java/frameworks/JUnitAnnotations.qll index 18afe9403e2..8716f7d625c 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JUnitAnnotations.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JUnitAnnotations.qll @@ -64,5 +64,5 @@ class RunWithAnnotation extends Annotation { /** * Gets the runner that will be used. */ - Type getRunner() { result = getValue("value").(TypeLiteral).getReferencedType() } + Type getRunner() { result = this.getValue("value").(TypeLiteral).getReferencedType() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Jackson.qll b/java/ql/lib/semmle/code/java/frameworks/Jackson.qll index 5612311c730..f93f1afccc8 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Jackson.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Jackson.qll @@ -7,31 +7,31 @@ private import semmle.code.java.dataflow.DataFlow private class ObjectMapper extends RefType { ObjectMapper() { - getASupertype*().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectMapper") + this.getASupertype*().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectMapper") } } /** A builder for building Jackson's `JsonMapper`. */ class MapperBuilder extends RefType { MapperBuilder() { - hasQualifiedName("com.fasterxml.jackson.databind.cfg", "MapperBuilder<JsonMapper,Builder>") + this.hasQualifiedName("com.fasterxml.jackson.databind.cfg", "MapperBuilder<JsonMapper,Builder>") } } private class JsonFactory extends RefType { - JsonFactory() { hasQualifiedName("com.fasterxml.jackson.core", "JsonFactory") } + JsonFactory() { this.hasQualifiedName("com.fasterxml.jackson.core", "JsonFactory") } } private class JsonParser extends RefType { - JsonParser() { hasQualifiedName("com.fasterxml.jackson.core", "JsonParser") } + JsonParser() { this.hasQualifiedName("com.fasterxml.jackson.core", "JsonParser") } } /** A type descriptor in Jackson libraries. For example, `java.lang.Class`. */ class JacksonTypeDescriptorType extends RefType { JacksonTypeDescriptorType() { this instanceof TypeClass or - hasQualifiedName("com.fasterxml.jackson.databind", "JavaType") or - hasQualifiedName("com.fasterxml.jackson.core.type", "TypeReference") + this.hasQualifiedName("com.fasterxml.jackson.databind", "JavaType") or + this.hasQualifiedName("com.fasterxml.jackson.core.type", "TypeReference") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Jndi.qll b/java/ql/lib/semmle/code/java/frameworks/Jndi.qll index fce87dcddab..9294c0c97c7 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Jndi.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Jndi.qll @@ -41,39 +41,39 @@ class TypeLdapName extends Class { /** A method with the name `addAll` declared in `javax.naming.ldap.LdapName`. */ class MethodLdapNameAddAll extends Method { MethodLdapNameAddAll() { - getDeclaringType() instanceof TypeLdapName and - hasName("addAll") + this.getDeclaringType() instanceof TypeLdapName and + this.hasName("addAll") } } /** A method with the name `clone` declared in `javax.naming.ldap.LdapName`. */ class MethodLdapNameClone extends Method { MethodLdapNameClone() { - getDeclaringType() instanceof TypeLdapName and - hasName("clone") + this.getDeclaringType() instanceof TypeLdapName and + this.hasName("clone") } } /** A method with the name `getAll` declared in `javax.naming.ldap.LdapName`. */ class MethodLdapNameGetAll extends Method { MethodLdapNameGetAll() { - getDeclaringType() instanceof TypeLdapName and - hasName("getAll") + this.getDeclaringType() instanceof TypeLdapName and + this.hasName("getAll") } } /** A method with the name `getRdns` declared in `javax.naming.ldap.LdapName`. */ class MethodLdapNameGetRdns extends Method { MethodLdapNameGetRdns() { - getDeclaringType() instanceof TypeLdapName and - hasName("getRdns") + this.getDeclaringType() instanceof TypeLdapName and + this.hasName("getRdns") } } /** A method with the name `toString` declared in `javax.naming.ldap.LdapName`. */ class MethodLdapNameToString extends Method { MethodLdapNameToString() { - getDeclaringType() instanceof TypeLdapName and - hasName("toString") + this.getDeclaringType() instanceof TypeLdapName and + this.hasName("toString") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Kryo.qll b/java/ql/lib/semmle/code/java/frameworks/Kryo.qll index 317148d56b5..057b10de632 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Kryo.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Kryo.qll @@ -11,8 +11,8 @@ private import semmle.code.java.dataflow.FlowSteps */ class Kryo extends RefType { Kryo() { - hasQualifiedName("com.esotericsoftware.kryo", "Kryo") or - hasQualifiedName("com.esotericsoftware.kryo5", "Kryo") + this.hasQualifiedName("com.esotericsoftware.kryo", "Kryo") or + this.hasQualifiedName("com.esotericsoftware.kryo5", "Kryo") } } @@ -21,8 +21,8 @@ class Kryo extends RefType { */ class KryoInput extends RefType { KryoInput() { - hasQualifiedName("com.esotericsoftware.kryo.io", "Input") or - hasQualifiedName("com.esotericsoftware.kryo5.io", "Input") + this.hasQualifiedName("com.esotericsoftware.kryo.io", "Input") or + this.hasQualifiedName("com.esotericsoftware.kryo5.io", "Input") } } @@ -31,8 +31,8 @@ class KryoInput extends RefType { */ class KryoPool extends RefType { KryoPool() { - hasQualifiedName("com.esotericsoftware.kryo.pool", "KryoPool") or - hasQualifiedName("com.esotericsoftware.kryo5.pool", "KryoPool") + this.hasQualifiedName("com.esotericsoftware.kryo.pool", "KryoPool") or + this.hasQualifiedName("com.esotericsoftware.kryo5.pool", "KryoPool") } } @@ -41,8 +41,8 @@ class KryoPool extends RefType { */ class KryoPoolBuilder extends RefType { KryoPoolBuilder() { - hasQualifiedName("com.esotericsoftware.kryo.pool", "KryoPool$Builder") or - hasQualifiedName("com.esotericsoftware.kryo5.pool", "KryoPool$Builder") + this.hasQualifiedName("com.esotericsoftware.kryo.pool", "KryoPool$Builder") or + this.hasQualifiedName("com.esotericsoftware.kryo5.pool", "KryoPool$Builder") } } @@ -51,10 +51,10 @@ class KryoPoolBuilder extends RefType { */ class KryoPoolBuilderMethod extends Method { KryoPoolBuilderMethod() { - getDeclaringType() instanceof KryoPoolBuilder and + this.getDeclaringType() instanceof KryoPoolBuilder and ( - getReturnType() instanceof KryoPoolBuilder or - getReturnType() instanceof KryoPool + this.getReturnType() instanceof KryoPoolBuilder or + this.getReturnType() instanceof KryoPool ) } } @@ -92,7 +92,7 @@ class KryoEnableWhiteListing extends MethodAccess { */ class KryoPoolRunMethod extends Method { KryoPoolRunMethod() { - getDeclaringType() instanceof KryoPool and - hasName("run") + this.getDeclaringType() instanceof KryoPool and + this.hasName("run") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Mockito.qll b/java/ql/lib/semmle/code/java/frameworks/Mockito.qll index 1745d3a9f5b..e42da4db357 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Mockito.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Mockito.qll @@ -11,8 +11,8 @@ import java */ class MockitoVerifyMethod extends Method { MockitoVerifyMethod() { - getDeclaringType().getPackage().getName().matches("org.mockito%") and - hasName("verify") + this.getDeclaringType().getPackage().getName().matches("org.mockito%") and + this.hasName("verify") } } @@ -21,7 +21,7 @@ class MockitoVerifyMethod extends Method { */ class MockitoVerifiedMethodAccess extends MethodAccess { MockitoVerifiedMethodAccess() { - getQualifier().(MethodAccess).getMethod() instanceof MockitoVerifyMethod + this.getQualifier().(MethodAccess).getMethod() instanceof MockitoVerifyMethod } } @@ -41,8 +41,8 @@ class MockitoMockableType extends ClassOrInterface { */ class MockitoInitMocks extends Method { MockitoInitMocks() { - getDeclaringType().hasQualifiedName("org.mockito", "MockitoAnnotations") and - hasName("initMocks") + this.getDeclaringType().hasQualifiedName("org.mockito", "MockitoAnnotations") and + this.hasName("initMocks") } } @@ -61,10 +61,10 @@ class MockitoInitedTest extends Class { or // Call to `MockitoAnnotations.initMocks()`, either by the constructor or by a `@Before` method. exists(MockitoInitMocks initMocks | - getAConstructor().calls*(initMocks) + this.getAConstructor().calls*(initMocks) or exists(Method m | - m = getAnAncestor().getAMethod() and + m = this.getAnAncestor().getAMethod() and ( m.hasAnnotation("org.junit", "Before") or m.hasAnnotation("org.testng.annotations", "BeforeMethod") @@ -85,8 +85,8 @@ class MockitoInitedTest extends Class { */ class MockitoAnnotation extends Annotation { MockitoAnnotation() { - getType().getPackage().getName().matches("org.mockito") or - getType().getPackage().getName().matches("org.mockito.%") + this.getType().getPackage().getName().matches("org.mockito") or + this.getType().getPackage().getName().matches("org.mockito.%") } } @@ -95,11 +95,11 @@ class MockitoAnnotation extends Annotation { */ class MockitoExclusiveAnnotation extends MockitoAnnotation { MockitoExclusiveAnnotation() { - getType().hasQualifiedName("org.mockito", "Mock") or - getType().hasQualifiedName("org.mockito", "MockitoAnnotations$Mock") or - getType().hasQualifiedName("org.mockito", "InjectMocks") or - getType().hasQualifiedName("org.mockito", "Spy") or - getType().hasQualifiedName("org.mockito", "Captor") + this.getType().hasQualifiedName("org.mockito", "Mock") or + this.getType().hasQualifiedName("org.mockito", "MockitoAnnotations$Mock") or + this.getType().hasQualifiedName("org.mockito", "InjectMocks") or + this.getType().hasQualifiedName("org.mockito", "Spy") or + this.getType().hasQualifiedName("org.mockito", "Captor") } } @@ -107,16 +107,16 @@ class MockitoExclusiveAnnotation extends MockitoAnnotation { * A field which has a Mockito annotation. */ class MockitoAnnotatedField extends Field { - MockitoAnnotatedField() { getAnAnnotation() instanceof MockitoAnnotation } + MockitoAnnotatedField() { this.getAnAnnotation() instanceof MockitoAnnotation } /** * Holds if this field will be processed by Mockito. */ predicate isValid() { // Mockito annotations are never parsed if the test isn't properly initialized. - getDeclaringType() instanceof MockitoInitedTest and + this.getDeclaringType() instanceof MockitoInitedTest and // There should only be one "exclusive" mockito annotation per field. - count(getAnAnnotation().(MockitoExclusiveAnnotation)) = 1 + count(this.getAnAnnotation().(MockitoExclusiveAnnotation)) = 1 } } @@ -125,16 +125,16 @@ class MockitoAnnotatedField extends Field { */ class MockitoMockedField extends MockitoAnnotatedField { MockitoMockedField() { - hasAnnotation("org.mockito", "Mock") + this.hasAnnotation("org.mockito", "Mock") or // Deprecated style. - hasAnnotation("org.mockito", "MockitoAnnotations$Mock") + this.hasAnnotation("org.mockito", "MockitoAnnotations$Mock") } override predicate isValid() { super.isValid() and // The type must also be mockable, otherwise it will not be initialized. - getType() instanceof MockitoMockableType + this.getType() instanceof MockitoMockableType } /** @@ -142,12 +142,13 @@ class MockitoMockedField extends MockitoAnnotatedField { */ predicate isReferencedByInjection() { exists(MockitoInjectedField injectedField | - injectedField.getDeclaringType() = getDeclaringType() + injectedField.getDeclaringType() = this.getDeclaringType() | // A `@Mock` is injected if it is used in one of the invoked callables (constructor or // setter), or injected directly onto a field. - getType().(RefType).getAnAncestor() = injectedField.getAnInvokedCallable().getAParamType() or - getType().(RefType).getAnAncestor() = injectedField.getASetField().getType() + this.getType().(RefType).getAnAncestor() = + injectedField.getAnInvokedCallable().getAParamType() or + this.getType().(RefType).getAnAncestor() = injectedField.getASetField().getType() ) } } @@ -156,25 +157,25 @@ class MockitoMockedField extends MockitoAnnotatedField { * A field annotated with `@InjectMocks`. */ class MockitoInjectedField extends MockitoAnnotatedField { - MockitoInjectedField() { hasAnnotation("org.mockito", "InjectMocks") } + MockitoInjectedField() { this.hasAnnotation("org.mockito", "InjectMocks") } override predicate isValid() { super.isValid() and ( // If we need to initialize the field, it is only valid if the type is a `Class` that is not // local, is static if it is a nested class, and is not abstract. - exists(getInitializer()) + exists(this.getInitializer()) or - exists(Class c | c = getType() | + exists(Class c | c = this.getType() | not c.isLocal() and - (getType() instanceof NestedClass implies c.(NestedClass).isStatic()) and + (this.getType() instanceof NestedClass implies c.(NestedClass).isStatic()) and not c.isAbstract() ) ) and ( // If neither of these is true, then mockito will fail to initialize this field. - usingConstructorInjection() or - usingPropertyInjection() + this.usingConstructorInjection() or + this.usingPropertyInjection() ) } @@ -184,7 +185,8 @@ class MockitoInjectedField extends MockitoAnnotatedField { * Note: this does not include the no-arg constructor. */ predicate usingConstructorInjection() { - not exists(getInitializer()) and exists(getMockInjectedClass().getAMostMockableConstructor()) + not exists(this.getInitializer()) and + exists(this.getMockInjectedClass().getAMostMockableConstructor()) } /** @@ -194,10 +196,10 @@ class MockitoInjectedField extends MockitoAnnotatedField { * constructor, in addition to any property. */ predicate usingPropertyInjection() { - not usingConstructorInjection() and + not this.usingConstructorInjection() and ( - exists(getInitializer()) or - exists(getMockInjectedClass().getNoArgsConstructor()) + exists(this.getInitializer()) or + exists(this.getMockInjectedClass().getNoArgsConstructor()) ) } @@ -212,18 +214,18 @@ class MockitoInjectedField extends MockitoAnnotatedField { Callable getAnInvokedCallable() { exists(MockitoMockInjectedClass mockInjectedClass | // This is the type we are constructing/injecting. - mockInjectedClass = getType() + mockInjectedClass = this.getType() | - if usingConstructorInjection() + if this.usingConstructorInjection() then // If there is no initializer for this field, and there is a most mockable constructor, // then we are doing a parameterized injection of mocks into a most mockable constructor. result = mockInjectedClass.getAMostMockableConstructor() else - if usingPropertyInjection() + if this.usingPropertyInjection() then // We will call the no-arg constructor if the field wasn't initialized. - not exists(getInitializer()) and + not exists(this.getInitializer()) and result = mockInjectedClass.getNoArgsConstructor() or // Perform property injection into setter fields, but only where there exists a mock @@ -249,9 +251,9 @@ class MockitoInjectedField extends MockitoAnnotatedField { * Field injection only occurs if property injection and not constructor injection is used. */ Field getASetField() { - if usingPropertyInjection() + if this.usingPropertyInjection() then - result = getMockInjectedClass().getASetField() and + result = this.getMockInjectedClass().getASetField() and exists(MockitoMockedField mockedField | mockedField.getDeclaringType() = this.getDeclaringType() and mockedField.isValid() @@ -268,15 +270,15 @@ class MockitoInjectedField extends MockitoAnnotatedField { * A field annotated with the Mockito `@Spy` annotation. */ class MockitoSpiedField extends MockitoAnnotatedField { - MockitoSpiedField() { hasAnnotation("org.mockito", "Spy") } + MockitoSpiedField() { this.hasAnnotation("org.mockito", "Spy") } override predicate isValid() { super.isValid() and ( - exists(getInitializer()) + exists(this.getInitializer()) or exists(Constructor c | - c = getType().(RefType).getAConstructor() and c.getNumberOfParameters() = 0 + c = this.getType().(RefType).getAConstructor() and c.getNumberOfParameters() = 0 ) ) } @@ -284,7 +286,7 @@ class MockitoSpiedField extends MockitoAnnotatedField { /** * Holds if construction ever occurs. */ - predicate isConstructed() { not exists(getInitializer()) } + predicate isConstructed() { not exists(this.getInitializer()) } } private int mockableParameterCount(Constructor constructor) { @@ -312,8 +314,8 @@ library class MockitoMockInjectedClass extends Class { * Mockito will call only one of them, but which one is dependent on the JVM... */ Constructor getAMostMockableConstructor() { - result = getAConstructor() and - mockableParameterCount(result) = max(mockableParameterCount(getAConstructor())) and + result = this.getAConstructor() and + mockableParameterCount(result) = max(mockableParameterCount(this.getAConstructor())) and result.getNumberOfParameters() > 0 } @@ -331,7 +333,7 @@ library class MockitoMockInjectedClass extends Class { * it sets. */ Method getASetterMethod() { - result = getAMethod() and + result = this.getAMethod() and exists(MockitoSettableField settableField | result = settableField.getSetterMethod()) } @@ -342,7 +344,7 @@ library class MockitoMockInjectedClass extends Class { * setter method. */ MockitoSettableField getASetField() { - result = getAField() and + result = this.getAField() and not exists(result.getSetterMethod()) } } @@ -353,8 +355,8 @@ library class MockitoMockInjectedClass extends Class { */ class MockitoSettableField extends Field { MockitoSettableField() { - not isFinal() and - not isStatic() and + not this.isFinal() and + not this.isStatic() and exists(MockitoMockInjectedClass injectedClass | injectedClass = this.getDeclaringType()) } diff --git a/java/ql/lib/semmle/code/java/frameworks/Networking.qll b/java/ql/lib/semmle/code/java/frameworks/Networking.qll index 10a1999b8b8..6e5ad743d44 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Networking.qll @@ -6,39 +6,39 @@ import semmle.code.java.Type /** The type `java.net.URLConnection`. */ class TypeUrlConnection extends RefType { - TypeUrlConnection() { hasQualifiedName("java.net", "URLConnection") } + TypeUrlConnection() { this.hasQualifiedName("java.net", "URLConnection") } } /** The type `java.net.Socket`. */ class TypeSocket extends RefType { - TypeSocket() { hasQualifiedName("java.net", "Socket") } + TypeSocket() { this.hasQualifiedName("java.net", "Socket") } } /** The type `java.net.URL`. */ class TypeUrl extends RefType { - TypeUrl() { hasQualifiedName("java.net", "URL") } + TypeUrl() { this.hasQualifiedName("java.net", "URL") } } /** The type `java.net.URI`. */ class TypeUri extends RefType { - TypeUri() { hasQualifiedName("java.net", "URI") } + TypeUri() { this.hasQualifiedName("java.net", "URI") } } /** The method `java.net.URLConnection::getInputStream`. */ class URLConnectionGetInputStreamMethod extends Method { URLConnectionGetInputStreamMethod() { - getDeclaringType() instanceof TypeUrlConnection and - hasName("getInputStream") and - hasNoParameters() + this.getDeclaringType() instanceof TypeUrlConnection and + this.hasName("getInputStream") and + this.hasNoParameters() } } /** The method `java.net.Socket::getInputStream`. */ class SocketGetInputStreamMethod extends Method { SocketGetInputStreamMethod() { - getDeclaringType() instanceof TypeSocket and - hasName("getInputStream") and - hasNoParameters() + this.getDeclaringType() instanceof TypeSocket and + this.hasName("getInputStream") and + this.hasNoParameters() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Protobuf.qll b/java/ql/lib/semmle/code/java/frameworks/Protobuf.qll index 7382294f6f9..414517924b4 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Protobuf.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Protobuf.qll @@ -30,7 +30,7 @@ class ProtobufMessageLite extends Interface { * Gets a static method named `parseFrom` (or similar) declared on a subtype of the `MessageLite` interface. */ Method getAParseFromMethod() { - result = getASubtype+().getAMethod() and + result = this.getASubtype+().getAMethod() and result.getName().matches("parse%From") and result.isStatic() } diff --git a/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll b/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll index db5687f916a..31532dcb02d 100644 --- a/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll +++ b/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll @@ -37,14 +37,14 @@ private class SafeYamlConstructionFlowConfig extends DataFlow2::Configuration { src.asExpr() instanceof SafeSnakeYamlConstruction } - override predicate isSink(DataFlow::Node sink) { sink = yamlClassInstanceExprArgument(_) } + override predicate isSink(DataFlow::Node sink) { sink = this.yamlClassInstanceExprArgument(_) } private DataFlow::ExprNode yamlClassInstanceExprArgument(ClassInstanceExpr cie) { cie.getConstructedType() instanceof Yaml and result.getExpr() = cie.getArgument(0) } - ClassInstanceExpr getSafeYaml() { hasFlowTo(yamlClassInstanceExprArgument(result)) } + ClassInstanceExpr getSafeYaml() { this.hasFlowTo(this.yamlClassInstanceExprArgument(result)) } } /** @@ -70,13 +70,13 @@ private class SafeYamlFlowConfig extends DataFlow3::Configuration { override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeYaml } - override predicate isSink(DataFlow::Node sink) { sink = yamlParseQualifier(_) } + override predicate isSink(DataFlow::Node sink) { sink = this.yamlParseQualifier(_) } private DataFlow::ExprNode yamlParseQualifier(SnakeYamlParse syp) { result.getExpr() = syp.getQualifier() } - SnakeYamlParse getASafeSnakeYamlParse() { hasFlowTo(yamlParseQualifier(result)) } + SnakeYamlParse getASafeSnakeYamlParse() { this.hasFlowTo(this.yamlParseQualifier(result)) } } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/SpringLdap.qll b/java/ql/lib/semmle/code/java/frameworks/SpringLdap.qll index 68124273f40..2db8435c22c 100644 --- a/java/ql/lib/semmle/code/java/frameworks/SpringLdap.qll +++ b/java/ql/lib/semmle/code/java/frameworks/SpringLdap.qll @@ -77,8 +77,8 @@ class TypeLdapOperations extends Interface { */ class MethodSpringLdapTemplateAuthenticate extends Method { MethodSpringLdapTemplateAuthenticate() { - getDeclaringType() instanceof TypeSpringLdapTemplate and - hasName("authenticate") + this.getDeclaringType() instanceof TypeSpringLdapTemplate and + this.hasName("authenticate") } } @@ -88,8 +88,8 @@ class MethodSpringLdapTemplateAuthenticate extends Method { */ class MethodSpringLdapTemplateFind extends Method { MethodSpringLdapTemplateFind() { - getDeclaringType() instanceof TypeSpringLdapTemplate and - hasName("find") + this.getDeclaringType() instanceof TypeSpringLdapTemplate and + this.hasName("find") } } @@ -99,8 +99,8 @@ class MethodSpringLdapTemplateFind extends Method { */ class MethodSpringLdapTemplateFindOne extends Method { MethodSpringLdapTemplateFindOne() { - getDeclaringType() instanceof TypeSpringLdapTemplate and - hasName("findOne") + this.getDeclaringType() instanceof TypeSpringLdapTemplate and + this.hasName("findOne") } } @@ -110,8 +110,8 @@ class MethodSpringLdapTemplateFindOne extends Method { */ class MethodSpringLdapTemplateSearch extends Method { MethodSpringLdapTemplateSearch() { - getDeclaringType() instanceof TypeSpringLdapTemplate and - hasName("search") + this.getDeclaringType() instanceof TypeSpringLdapTemplate and + this.hasName("search") } } @@ -121,8 +121,8 @@ class MethodSpringLdapTemplateSearch extends Method { */ class MethodSpringLdapTemplateSearchForContext extends Method { MethodSpringLdapTemplateSearchForContext() { - getDeclaringType() instanceof TypeSpringLdapTemplate and - hasName("searchForContext") + this.getDeclaringType() instanceof TypeSpringLdapTemplate and + this.hasName("searchForContext") } } @@ -132,8 +132,8 @@ class MethodSpringLdapTemplateSearchForContext extends Method { */ class MethodSpringLdapTemplateSearchForObject extends Method { MethodSpringLdapTemplateSearchForObject() { - getDeclaringType() instanceof TypeSpringLdapTemplate and - hasName("searchForObject") + this.getDeclaringType() instanceof TypeSpringLdapTemplate and + this.hasName("searchForObject") } } @@ -143,8 +143,8 @@ class MethodSpringLdapTemplateSearchForObject extends Method { */ class MethodSpringLdapQueryBuilderFilter extends Method { MethodSpringLdapQueryBuilderFilter() { - getDeclaringType() instanceof TypeSpringLdapQueryBuilder and - hasName("filter") + this.getDeclaringType() instanceof TypeSpringLdapQueryBuilder and + this.hasName("filter") } } @@ -154,8 +154,8 @@ class MethodSpringLdapQueryBuilderFilter extends Method { */ class MethodSpringLdapQueryBuilderBase extends Method { MethodSpringLdapQueryBuilderBase() { - getDeclaringType() instanceof TypeSpringLdapQueryBuilder and - hasName("base") + this.getDeclaringType() instanceof TypeSpringLdapQueryBuilder and + this.hasName("base") } } @@ -165,8 +165,8 @@ class MethodSpringLdapQueryBuilderBase extends Method { */ class MethodSpringLdapNameBuilderNewInstance extends Method { MethodSpringLdapNameBuilderNewInstance() { - getDeclaringType() instanceof TypeSpringLdapNameBuilder and - hasName("newInstance") + this.getDeclaringType() instanceof TypeSpringLdapNameBuilder and + this.hasName("newInstance") } } @@ -176,8 +176,8 @@ class MethodSpringLdapNameBuilderNewInstance extends Method { */ class MethodSpringLdapNameBuilderAdd extends Method { MethodSpringLdapNameBuilderAdd() { - getDeclaringType() instanceof TypeSpringLdapNameBuilder and - hasName("add") + this.getDeclaringType() instanceof TypeSpringLdapNameBuilder and + this.hasName("add") } } @@ -187,8 +187,8 @@ class MethodSpringLdapNameBuilderAdd extends Method { */ class MethodSpringLdapNameBuilderBuild extends Method { MethodSpringLdapNameBuilderBuild() { - getDeclaringType() instanceof TypeSpringLdapNameBuilder and - hasName("build") + this.getDeclaringType() instanceof TypeSpringLdapNameBuilder and + this.hasName("build") } } @@ -198,7 +198,7 @@ class MethodSpringLdapNameBuilderBuild extends Method { */ class MethodSpringLdapUtilsNewLdapName extends Method { MethodSpringLdapUtilsNewLdapName() { - getDeclaringType() instanceof TypeSpringLdapUtils and - hasName("newLdapName") + this.getDeclaringType() instanceof TypeSpringLdapUtils and + this.hasName("newLdapName") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Thrift.qll b/java/ql/lib/semmle/code/java/frameworks/Thrift.qll index 60ca7ee7b4d..9b2e2fcd5a2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Thrift.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Thrift.qll @@ -27,7 +27,7 @@ class ThriftIface extends Interface { Method getAnImplementingMethod() { result.getDeclaringType().(Class).getASupertype+() = this and - result.overrides(getAMethod()) and + result.overrides(this.getAMethod()) and not result.getFile() = this.getFile() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/UnboundId.qll b/java/ql/lib/semmle/code/java/frameworks/UnboundId.qll index 8eee0f14ce5..88156da0264 100644 --- a/java/ql/lib/semmle/code/java/frameworks/UnboundId.qll +++ b/java/ql/lib/semmle/code/java/frameworks/UnboundId.qll @@ -35,79 +35,79 @@ class TypeUnboundIdLDAPConnection extends Class { /** A method with the name `setBaseDN` declared in `com.unboundid.ldap.sdk.SearchRequest`. */ class MethodUnboundIdSearchRequestSetBaseDN extends Method { MethodUnboundIdSearchRequestSetBaseDN() { - getDeclaringType() instanceof TypeUnboundIdSearchRequest and - hasName("setBaseDN") + this.getDeclaringType() instanceof TypeUnboundIdSearchRequest and + this.hasName("setBaseDN") } } /** A method with the name `setFilter` declared in `com.unboundid.ldap.sdk.SearchRequest`. */ class MethodUnboundIdSearchRequestSetFilter extends Method { MethodUnboundIdSearchRequestSetFilter() { - getDeclaringType() instanceof TypeUnboundIdSearchRequest and - hasName("setFilter") + this.getDeclaringType() instanceof TypeUnboundIdSearchRequest and + this.hasName("setFilter") } } /** A method with the name `create` declared in `com.unboundid.ldap.sdk.Filter`. */ class MethodUnboundIdFilterCreate extends Method { MethodUnboundIdFilterCreate() { - getDeclaringType() instanceof TypeUnboundIdLdapFilter and - hasName("create") + this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and + this.hasName("create") } } /** A method with the name `createANDFilter` declared in `com.unboundid.ldap.sdk.Filter`. */ class MethodUnboundIdFilterCreateANDFilter extends Method { MethodUnboundIdFilterCreateANDFilter() { - getDeclaringType() instanceof TypeUnboundIdLdapFilter and - hasName("createANDFilter") + this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and + this.hasName("createANDFilter") } } /** A method with the name `createORFilter` declared in `com.unboundid.ldap.sdk.Filter`. */ class MethodUnboundIdFilterCreateORFilter extends Method { MethodUnboundIdFilterCreateORFilter() { - getDeclaringType() instanceof TypeUnboundIdLdapFilter and - hasName("createORFilter") + this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and + this.hasName("createORFilter") } } /** A method with the name `createNOTFilter` declared in `com.unboundid.ldap.sdk.Filter`. */ class MethodUnboundIdFilterCreateNOTFilter extends Method { MethodUnboundIdFilterCreateNOTFilter() { - getDeclaringType() instanceof TypeUnboundIdLdapFilter and - hasName("createNOTFilter") + this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and + this.hasName("createNOTFilter") } } /** A method with the name `simplifyFilter` declared in `com.unboundid.ldap.sdk.Filter`. */ class MethodUnboundIdFilterSimplifyFilter extends Method { MethodUnboundIdFilterSimplifyFilter() { - getDeclaringType() instanceof TypeUnboundIdLdapFilter and - hasName("simplifyFilter") + this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and + this.hasName("simplifyFilter") } } /** A method with the name `search` declared in `com.unboundid.ldap.sdk.LDAPConnection`. */ class MethodUnboundIdLDAPConnectionSearch extends Method { MethodUnboundIdLDAPConnectionSearch() { - getDeclaringType() instanceof TypeUnboundIdLDAPConnection and - hasName("search") + this.getDeclaringType() instanceof TypeUnboundIdLDAPConnection and + this.hasName("search") } } /** A method with the name `asyncSearch` declared in `com.unboundid.ldap.sdk.LDAPConnection`. */ class MethodUnboundIdLDAPConnectionAsyncSearch extends Method { MethodUnboundIdLDAPConnectionAsyncSearch() { - getDeclaringType() instanceof TypeUnboundIdLDAPConnection and - hasName("asyncSearch") + this.getDeclaringType() instanceof TypeUnboundIdLDAPConnection and + this.hasName("asyncSearch") } } /** A method with the name `searchForEntry` declared in `com.unboundid.ldap.sdk.LDAPConnection`. */ class MethodUnboundIdLDAPConnectionSearchForEntry extends Method { MethodUnboundIdLDAPConnectionSearchForEntry() { - getDeclaringType() instanceof TypeUnboundIdLDAPConnection and - hasName("searchForEntry") + this.getDeclaringType() instanceof TypeUnboundIdLDAPConnection and + this.hasName("searchForEntry") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index a599f7befc9..c019dc11bd8 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -37,10 +37,12 @@ class AndroidComponent extends Class { } /** Holds if this Android component is configured as `exported` in an `AndroidManifest.xml` file. */ - predicate isExported() { getAndroidComponentXmlElement().isExported() } + predicate isExported() { this.getAndroidComponentXmlElement().isExported() } /** Holds if this Android component has an intent filter configured in an `AndroidManifest.xml` file. */ - predicate hasIntentFilter() { exists(getAndroidComponentXmlElement().getAnIntentFilterElement()) } + predicate hasIntentFilter() { + exists(this.getAndroidComponentXmlElement().getAnIntentFilterElement()) + } } /** @@ -53,10 +55,10 @@ class ExportableAndroidComponent extends AndroidComponent { * `AndroidManifest.xml` file. */ override predicate isExported() { - getAndroidComponentXmlElement().isExported() + this.getAndroidComponentXmlElement().isExported() or - hasIntentFilter() and - not getAndroidComponentXmlElement().isNotExported() + this.hasIntentFilter() and + not this.getAndroidComponentXmlElement().isNotExported() } } @@ -88,7 +90,7 @@ class AndroidContentProvider extends ExportableAndroidComponent { * in an `AndroidManifest.xml` file. */ predicate requiresPermissions() { - getAndroidComponentXmlElement().(AndroidProviderXmlElement).requiresPermissions() + this.getAndroidComponentXmlElement().(AndroidProviderXmlElement).requiresPermissions() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 3798d91d99a..296d6b39b2b 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -7,35 +7,37 @@ import semmle.code.java.dataflow.ExternalFlow * The class `android.content.Intent`. */ class TypeIntent extends Class { - TypeIntent() { hasQualifiedName("android.content", "Intent") } + TypeIntent() { this.hasQualifiedName("android.content", "Intent") } } /** * The class `android.app.Activity`. */ class TypeActivity extends Class { - TypeActivity() { hasQualifiedName("android.app", "Activity") } + TypeActivity() { this.hasQualifiedName("android.app", "Activity") } } /** * The class `android.content.Context`. */ class TypeContext extends RefType { - TypeContext() { hasQualifiedName("android.content", "Context") } + TypeContext() { this.hasQualifiedName("android.content", "Context") } } /** * The class `android.content.BroadcastReceiver`. */ class TypeBroadcastReceiver extends Class { - TypeBroadcastReceiver() { hasQualifiedName("android.content", "BroadcastReceiver") } + TypeBroadcastReceiver() { this.hasQualifiedName("android.content", "BroadcastReceiver") } } /** * The method `Activity.getIntent` */ class AndroidGetIntentMethod extends Method { - AndroidGetIntentMethod() { hasName("getIntent") and getDeclaringType() instanceof TypeActivity } + AndroidGetIntentMethod() { + this.hasName("getIntent") and this.getDeclaringType() instanceof TypeActivity + } } /** @@ -43,7 +45,7 @@ class AndroidGetIntentMethod extends Method { */ class AndroidReceiveIntentMethod extends Method { AndroidReceiveIntentMethod() { - hasName("onReceive") and getDeclaringType() instanceof TypeBroadcastReceiver + this.hasName("onReceive") and this.getDeclaringType() instanceof TypeBroadcastReceiver } } @@ -52,8 +54,8 @@ class AndroidReceiveIntentMethod extends Method { */ class ContextStartActivityMethod extends Method { ContextStartActivityMethod() { - (hasName("startActivity") or hasName("startActivities")) and - getDeclaringType() instanceof TypeContext + (this.hasName("startActivity") or this.hasName("startActivities")) and + this.getDeclaringType() instanceof TypeContext } } @@ -70,8 +72,8 @@ private class IntentFieldsInheritTaint extends DataFlow::SyntheticFieldContent, */ class IntentGetParcelableExtraMethod extends Method { IntentGetParcelableExtraMethod() { - hasName("getParcelableExtra") and - getDeclaringType() instanceof TypeIntent + this.hasName("getParcelableExtra") and + this.getDeclaringType() instanceof TypeIntent } } diff --git a/java/ql/lib/semmle/code/java/frameworks/android/WebView.qll b/java/ql/lib/semmle/code/java/frameworks/android/WebView.qll index 683faa73bef..6717eed4f63 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/WebView.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/WebView.qll @@ -1,15 +1,15 @@ import java class TypeWebView extends Class { - TypeWebView() { hasQualifiedName("android.webkit", "WebView") } + TypeWebView() { this.hasQualifiedName("android.webkit", "WebView") } } class TypeWebViewClient extends Class { - TypeWebViewClient() { hasQualifiedName("android.webkit", "WebViewClient") } + TypeWebViewClient() { this.hasQualifiedName("android.webkit", "WebViewClient") } } class TypeWebSettings extends Class { - TypeWebSettings() { hasQualifiedName("android.webkit", "WebSettings") } + TypeWebSettings() { this.hasQualifiedName("android.webkit", "WebSettings") } } class WebViewGetSettingsMethod extends Method { diff --git a/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll b/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll index 6f3da74f017..d98967566e8 100644 --- a/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll +++ b/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll @@ -25,14 +25,14 @@ private class TypeLiteralToParseAsFlowConfiguration extends DataFlowForSerializa ) } - TypeLiteral getSourceWithFlowToParseAs() { hasFlow(DataFlow::exprNode(result), _) } + TypeLiteral getSourceWithFlowToParseAs() { this.hasFlow(DataFlow::exprNode(result), _) } } /** A field that is deserialized by `HttpResponse.parseAs`. */ class HttpResponseParseAsDeserializableField extends DeserializableField { HttpResponseParseAsDeserializableField() { exists(RefType decltype, TypeLiteralToParseAsFlowConfiguration conf | - decltype = getDeclaringType() and + decltype = this.getDeclaringType() and conf.getSourceWithFlowToParseAs().getReferencedType() = decltype and decltype.fromSource() ) diff --git a/java/ql/lib/semmle/code/java/frameworks/gwt/GWT.qll b/java/ql/lib/semmle/code/java/frameworks/gwt/GWT.qll index 93d79813e39..0da20780482 100644 --- a/java/ql/lib/semmle/code/java/frameworks/gwt/GWT.qll +++ b/java/ql/lib/semmle/code/java/frameworks/gwt/GWT.qll @@ -38,7 +38,7 @@ class GwtEntryPointClass extends Class { isGwtXmlIncluded() implies // The entry point is live if it is specified in a `*.gwt.xml` file. - exists(getAGwtXmlFile()) + exists(this.getAGwtXmlFile()) } } @@ -48,7 +48,7 @@ class GwtEntryPointClass extends Class { */ class GwtCompilationUnit extends CompilationUnit { GwtCompilationUnit() { - exists(GwtXmlFile f | getRelativePath().matches(f.getARelativeSourcePath() + "%")) + exists(GwtXmlFile f | this.getRelativePath().matches(f.getARelativeSourcePath() + "%")) } } diff --git a/java/ql/lib/semmle/code/java/frameworks/gwt/GwtUiBinder.qll b/java/ql/lib/semmle/code/java/frameworks/gwt/GwtUiBinder.qll index dc8aa0b1ba6..8532cc81bb3 100644 --- a/java/ql/lib/semmle/code/java/frameworks/gwt/GwtUiBinder.qll +++ b/java/ql/lib/semmle/code/java/frameworks/gwt/GwtUiBinder.qll @@ -12,57 +12,62 @@ import GwtUiBinderXml * An annotation in the package `com.google.gwt.uibinder.client`. */ class GwtUiBinderClientAnnotation extends Annotation { - GwtUiBinderClientAnnotation() { getType().getPackage().hasName("com.google.gwt.uibinder.client") } + GwtUiBinderClientAnnotation() { + this.getType().getPackage().hasName("com.google.gwt.uibinder.client") + } } /** * A `@com.google.gwt.uibinder.client.UiHandler` annotation. */ class GwtUiHandlerAnnotation extends GwtUiBinderClientAnnotation { - GwtUiHandlerAnnotation() { getType().hasName("UiHandler") } + GwtUiHandlerAnnotation() { this.getType().hasName("UiHandler") } } /** * A `@com.google.gwt.uibinder.client.UiField` annotation. */ class GwtUiFieldAnnotation extends GwtUiBinderClientAnnotation { - GwtUiFieldAnnotation() { getType().hasName("UiField") } + GwtUiFieldAnnotation() { this.getType().hasName("UiField") } } /** * A `@com.google.gwt.uibinder.client.UiTemplate` annotation. */ class GwtUiTemplateAnnotation extends GwtUiBinderClientAnnotation { - GwtUiTemplateAnnotation() { getType().hasName("UiTemplate") } + GwtUiTemplateAnnotation() { this.getType().hasName("UiTemplate") } } /** * A `@com.google.gwt.uibinder.client.UiFactory` annotation. */ class GwtUiFactoryAnnotation extends GwtUiBinderClientAnnotation { - GwtUiFactoryAnnotation() { getType().hasName("UiFactory") } + GwtUiFactoryAnnotation() { this.getType().hasName("UiFactory") } } /** * A `@com.google.gwt.uibinder.client.UiConstructor` annotation. */ class GwtUiConstructorAnnotation extends GwtUiBinderClientAnnotation { - GwtUiConstructorAnnotation() { getType().hasName("UiConstructor") } + GwtUiConstructorAnnotation() { this.getType().hasName("UiConstructor") } } /** * A field that is reflectively written to, and read from, by the GWT UiBinder framework. */ class GwtUiField extends Field { - GwtUiField() { getAnAnnotation() instanceof GwtUiFieldAnnotation } + GwtUiField() { this.getAnAnnotation() instanceof GwtUiFieldAnnotation } /** * If true, the field must be filled before `UiBinder.createAndBindUi` is called. * If false, `UiBinder.createAndBindUi` will fill the field. */ predicate isProvided() { - getAnAnnotation().(GwtUiFieldAnnotation).getValue("provided").(BooleanLiteral).getBooleanValue() = - true + this.getAnAnnotation() + .(GwtUiFieldAnnotation) + .getValue("provided") + .(BooleanLiteral) + .getBooleanValue() = true } } @@ -70,14 +75,14 @@ class GwtUiField extends Field { * A method called as a handler for events thrown by GWT widgets. */ class GwtUiHandler extends Method { - GwtUiHandler() { getAnAnnotation() instanceof GwtUiHandlerAnnotation } + GwtUiHandler() { this.getAnAnnotation() instanceof GwtUiHandlerAnnotation } /** * Gets the name of the field for which this handler is registered. */ string getFieldName() { result = - getAnAnnotation() + this.getAnAnnotation() .(GwtUiHandlerAnnotation) .getValue("value") .(CompileTimeConstantExpr) @@ -89,7 +94,7 @@ class GwtUiHandler extends Method { */ GwtUiField getField() { result = this.getDeclaringType().getAField() and - result.getName() = getFieldName() + result.getName() = this.getFieldName() } } @@ -98,12 +103,12 @@ class GwtUiHandler extends Method { * construct an instance of a class specified in a UiBinder XML file. */ class GwtUiFactory extends Method { - GwtUiFactory() { getAnAnnotation() instanceof GwtUiFactoryAnnotation } + GwtUiFactory() { this.getAnAnnotation() instanceof GwtUiFactoryAnnotation } } /** * A constructor that may be called by the UiBinder framework as a result of a `GWT.create()` call. */ class GwtUiConstructor extends Constructor { - GwtUiConstructor() { getAnAnnotation() instanceof GwtUiConstructorAnnotation } + GwtUiConstructor() { this.getAnAnnotation() instanceof GwtUiConstructorAnnotation } } diff --git a/java/ql/lib/semmle/code/java/frameworks/gwt/GwtUiBinderXml.qll b/java/ql/lib/semmle/code/java/frameworks/gwt/GwtUiBinderXml.qll index 26d598b77ef..f5227e0a722 100644 --- a/java/ql/lib/semmle/code/java/frameworks/gwt/GwtUiBinderXml.qll +++ b/java/ql/lib/semmle/code/java/frameworks/gwt/GwtUiBinderXml.qll @@ -36,8 +36,8 @@ class GwtComponentTemplateElement extends XMLElement { */ Class getClass() { exists(string namespace | - namespace = getNamespace().getURI() and - result.getQualifiedName() = namespace.substring(11, namespace.length()) + "." + getName() + namespace = this.getNamespace().getURI() and + result.getQualifiedName() = namespace.substring(11, namespace.length()) + "." + this.getName() ) } } diff --git a/java/ql/lib/semmle/code/java/frameworks/gwt/GwtXml.qll b/java/ql/lib/semmle/code/java/frameworks/gwt/GwtXml.qll index 482d5d70e93..3ac223be2d5 100644 --- a/java/ql/lib/semmle/code/java/frameworks/gwt/GwtXml.qll +++ b/java/ql/lib/semmle/code/java/frameworks/gwt/GwtXml.qll @@ -16,24 +16,24 @@ class GwtXmlFile extends XMLFile { /** Gets the name of an inherited GWT module, for example `com.google.gwt.user.User`. */ string getAnInheritedModuleName() { - result = getModuleElement().getAnInheritsElement().getAnInheritedName() + result = this.getModuleElement().getAnInheritsElement().getAnInheritedName() } /** Gets a GWT module XML file (from source) inherited from this module. */ GwtXmlFile getAnInheritedXmlFile() { exists(GwtXmlFile f, string name | - name = getAnInheritedModuleName() and + name = this.getAnInheritedModuleName() and f.getAbsolutePath().matches("%/" + name.replaceAll(".", "/") + ".gwt.xml") and result = f ) } /** Gets the relative path of the folder containing this GWT module XML file. */ - string getRelativeRootFolderPath() { result = getParentContainer().getRelativePath() } + string getRelativeRootFolderPath() { result = this.getParentContainer().getRelativePath() } /** Gets a GWT-translatable source sub-folder explicitly defined in a `<source>` element. */ string getAnExplicitSourceSubPath() { - result = getModuleElement().getASourceElement().getASourcePath() + result = this.getModuleElement().getASourceElement().getASourcePath() } /** @@ -41,9 +41,9 @@ class GwtXmlFile extends XMLFile { * Either the default `client` folder or as specified by `<source>` tags. */ string getASourceSubPath() { - result = "client" and not exists(getAnExplicitSourceSubPath()) + result = "client" and not exists(this.getAnExplicitSourceSubPath()) or - result = getAnExplicitSourceSubPath() + result = this.getAnExplicitSourceSubPath() } /** @@ -52,7 +52,7 @@ class GwtXmlFile extends XMLFile { * (Includes the full relative root folder path of the GWT module.) */ string getARelativeSourcePath() { - result = getRelativeRootFolderPath() + "/" + getASourceSubPath() + result = this.getRelativeRootFolderPath() + "/" + this.getASourceSubPath() } } @@ -81,7 +81,7 @@ class GwtInheritsElement extends XMLElement { } /** Gets the name of an inherited GWT module, for example `com.google.gwt.user.User`. */ - string getAnInheritedName() { result = getAttribute("name").getValue() } + string getAnInheritedName() { result = this.getAttribute("name").getValue() } } /** An `<entry-point>` element within a GWT module XML file. */ @@ -92,7 +92,7 @@ class GwtEntryPointElement extends XMLElement { } /** Gets the name of a class that serves as a GWT entry-point. */ - string getClassName() { result = getAttribute("class").getValue().trim() } + string getClassName() { result = this.getAttribute("class").getValue().trim() } } /** A `<source>` element within a GWT module XML file. */ @@ -104,11 +104,11 @@ class GwtSourceElement extends XMLElement { /** Gets a path specified to be GWT translatable source code. */ string getASourcePath() { - result = getAttribute("path").getValue() and + result = this.getAttribute("path").getValue() and // Conservative approximation, ignoring Ant-style `FileSet` semantics. - not exists(getAChild()) and - not exists(getAttribute("includes")) and - not exists(getAttribute("excludes")) + not exists(this.getAChild()) and + not exists(this.getAttribute("includes")) and + not exists(this.getAttribute("excludes")) } } @@ -120,5 +120,5 @@ class GwtServletElement extends XMLElement { } /** Gets the name of a class that is used as a servlet. */ - string getClassName() { result = getAttribute("class").getValue().trim() } + string getClassName() { result = this.getAttribute("class").getValue().trim() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/j2objc/J2ObjC.qll b/java/ql/lib/semmle/code/java/frameworks/j2objc/J2ObjC.qll index c3a28fecd42..113c8b76024 100644 --- a/java/ql/lib/semmle/code/java/frameworks/j2objc/J2ObjC.qll +++ b/java/ql/lib/semmle/code/java/frameworks/j2objc/J2ObjC.qll @@ -10,9 +10,9 @@ import java class OCNIComment extends Javadoc { OCNIComment() { // The comment must start with `-[` ... - getChild(0).getText().matches("-[%") and + this.getChild(0).getText().matches("-[%") and // ... and it must end with `]-`. - getChild(getNumChild() - 1).getText().matches("%]-") + this.getChild(this.getNumChild() - 1).getText().matches("%]-") } } @@ -42,9 +42,9 @@ class OCNIMethodComment extends OCNIComment { */ class OCNIImport extends OCNIComment { OCNIImport() { - getAChild().getText().regexpMatch(".*#(import|include).*") and + this.getAChild().getText().regexpMatch(".*#(import|include).*") and not exists(RefType rt | rt.getFile() = this.getFile() | - rt.getLocation().getStartLine() < getLocation().getStartLine() + rt.getLocation().getStartLine() < this.getLocation().getStartLine() ) } } diff --git a/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll index 6dda49dbadd..f5d2bfb78f9 100644 --- a/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll +++ b/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll @@ -32,21 +32,21 @@ abstract class JacksonSerializableType extends Type { } private class JacksonWriteValueMethod extends Method, TaintPreservingCallable { JacksonWriteValueMethod() { ( - getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectWriter") or - getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectMapper") + this.getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectWriter") or + this.getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectMapper") ) and - getName().matches("writeValue%") and - getParameter(getNumberOfParameters() - 1).getType() instanceof TypeObject + this.getName().matches("writeValue%") and + this.getParameter(this.getNumberOfParameters() - 1).getType() instanceof TypeObject } override predicate returnsTaintFrom(int arg) { - getNumberOfParameters() = 1 and + this.getNumberOfParameters() = 1 and arg = 0 } override predicate transfersTaint(int src, int sink) { - getNumberOfParameters() > 1 and - src = getNumberOfParameters() - 1 and + this.getNumberOfParameters() > 1 and + src = this.getNumberOfParameters() - 1 and sink = 0 } } @@ -58,10 +58,10 @@ private class JacksonWriteValueMethod extends Method, TaintPreservingCallable { private class JacksonReadValueMethod extends Method, TaintPreservingCallable { JacksonReadValueMethod() { ( - getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectReader") or - getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectMapper") + this.getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectReader") or + this.getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectMapper") ) and - hasName(["readValue", "readValues"]) + this.hasName(["readValue", "readValues"]) } override predicate returnsTaintFrom(int arg) { arg = 0 } @@ -109,7 +109,7 @@ private class TypeLiteralToJacksonDatabindFlowConfiguration extends DataFlowForS ) } - TypeLiteral getSourceWithFlowToJacksonDatabind() { hasFlow(DataFlow::exprNode(result), _) } + TypeLiteral getSourceWithFlowToJacksonDatabind() { this.hasFlow(DataFlow::exprNode(result), _) } } /** A type whose values are explicitly deserialized in a call to a Jackson method. */ @@ -139,7 +139,7 @@ private class FieldReferencedJacksonDeserializableType extends JacksonDeserializ class JacksonSerializableField extends SerializableField { JacksonSerializableField() { exists(JacksonSerializableType superType | - superType = getDeclaringType().getASupertype*() and + superType = this.getDeclaringType().getASupertype*() and not superType instanceof TypeObject and superType.fromSource() ) and @@ -151,7 +151,7 @@ class JacksonSerializableField extends SerializableField { class JacksonDeserializableField extends DeserializableField { JacksonDeserializableField() { exists(JacksonDeserializableType superType | - superType = getDeclaringType().getASupertype*() and + superType = this.getDeclaringType().getASupertype*() and not superType instanceof TypeObject and superType.fromSource() ) and @@ -161,7 +161,7 @@ class JacksonDeserializableField extends DeserializableField { /** A call to a field that may be deserialized using the Jackson JSON framework. */ private class JacksonDeserializableFieldAccess extends FieldAccess { - JacksonDeserializableFieldAccess() { getField() instanceof JacksonDeserializableField } + JacksonDeserializableFieldAccess() { this.getField() instanceof JacksonDeserializableField } } /** @@ -194,19 +194,19 @@ class JacksonAddMixinCall extends MethodAccess { /** * Gets a possible type for the target of the mixing, if any can be deduced. */ - RefType getATarget() { result = inferClassParameterType(getArgument(0)) } + RefType getATarget() { result = inferClassParameterType(this.getArgument(0)) } /** * Gets a possible type that will be mixed in, if any can be deduced. */ - RefType getAMixedInType() { result = inferClassParameterType(getArgument(1)) } + RefType getAMixedInType() { result = inferClassParameterType(this.getArgument(1)) } } /** * A Jackson annotation. */ class JacksonAnnotation extends Annotation { - JacksonAnnotation() { getType().getPackage().hasName("com.fasterxml.jackson.annotation") } + JacksonAnnotation() { this.getType().getPackage().hasName("com.fasterxml.jackson.annotation") } } /** @@ -228,7 +228,7 @@ class JacksonMixinType extends ClassOrInterface { * Gets a callable from this type that is mixed in by Jackson. */ Callable getAMixedInCallable() { - result = getACallable() and + result = this.getACallable() and ( result.(Constructor).isDefaultConstructor() or result.getAnAnnotation() instanceof JacksonAnnotation or @@ -240,7 +240,7 @@ class JacksonMixinType extends ClassOrInterface { * Gets a field that is mixed in by Jackson. */ Field getAMixedInField() { - result = getAField() and + result = this.getAField() and result.getAnAnnotation() instanceof JacksonAnnotation } } @@ -264,17 +264,17 @@ class JacksonMixedInCallable extends Callable { * Gets a callable on a possible target that this is mixed into. */ Callable getATargetCallable() { - exists(RefType targetType | targetType = getATargetType() | - result = getATargetType().getACallable() and + exists(RefType targetType | targetType = this.getATargetType() | + result = this.getATargetType().getACallable() and if this instanceof Constructor then // The mixed in type will have a different name to the target type, so just compare the // parameters. result.getSignature().suffix(targetType.getName().length()) = - getSignature().suffix(getDeclaringType().getName().length()) + this.getSignature().suffix(this.getDeclaringType().getName().length()) else // Signatures should match - result.getSignature() = getSignature() + result.getSignature() = this.getSignature() ) } } diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll index e980cb2187a..82569754394 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll @@ -10,8 +10,8 @@ import java */ class PersistentEntity extends RefType { PersistentEntity() { - getAnAnnotation() instanceof EntityAnnotation or - getAnAnnotation() instanceof EmbeddableAnnotation + this.getAnAnnotation() instanceof EntityAnnotation or + this.getAnAnnotation() instanceof EmbeddableAnnotation } /** @@ -22,12 +22,12 @@ class PersistentEntity extends RefType { * instead. */ string getAccessType() { - if exists(getAccessTypeFromAnnotation()) - then result = getAccessTypeFromAnnotation() + if exists(this.getAccessTypeFromAnnotation()) + then result = this.getAccessTypeFromAnnotation() else // If the access type is not explicit, then the location of the `Id` annotation determines // which access type is used. - if getAMethod().hasAnnotation("javax.persistence", "Id") + if this.getAMethod().hasAnnotation("javax.persistence", "Id") then result = "property" else result = "field" } @@ -36,7 +36,7 @@ class PersistentEntity extends RefType { * Gets the access type for this entity as defined by a `@javax.persistence.Access` annotation, if any. */ string getAccessTypeFromAnnotation() { - exists(AccessAnnotation accessType | accessType = getAnAnnotation() | + exists(AccessAnnotation accessType | accessType = this.getAnAnnotation() | result = accessType.getValue("value").(FieldRead).getField().(EnumConstant).getName().toLowerCase() ) diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/PersistenceXML.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/PersistenceXML.qll index 8051b470bd3..82fc32baca2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/PersistenceXML.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/PersistenceXML.qll @@ -100,7 +100,7 @@ class PersistencePropertyElement extends XMLElement { * disables the EclipseLink shared cache. */ predicate disablesEclipseLinkSharedCache() { - getAttribute("name").getValue() = "eclipselink.cache.shared.default" and - getAttribute("value").getValue() = "false" + this.getAttribute("name").getValue() = "eclipselink.cache.shared.default" and + this.getAttribute("value").getValue() = "false" } } diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll index 9f180dcd587..8509afc5622 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll @@ -8,7 +8,7 @@ import EJBJarXML */ abstract class EJB extends Class { /** Gets a `Callable` that is directly or indirectly called from within the EJB. */ - Callable getAUsedCallable() { getACallable().polyCalls*(result) } + Callable getAUsedCallable() { this.getACallable().polyCalls*(result) } } /** @@ -33,16 +33,16 @@ class SessionEJB extends EJB { // Either the EJB does not declare any business interfaces explicitly // and implements a single interface candidate, // which is then considered to be the business interface... - count(getAnExplicitBusinessInterface()) = 0 and - count(getAnImplementedBusinessInterfaceCandidate()) = 1 and - result = getAnImplementedBusinessInterfaceCandidate() + count(this.getAnExplicitBusinessInterface()) = 0 and + count(this.getAnImplementedBusinessInterfaceCandidate()) = 1 and + result = this.getAnImplementedBusinessInterfaceCandidate() or // ...or each business interface needs to be declared explicitly. ( - count(getAnImplementedBusinessInterfaceCandidate()) != 1 or - count(getAnExplicitBusinessInterface()) != 0 + count(this.getAnImplementedBusinessInterfaceCandidate()) != 1 or + count(this.getAnExplicitBusinessInterface()) != 0 ) and - result = getAnExplicitBusinessInterface() + result = this.getAnExplicitBusinessInterface() } /** @@ -198,7 +198,7 @@ abstract class EjbInterfaceAnnotation extends Annotation { // Returns the type `Foo` of any type literal `Foo.class` occurring // within the "value" element of this annotation. // Uses `getAChildExpr*()` since the "value" element can have type `Class` or `Class[]`. - exists(TypeLiteral tl | tl = getValue("value").getAChildExpr*() | + exists(TypeLiteral tl | tl = this.getValue("value").getAChildExpr*() | result = tl.getReferencedType() ) } @@ -447,7 +447,7 @@ class AnnotatedRemoteHomeInterface extends LegacyEjbRemoteHomeInterface { SessionEJB getAnEJB() { result.getAnAnnotation().(RemoteHomeAnnotation).getANamedType() = this } /** Gets a remote interface associated with this legacy remote home interface. */ - Interface getAnAssociatedRemoteInterface() { result = getACreateMethod().getReturnType() } + Interface getAnAssociatedRemoteInterface() { result = this.getACreateMethod().getReturnType() } } /** A legacy remote home interface specified within an XML deployment descriptor. */ @@ -511,7 +511,7 @@ class AnnotatedLocalHomeInterface extends LegacyEjbLocalHomeInterface { SessionEJB getAnEJB() { result.getAnAnnotation().(LocalHomeAnnotation).getANamedType() = this } /** Gets a local interface associated with this legacy local home interface. */ - Interface getAnAssociatedLocalInterface() { result = getACreateMethod().getReturnType() } + Interface getAnAssociatedLocalInterface() { result = this.getACreateMethod().getReturnType() } } /** A legacy local home interface specified within an XML deployment descriptor. */ @@ -562,8 +562,8 @@ class RemoteInterface extends Interface { /** Gets a remote method implementation for this remote interface. */ Method getARemoteMethodImplementation() { - result = getARemoteMethodImplementationChecked() or - result = getARemoteMethodImplementationUnchecked() + result = this.getARemoteMethodImplementationChecked() or + result = this.getARemoteMethodImplementationUnchecked() } /** @@ -572,7 +572,7 @@ class RemoteInterface extends Interface { * abstract methods or overriding within an interface hierarchy. */ Method getARemoteMethodImplementationChecked() { - result.overrides(getARemoteMethod()) and + result.overrides(this.getARemoteMethod()) and exists(result.getBody()) } @@ -586,9 +586,9 @@ class RemoteInterface extends Interface { */ Method getARemoteMethodImplementationUnchecked() { exists(SessionEJB ejb, Method rm | - ejb = getAnEJB() and + ejb = this.getAnEJB() and not ejb.getASupertype*() = this and - rm = getARemoteMethod() and + rm = this.getARemoteMethod() and result = getAnInheritedMatchingMethodIgnoreThrows(ejb, rm.getSignature()) and not exists(inheritsMatchingMethodExceptThrows(ejb, rm)) ) and diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBJarXML.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBJarXML.qll index 02e73c2be5c..db89836ff9d 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBJarXML.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBJarXML.qll @@ -114,8 +114,8 @@ class EjbJarSessionElement extends EjbJarBeanTypeElement { * This is either a `business-local` or `business-remote` element. */ XMLElement getABusinessElement() { - result = getABusinessLocalElement() or - result = getABusinessRemoteElement() + result = this.getABusinessLocalElement() or + result = this.getABusinessRemoteElement() } /** Gets a `remote` child XML element of this `session` XML element. */ @@ -153,7 +153,7 @@ class EjbJarSessionElement extends EjbJarBeanTypeElement { * XML element nested within this `session` XML element. */ XMLElement getACreateMethodNameElement() { - result = getAnInitMethodElement().getACreateMethodElement().getAMethodNameElement() + result = this.getAnInitMethodElement().getACreateMethodElement().getAMethodNameElement() } /** @@ -161,7 +161,7 @@ class EjbJarSessionElement extends EjbJarBeanTypeElement { * XML element nested within this `session` XML element. */ XMLElement getABeanMethodNameElement() { - result = getAnInitMethodElement().getABeanMethodElement().getAMethodNameElement() + result = this.getAnInitMethodElement().getABeanMethodElement().getAMethodNameElement() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFFacesContextXML.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFFacesContextXML.qll index 8d26c1efc62..2d6721298a9 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFFacesContextXML.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFFacesContextXML.qll @@ -25,14 +25,14 @@ class FacesConfigXMLElement extends XMLElement { /** * Gets the value for this element, with leading and trailing whitespace trimmed. */ - string getValue() { result = allCharactersString().trim() } + string getValue() { result = this.allCharactersString().trim() } } /** * An element in a JSF config file that declares a managed bean. */ class FacesConfigManagedBean extends FacesConfigXMLElement { - FacesConfigManagedBean() { getName() = "managed-bean" } + FacesConfigManagedBean() { this.getName() = "managed-bean" } } /** @@ -40,21 +40,21 @@ class FacesConfigManagedBean extends FacesConfigXMLElement { */ class FacesConfigManagedBeanClass extends FacesConfigXMLElement { FacesConfigManagedBeanClass() { - getName() = "managed-bean-class" and - getParent() instanceof FacesConfigManagedBean + this.getName() = "managed-bean-class" and + this.getParent() instanceof FacesConfigManagedBean } /** * Gets the `Class` of the managed bean. */ - Class getManagedBeanClass() { result.getQualifiedName() = getValue() } + Class getManagedBeanClass() { result.getQualifiedName() = this.getValue() } } /** * An element in a JSF config file that declares a custom component. */ class FacesConfigComponent extends FacesConfigXMLElement { - FacesConfigComponent() { getName() = "component" } + FacesConfigComponent() { this.getName() = "component" } } /** @@ -62,12 +62,12 @@ class FacesConfigComponent extends FacesConfigXMLElement { */ class FacesConfigComponentClass extends FacesConfigXMLElement { FacesConfigComponentClass() { - getName() = "component-class" and - getParent() instanceof FacesConfigComponent + this.getName() = "component-class" and + this.getParent() instanceof FacesConfigComponent } /** * Gets the `Class` of the faces component. */ - Class getFacesComponentClass() { result.getQualifiedName() = getValue() } + Class getFacesComponentClass() { result.getQualifiedName() = this.getValue() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFRenderer.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFRenderer.qll index 5703cde79ed..1b825d29c2f 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFRenderer.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFRenderer.qll @@ -33,9 +33,9 @@ private class ExternalContextSource extends SourceModelCsv { */ class FacesGetResponseWriterMethod extends Method { FacesGetResponseWriterMethod() { - getDeclaringType() instanceof FacesContext and - hasName("getResponseWriter") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof FacesContext and + this.hasName("getResponseWriter") and + this.getNumberOfParameters() = 0 } } @@ -44,9 +44,9 @@ class FacesGetResponseWriterMethod extends Method { */ class FacesGetResponseStreamMethod extends Method { FacesGetResponseStreamMethod() { - getDeclaringType() instanceof FacesContext and - hasName("getResponseStream") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof FacesContext and + this.hasName("getResponseStream") and + this.getNumberOfParameters() = 0 } } diff --git a/java/ql/lib/semmle/code/java/frameworks/javase/Http.qll b/java/ql/lib/semmle/code/java/frameworks/javase/Http.qll index 29a6c5f6646..5f03c0b190f 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javase/Http.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javase/Http.qll @@ -6,12 +6,12 @@ import java /** The interface representing `HttpRequest.Builder`. */ class TypeHttpRequestBuilder extends Interface { - TypeHttpRequestBuilder() { hasQualifiedName("java.net.http", "HttpRequest$Builder") } + TypeHttpRequestBuilder() { this.hasQualifiedName("java.net.http", "HttpRequest$Builder") } } /** The interface representing `java.net.http.HttpRequest`. */ class TypeHttpRequest extends Interface { - TypeHttpRequest() { hasQualifiedName("java.net.http", "HttpRequest") } + TypeHttpRequest() { this.hasQualifiedName("java.net.http", "HttpRequest") } } /** The `uri` method on `java.net.http.HttpRequest.Builder`. */ diff --git a/java/ql/lib/semmle/code/java/frameworks/play/Play.qll b/java/ql/lib/semmle/code/java/frameworks/play/Play.qll index efe2e128fee..695f64f53d1 100644 --- a/java/ql/lib/semmle/code/java/frameworks/play/Play.qll +++ b/java/ql/lib/semmle/code/java/frameworks/play/Play.qll @@ -45,7 +45,7 @@ class PlayAddCsrfTokenAnnotation extends Annotation { * The type `play.libs.F.Promise<Result>`. */ class PlayAsyncResultPromise extends MemberType { - PlayAsyncResultPromise() { hasQualifiedName("play.libs", "F$Promise<Result>") } + PlayAsyncResultPromise() { this.hasQualifiedName("play.libs", "F$Promise<Result>") } } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll index e695b26ba0c..f387b40a547 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll @@ -24,7 +24,7 @@ predicate hasInjectAnnotation(Annotatable a) { class SpringComponentConstructor extends Constructor { SpringComponentConstructor() { // Must be a live Spring component. - getDeclaringType().(SpringComponent).isLive() and + this.getDeclaringType().(SpringComponent).isLive() and ( this.getNumberOfParameters() = 0 or hasInjectAnnotation(this) @@ -93,8 +93,8 @@ class SpringBeanXMLAutowiredSetterMethod extends Method { ) ) and // The resulting bean is of the right type. - result.getClass().getAnAncestor() = getParameter(0).getType() and - getNumberOfParameters() = 1 and + result.getClass().getAnAncestor() = this.getParameter(0).getType() and + this.getNumberOfParameters() = 1 and this.getName().matches("set%") ) } @@ -110,7 +110,7 @@ class SpringBeanAutowiredCallable extends Callable { // Marked as `@Autowired`. hasInjectAnnotation(this) and // No autowiring occurs if there are no parameters - getNumberOfParameters() > 0 + this.getNumberOfParameters() > 0 } /** @@ -118,7 +118,7 @@ class SpringBeanAutowiredCallable extends Callable { * defined in. */ SpringBean getEnclosingSpringBean() { - result = getDeclaringType().(SpringBeanRefType).getSpringBean() + result = this.getDeclaringType().(SpringBeanRefType).getSpringBean() } /** @@ -129,22 +129,24 @@ class SpringBeanAutowiredCallable extends Callable { /** * Gets the qualifier annotation for parameter at `pos`, if any. */ - SpringQualifierAnnotation getQualifier(int pos) { result = getParameter(pos).getAnAnnotation() } + SpringQualifierAnnotation getQualifier(int pos) { + result = this.getParameter(pos).getAnAnnotation() + } /** * Gets the qualifier annotation for this method, if any. */ - SpringQualifierAnnotation getQualifier() { result = getAnAnnotation() } + SpringQualifierAnnotation getQualifier() { result = this.getAnAnnotation() } /** * Gets the resource annotation for this method, if any. */ - SpringResourceAnnotation getResource() { result = getAnAnnotation() } + SpringResourceAnnotation getResource() { result = this.getAnAnnotation() } /** * Gets a bean that will be injected into this callable. */ - SpringBean getAnInjectedBean() { result = getInjectedBean(_) } + SpringBean getAnInjectedBean() { result = this.getInjectedBean(_) } /** * Gets the `SpringBean`, if any, that will be injected for the parameter at position `pos`, @@ -152,24 +154,24 @@ class SpringBeanAutowiredCallable extends Callable { */ SpringBean getInjectedBean(int pos) { // Must be a sub-type of the parameter type - result.getClass().getAnAncestor() = getParameterType(pos) and + result.getClass().getAnAncestor() = this.getParameterType(pos) and // Now look up bean - if exists(getQualifier(pos)) + if exists(this.getQualifier(pos)) then // Resolved by `@Qualifier("qualifier")` specified on the parameter - result = getQualifier(pos).getSpringBean() + result = this.getQualifier(pos).getSpringBean() else - if exists(getQualifier()) and getNumberOfParameters() = 1 + if exists(this.getQualifier()) and this.getNumberOfParameters() = 1 then // Resolved by `@Qualifier("qualifier")` on the method pos = 0 and - result = getQualifier().getSpringBean() + result = this.getQualifier().getSpringBean() else - if exists(getResource().getNameValue()) and getNumberOfParameters() = 1 + if exists(this.getResource().getNameValue()) and this.getNumberOfParameters() = 1 then // Resolved by looking at the name part of `@Resource(name="qualifier")` pos = 0 and - result = getResource().getSpringBean() + result = this.getResource().getSpringBean() else // Otherwise no restrictions, just by type any() @@ -181,24 +183,24 @@ class SpringBeanAutowiredCallable extends Callable { */ SpringComponent getInjectedComponent(int pos) { // Must be a sub-type of the parameter type - result.getAnAncestor() = getParameterType(pos) and + result.getAnAncestor() = this.getParameterType(pos) and // Now look up bean - if exists(getQualifier(pos)) + if exists(this.getQualifier(pos)) then // Resolved by `@Qualifier("qualifier")` specified on the parameter - result = getQualifier(pos).getSpringComponent() + result = this.getQualifier(pos).getSpringComponent() else - if exists(getQualifier()) and getNumberOfParameters() = 1 + if exists(this.getQualifier()) and this.getNumberOfParameters() = 1 then // Resolved by `@Qualifier("qualifier")` on the method pos = 0 and - result = getQualifier().getSpringComponent() + result = this.getQualifier().getSpringComponent() else - if exists(getResource().getNameValue()) and getNumberOfParameters() = 1 + if exists(this.getResource().getNameValue()) and this.getNumberOfParameters() = 1 then // Resolved by looking at the name part of `@Resource(name="qualifier")` pos = 0 and - result = getResource().getSpringComponent() + result = this.getResource().getSpringComponent() else // Otherwise no restrictions, just by type any() @@ -219,7 +221,7 @@ class SpringBeanAutowiredField extends Field { * defined in. */ SpringBean getEnclosingSpringBean() { - result = getDeclaringType().(SpringBeanRefType).getSpringBean() + result = this.getDeclaringType().(SpringBeanRefType).getSpringBean() } /** @@ -230,12 +232,12 @@ class SpringBeanAutowiredField extends Field { /** * Gets the qualifier annotation for this method, if any. */ - SpringQualifierAnnotation getQualifier() { result = getAnAnnotation() } + SpringQualifierAnnotation getQualifier() { result = this.getAnAnnotation() } /** * Gets the resource annotation for this method, if any. */ - SpringResourceAnnotation getResource() { result = getAnAnnotation() } + SpringResourceAnnotation getResource() { result = this.getAnAnnotation() } /** * Gets the `SpringBean`, if any, that will be injected for this field, considering any `@Qualifier` @@ -243,17 +245,17 @@ class SpringBeanAutowiredField extends Field { */ SpringBean getInjectedBean() { // Must be a sub-type of the parameter type - result.getClass().getAnAncestor() = getType() and + result.getClass().getAnAncestor() = this.getType() and // Now look up bean - if exists(getQualifier()) + if exists(this.getQualifier()) then // Resolved by `@Qualifier("qualifier")` specified on the field - result = getQualifier().getSpringBean() + result = this.getQualifier().getSpringBean() else - if exists(getResource().getNameValue()) + if exists(this.getResource().getNameValue()) then // Resolved by looking at the name part of `@Resource(name="qualifier")` - result = getResource().getSpringBean() + result = this.getResource().getSpringBean() else // Otherwise no restrictions, just by type any() @@ -265,17 +267,17 @@ class SpringBeanAutowiredField extends Field { */ SpringComponent getInjectedComponent() { // Must be a sub-type of the parameter type - result.getAnAncestor() = getType() and + result.getAnAncestor() = this.getType() and // Now look up bean - if exists(getQualifier()) + if exists(this.getQualifier()) then // Resolved by `@Qualifier("qualifier")` specified on the field - result = getQualifier().getSpringComponent() + result = this.getQualifier().getSpringComponent() else - if exists(getResource().getNameValue()) + if exists(this.getResource().getNameValue()) then // Resolved by looking at the name part of `@Resource(name="qualifier")` - result = getResource().getSpringComponent() + result = this.getResource().getSpringComponent() else // Otherwise no restrictions, just by type any() @@ -287,9 +289,9 @@ class SpringBeanAutowiredField extends Field { */ class SpringQualifierAnnotationType extends AnnotationType { SpringQualifierAnnotationType() { - hasQualifiedName("org.springframework.beans.factory.annotation", "Qualifier") or - hasQualifiedName("javax.inject", "Qualifier") or - getAnAnnotation().getType() instanceof SpringQualifierAnnotationType + this.hasQualifiedName("org.springframework.beans.factory.annotation", "Qualifier") or + this.hasQualifiedName("javax.inject", "Qualifier") or + this.getAnAnnotation().getType() instanceof SpringQualifierAnnotationType } } @@ -299,15 +301,15 @@ class SpringQualifierAnnotationType extends AnnotationType { */ class SpringQualifierDefinitionAnnotation extends Annotation { SpringQualifierDefinitionAnnotation() { - getType() instanceof SpringQualifierAnnotationType and - getAnnotatedElement() instanceof SpringComponent + this.getType() instanceof SpringQualifierAnnotationType and + this.getAnnotatedElement() instanceof SpringComponent } /** * Gets the value of the qualifier field for this qualifier. */ string getQualifierValue() { - result = getValue("value").(CompileTimeConstantExpr).getStringValue() + result = this.getValue("value").(CompileTimeConstantExpr).getStringValue() } } @@ -315,24 +317,24 @@ class SpringQualifierDefinitionAnnotation extends Annotation { * A qualifier annotation on a method or field that is used to disambiguate which bean will be used. */ class SpringQualifierAnnotation extends Annotation { - SpringQualifierAnnotation() { getType() instanceof SpringQualifierAnnotationType } + SpringQualifierAnnotation() { this.getType() instanceof SpringQualifierAnnotationType } /** * Gets the value of the qualifier field for this qualifier. */ string getQualifierValue() { - result = getValue("value").(CompileTimeConstantExpr).getStringValue() + result = this.getValue("value").(CompileTimeConstantExpr).getStringValue() } /** * Gets the bean definition in an XML file that this qualifier resolves to, if any. */ - SpringBean getSpringBean() { result.getQualifierValue() = getQualifierValue() } + SpringBean getSpringBean() { result.getQualifierValue() = this.getQualifierValue() } /** * Gets the Spring component that this qualifier resolves to, if any. */ - SpringComponent getSpringComponent() { result.getQualifierValue() = getQualifierValue() } + SpringComponent getSpringComponent() { result.getQualifierValue() = this.getQualifierValue() } } /** @@ -340,20 +342,22 @@ class SpringQualifierAnnotation extends Annotation { * autowired by Spring, and can optionally specify a qualifier in the "name". */ class SpringResourceAnnotation extends Annotation { - SpringResourceAnnotation() { getType().hasQualifiedName("javax.inject", "Resource") } + SpringResourceAnnotation() { this.getType().hasQualifiedName("javax.inject", "Resource") } /** * Gets the specified name value, if any. */ - string getNameValue() { result = getValue("name").(CompileTimeConstantExpr).getStringValue() } + string getNameValue() { + result = this.getValue("name").(CompileTimeConstantExpr).getStringValue() + } /** * Gets the bean definition in an XML file that the resource resolves to, if any. */ - SpringBean getSpringBean() { result.getQualifierValue() = getNameValue() } + SpringBean getSpringBean() { result.getQualifierValue() = this.getNameValue() } /** * Gets the Spring component that this qualifier resolves to, if any. */ - SpringComponent getSpringComponent() { result.getQualifierValue() = getNameValue() } + SpringComponent getSpringComponent() { result.getQualifierValue() = this.getNameValue() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll index e4b97375efd..df3799153e4 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll @@ -16,7 +16,7 @@ class SpringBean extends SpringXMLElement { SpringBean() { this.getName() = "bean" and // Do not capture Camel beans, which are different - not getNamespace().getURI() = "http://camel.apache.org/schema/spring" + not this.getNamespace().getURI() = "http://camel.apache.org/schema/spring" } override string toString() { result = this.getBeanIdentifier() } @@ -383,7 +383,7 @@ class SpringBean extends SpringXMLElement { // If a factory bean is specified, use that, otherwise use the current bean. ( if exists(this.getFactoryBeanName()) - then result.getDeclaringType() = getFactoryBean().getClass() + then result.getDeclaringType() = this.getFactoryBean().getClass() else ( result.getDeclaringType() = this.getClass() and // Must be static because we don't yet have an instance. @@ -400,9 +400,9 @@ class SpringBean extends SpringXMLElement { * the bean identifier if no qualifier is specified. */ string getQualifierValue() { - if exists(getQualifier()) - then result = getQualifier().getQualifierValue() - else result = getBeanIdentifier() + if exists(this.getQualifier()) + then result = this.getQualifier().getQualifierValue() + else result = this.getBeanIdentifier() } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll index e9549676e1f..2417002a412 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll @@ -35,7 +35,12 @@ class SpringBeanFile extends XMLFile { */ string getAProfileExpr() { result = - getBeansElement().getAttribute("profile").getValue().splitAt(",").splitAt(" ").splitAt(";") and + this.getBeansElement() + .getAttribute("profile") + .getValue() + .splitAt(",") + .splitAt(" ") + .splitAt(";") and result.length() != 0 } diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll index 568987114f2..6ee3e68d7f2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll @@ -20,7 +20,7 @@ class SpringXMLComponentScan extends SpringXMLElement { * Gets a profile expression for which this `component-scan` is enabled, or nothing if it is * applicable to any profile. */ - string getAProfileExpr() { result = getSpringBeanFile().getAProfileExpr() } + string getAProfileExpr() { result = this.getSpringBeanFile().getAProfileExpr() } } /** @@ -29,7 +29,7 @@ class SpringXMLComponentScan extends SpringXMLElement { */ class SpringComponentScan extends Annotation { SpringComponentScan() { - getType().hasQualifiedName("org.springframework.context.annotation", "ComponentScan") + this.getType().hasQualifiedName("org.springframework.context.annotation", "ComponentScan") } /** @@ -37,13 +37,13 @@ class SpringComponentScan extends Annotation { */ string getBasePackages() { // "value" and "basePackages" are synonymous, and are simple strings - result = getAValue("basePackages").(StringLiteral).getRepresentedString() + result = this.getAValue("basePackages").(StringLiteral).getRepresentedString() or - result = getAValue("value").(StringLiteral).getRepresentedString() + result = this.getAValue("value").(StringLiteral).getRepresentedString() or exists(TypeLiteral typeLiteral | // Base package classes are type literals whose package should be considered a base package. - typeLiteral = getAValue("basePackageClasses") + typeLiteral = this.getAValue("basePackageClasses") | result = typeLiteral.getReferencedType().(RefType).getPackage().getName() ) @@ -97,10 +97,10 @@ class SpringBasePackage extends string { class SpringComponentAnnotation extends AnnotationType { SpringComponentAnnotation() { // Component used directly as an annotation. - hasQualifiedName("org.springframework.stereotype", "Component") + this.hasQualifiedName("org.springframework.stereotype", "Component") or // Component can be used as a meta-annotation on other annotation types. - getAnAnnotation().getType() instanceof SpringComponentAnnotation + this.getAnAnnotation().getType() instanceof SpringComponentAnnotation } } @@ -117,20 +117,20 @@ private predicate isSpringXMLEnabled() { exists(SpringXMLElement springXMLElemen */ class SpringComponent extends RefType { SpringComponent() { - getAnAnnotation().getType() instanceof SpringComponentAnnotation and + this.getAnAnnotation().getType() instanceof SpringComponentAnnotation and not this instanceof AnnotationType } /** * Gets a qualifier used to distinguish when this class should be autowired into other classes. */ - SpringQualifierDefinitionAnnotation getQualifier() { result = getAnAnnotation() } + SpringQualifierDefinitionAnnotation getQualifier() { result = this.getAnAnnotation() } /** * Gets the `@Component` or equivalent annotation. */ Annotation getComponentAnnotation() { - result = getAnAnnotation() and + result = this.getAnAnnotation() and result.getType() instanceof SpringComponentAnnotation } @@ -138,13 +138,14 @@ class SpringComponent extends RefType { * Gets the bean identifier for this component. */ string getBeanIdentifier() { - if exists(getComponentAnnotation().getValue("value")) + if exists(this.getComponentAnnotation().getValue("value")) then // If the name has been specified in the component annotation, use that. - result = getComponentAnnotation().getValue("value").(CompileTimeConstantExpr).getStringValue() + result = + this.getComponentAnnotation().getValue("value").(CompileTimeConstantExpr).getStringValue() else // Otherwise use the name of the class, with the initial letter lower cased. - exists(string name | name = getName() | + exists(string name | name = this.getName() | result = name.charAt(0).toLowerCase() + name.suffix(1) ) } @@ -154,13 +155,13 @@ class SpringComponent extends RefType { * resolving autowiring on other classes. */ string getQualifierValue() { - if exists(getQualifier()) + if exists(this.getQualifier()) then // If given a qualifier, use the value specified. - result = getQualifier().getQualifierValue() + result = this.getQualifier().getQualifierValue() else // Otherwise, default to the bean identifier. - result = getBeanIdentifier() + result = this.getBeanIdentifier() } /** @@ -184,8 +185,8 @@ class SpringComponent extends RefType { this.getPackage().getName() = sbp ) and ( - not exists(getAProfileExpr()) or - getAProfileExpr().(SpringProfileExpr).isActive() + not exists(this.getAProfileExpr()) or + this.getAProfileExpr().(SpringProfileExpr).isActive() ) } @@ -195,7 +196,7 @@ class SpringComponent extends RefType { */ string getAProfileExpr() { exists(Annotation profileAnnotation | - profileAnnotation = getAnAnnotation() and + profileAnnotation = this.getAnAnnotation() and profileAnnotation .getType() .hasQualifiedName("org.springframework.context.annotation", "Profile") diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll index 6a3e9c9eb48..53829d02752 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -9,10 +9,10 @@ import SpringWebClient class SpringControllerAnnotation extends AnnotationType { SpringControllerAnnotation() { // `@Controller` used directly as an annotation. - hasQualifiedName("org.springframework.stereotype", "Controller") + this.hasQualifiedName("org.springframework.stereotype", "Controller") or // `@Controller` can be used as a meta-annotation on other annotation types. - getAnAnnotation().getType() instanceof SpringControllerAnnotation + this.getAnAnnotation().getType() instanceof SpringControllerAnnotation } } @@ -22,28 +22,30 @@ class SpringControllerAnnotation extends AnnotationType { * Rest controllers are the same as controllers, but imply the `@ResponseBody` annotation. */ class SpringRestControllerAnnotation extends SpringControllerAnnotation { - SpringRestControllerAnnotation() { hasName("RestController") } + SpringRestControllerAnnotation() { this.hasName("RestController") } } /** * A class annotated, directly or indirectly, as a Spring `Controller`. */ class SpringController extends Class { - SpringController() { getAnAnnotation().getType() instanceof SpringControllerAnnotation } + SpringController() { this.getAnAnnotation().getType() instanceof SpringControllerAnnotation } } /** * A class annotated, directly or indirectly, as a Spring `RestController`. */ class SpringRestController extends SpringController { - SpringRestController() { getAnAnnotation().getType() instanceof SpringRestControllerAnnotation } + SpringRestController() { + this.getAnAnnotation().getType() instanceof SpringRestControllerAnnotation + } } /** * A method on a Spring controller which is accessed by the Spring MVC framework. */ abstract class SpringControllerMethod extends Method { - SpringControllerMethod() { getDeclaringType() instanceof SpringController } + SpringControllerMethod() { this.getDeclaringType() instanceof SpringController } } /** @@ -83,10 +85,10 @@ class SpringInitBinderMethod extends SpringControllerMethod { class SpringRequestMappingAnnotationType extends AnnotationType { SpringRequestMappingAnnotationType() { // `@RequestMapping` used directly as an annotation. - hasQualifiedName("org.springframework.web.bind.annotation", "RequestMapping") + this.hasQualifiedName("org.springframework.web.bind.annotation", "RequestMapping") or // `@RequestMapping` can be used as a meta-annotation on other annotation types, e.g. GetMapping, PostMapping etc. - getAnAnnotation().getType() instanceof SpringRequestMappingAnnotationType + this.getAnAnnotation().getType() instanceof SpringRequestMappingAnnotationType } } @@ -96,7 +98,7 @@ class SpringRequestMappingAnnotationType extends AnnotationType { class SpringResponseBodyAnnotationType extends AnnotationType { SpringResponseBodyAnnotationType() { // `@ResponseBody` used directly as an annotation. - hasQualifiedName("org.springframework.web.bind.annotation", "ResponseBody") + this.hasQualifiedName("org.springframework.web.bind.annotation", "ResponseBody") } } @@ -129,7 +131,7 @@ class SpringRequestMappingMethod extends SpringControllerMethod { } /** Gets a request mapping parameter. */ - SpringRequestMappingParameter getARequestParameter() { result = getAParameter() } + SpringRequestMappingParameter getARequestParameter() { result = this.getAParameter() } /** Gets the "produces" @RequestMapping annotation value, if present. If an array is specified, gets the array. */ Expr getProducesExpr() { @@ -158,9 +160,9 @@ class SpringRequestMappingMethod extends SpringControllerMethod { /** Holds if this is considered an `@ResponseBody` method. */ predicate isResponseBody() { - getAnAnnotation().getType() instanceof SpringResponseBodyAnnotationType or - getDeclaringType().getAnAnnotation().getType() instanceof SpringResponseBodyAnnotationType or - getDeclaringType() instanceof SpringRestController + this.getAnAnnotation().getType() instanceof SpringResponseBodyAnnotationType or + this.getDeclaringType().getAnAnnotation().getType() instanceof SpringResponseBodyAnnotationType or + this.getDeclaringType() instanceof SpringRestController } } @@ -185,44 +187,50 @@ class SpringServletInputAnnotation extends Annotation { /** An annotation of the type `org.springframework.web.bind.annotation.ModelAttribute`. */ class SpringModelAttributeAnnotation extends Annotation { SpringModelAttributeAnnotation() { - getType().hasQualifiedName("org.springframework.web.bind.annotation", "ModelAttribute") + this.getType().hasQualifiedName("org.springframework.web.bind.annotation", "ModelAttribute") } } /** A parameter of a `SpringRequestMappingMethod`. */ class SpringRequestMappingParameter extends Parameter { - SpringRequestMappingParameter() { getCallable() instanceof SpringRequestMappingMethod } + SpringRequestMappingParameter() { this.getCallable() instanceof SpringRequestMappingMethod } /** Holds if the parameter should not be consider a direct source of taint. */ predicate isNotDirectlyTaintedInput() { - getType().(RefType).getAnAncestor() instanceof SpringWebRequest or - getType().(RefType).getAnAncestor() instanceof SpringNativeWebRequest or - getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet", "ServletRequest") or - getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet", "ServletResponse") or - getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet.http", "HttpSession") or - getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet.http", "PushBuilder") or - getType().(RefType).getAnAncestor().hasQualifiedName("java.security", "Principal") or - getType().(RefType).getAnAncestor().hasQualifiedName("org.springframework.http", "HttpMethod") or - getType().(RefType).getAnAncestor().hasQualifiedName("java.util", "Locale") or - getType().(RefType).getAnAncestor().hasQualifiedName("java.util", "TimeZone") or - getType().(RefType).getAnAncestor().hasQualifiedName("java.time", "ZoneId") or - getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "OutputStream") or - getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "Writer") or - getType() + this.getType().(RefType).getAnAncestor() instanceof SpringWebRequest or + this.getType().(RefType).getAnAncestor() instanceof SpringNativeWebRequest or + this.getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet", "ServletRequest") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet", "ServletResponse") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet.http", "HttpSession") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet.http", "PushBuilder") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("java.security", "Principal") or + this.getType() + .(RefType) + .getAnAncestor() + .hasQualifiedName("org.springframework.http", "HttpMethod") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("java.util", "Locale") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("java.util", "TimeZone") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("java.time", "ZoneId") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "OutputStream") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "Writer") or + this.getType() .(RefType) .getAnAncestor() .hasQualifiedName("org.springframework.web.servlet.mvc.support", "RedirectAttributes") or // Also covers BindingResult. Note, you can access the field value through this interface, which should be considered tainted - getType().(RefType).getAnAncestor().hasQualifiedName("org.springframework.validation", "Errors") or - getType() + this.getType() + .(RefType) + .getAnAncestor() + .hasQualifiedName("org.springframework.validation", "Errors") or + this.getType() .(RefType) .getAnAncestor() .hasQualifiedName("org.springframework.web.bind.support", "SessionStatus") or - getType() + this.getType() .(RefType) .getAnAncestor() .hasQualifiedName("org.springframework.web.util", "UriComponentsBuilder") or - getType() + this.getType() .(RefType) .getAnAncestor() .hasQualifiedName("org.springframework.data.domain", "Pageable") or @@ -231,13 +239,13 @@ class SpringRequestMappingParameter extends Parameter { private predicate isExplicitlyTaintedInput() { // InputStream or Reader parameters allow access to the body of a request - getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "InputStream") or - getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "Reader") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "InputStream") or + this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "Reader") or // The SpringServletInputAnnotations allow access to the URI, request parameters, cookie values and the body of the request this.getAnAnnotation() instanceof SpringServletInputAnnotation or // HttpEntity is like @RequestBody, but with a wrapper including the headers // TODO model unwrapping aspects - getType().(RefType).getASourceSupertype*() instanceof SpringHttpEntity or + this.getType().(RefType).getASourceSupertype*() instanceof SpringHttpEntity or this.getAnAnnotation() .getType() .hasQualifiedName("org.springframework.web.bind.annotation", "RequestAttribute") or @@ -249,35 +257,35 @@ class SpringRequestMappingParameter extends Parameter { private predicate isImplicitRequestParam() { // Any parameter which is not explicitly handled, is consider to be an `@RequestParam`, if // it is a simple bean property - not isNotDirectlyTaintedInput() and - not isExplicitlyTaintedInput() and + not this.isNotDirectlyTaintedInput() and + not this.isExplicitlyTaintedInput() and ( - getType() instanceof PrimitiveType or - getType() instanceof TypeString + this.getType() instanceof PrimitiveType or + this.getType() instanceof TypeString ) } private predicate isImplicitModelAttribute() { // Any parameter which is not explicitly handled, is consider to be an `@ModelAttribute`, if // it is not an implicit request param - not isNotDirectlyTaintedInput() and - not isExplicitlyTaintedInput() and - not isImplicitRequestParam() + not this.isNotDirectlyTaintedInput() and + not this.isExplicitlyTaintedInput() and + not this.isImplicitRequestParam() } /** Holds if this is an explicit or implicit `@ModelAttribute` parameter. */ predicate isModelAttribute() { - isImplicitModelAttribute() or - getAnAnnotation() instanceof SpringModelAttributeAnnotation + this.isImplicitModelAttribute() or + this.getAnAnnotation() instanceof SpringModelAttributeAnnotation } /** Holds if the input is tainted. */ predicate isTaintedInput() { - isExplicitlyTaintedInput() + this.isExplicitlyTaintedInput() or // Any parameter which is not explicitly identified, is consider to be an `@RequestParam`, if // it is a simple bean property) or a @ModelAttribute if not - not isNotDirectlyTaintedInput() + not this.isNotDirectlyTaintedInput() } } @@ -286,7 +294,7 @@ class SpringRequestMappingParameter extends Parameter { * the method, which will be used to render the response e.g. as a JSP file. */ abstract class SpringModel extends Parameter { - SpringModel() { getCallable() instanceof SpringRequestMappingMethod } + SpringModel() { this.getCallable() instanceof SpringRequestMappingMethod } /** * Types for which instances are placed inside the model. @@ -298,11 +306,11 @@ abstract class SpringModel extends Parameter { * A `java.util.Map` can be accepted as the model parameter for a Spring `RequestMapping` method. */ class SpringModelPlainMap extends SpringModel { - SpringModelPlainMap() { getType() instanceof MapType } + SpringModelPlainMap() { this.getType() instanceof MapType } override RefType getATypeInModel() { exists(MethodAccess methodCall | - methodCall.getQualifier() = getAnAccess() and + methodCall.getQualifier() = this.getAnAccess() and methodCall.getCallee().hasName("put") | result = methodCall.getArgument(1).getType() @@ -316,13 +324,13 @@ class SpringModelPlainMap extends SpringModel { */ class SpringModelModel extends SpringModel { SpringModelModel() { - getType().(RefType).hasQualifiedName("org.springframework.ui", "Model") or - getType().(RefType).hasQualifiedName("org.springframework.ui", "ModelMap") + this.getType().(RefType).hasQualifiedName("org.springframework.ui", "Model") or + this.getType().(RefType).hasQualifiedName("org.springframework.ui", "ModelMap") } override RefType getATypeInModel() { exists(MethodAccess methodCall | - methodCall.getQualifier() = getAnAccess() and + methodCall.getQualifier() = this.getAnAccess() and methodCall.getCallee().hasName("addAttribute") | result = methodCall.getArgument(methodCall.getNumArgument() - 1).getType() diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringExpression.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringExpression.qll index 0b79587c551..155e11544fc 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringExpression.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringExpression.qll @@ -18,7 +18,7 @@ class ExpressionEvaluationMethod extends Method { * The class `org.springframework.expression.ExpressionParser`. */ class ExpressionParser extends RefType { - ExpressionParser() { hasQualifiedName("org.springframework.expression", "ExpressionParser") } + ExpressionParser() { this.hasQualifiedName("org.springframework.expression", "ExpressionParser") } } /** @@ -26,7 +26,7 @@ class ExpressionParser extends RefType { */ class SimpleEvaluationContextBuilder extends RefType { SimpleEvaluationContextBuilder() { - hasQualifiedName("org.springframework.expression.spel.support", + this.hasQualifiedName("org.springframework.expression.spel.support", "SimpleEvaluationContext$Builder") } } @@ -35,7 +35,7 @@ class SimpleEvaluationContextBuilder extends RefType { * The class `org.springframework.expression.Expression`. */ class Expression extends RefType { - Expression() { hasQualifiedName("org.springframework.expression", "Expression") } + Expression() { this.hasQualifiedName("org.springframework.expression", "Expression") } } /** @@ -43,6 +43,6 @@ class Expression extends RefType { */ class SimpleEvaluationContext extends RefType { SimpleEvaluationContext() { - hasQualifiedName("org.springframework.expression.spel.support", "SimpleEvaluationContext") + this.hasQualifiedName("org.springframework.expression.spel.support", "SimpleEvaluationContext") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringFlex.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringFlex.qll index 30ca9db14f7..7ed0f78fd37 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringFlex.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringFlex.qll @@ -16,22 +16,22 @@ class SpringRemotingDestination extends SpringXMLElement { * Gets the bean that this remoting destination refers to. */ SpringBean getSpringBean() { - result = getParent() or - result.getBeanIdentifier() = getAttribute("ref").getValue() + result = this.getParent() or + result.getBeanIdentifier() = this.getAttribute("ref").getValue() } /** * Methods that are specifically included when the bean is exposed as a remote destination. */ string getAnIncludeMethod() { - result = getAttribute("include-methods").getValue().splitAt(",").trim() + result = this.getAttribute("include-methods").getValue().splitAt(",").trim() } /** * Methods that are specifically excluded when the bean is exposed as a remote destination. */ string getAnExcludeMethod() { - result = getAttribute("exclude-methods").getValue().splitAt(",").trim() + result = this.getAttribute("exclude-methods").getValue().splitAt(",").trim() } } @@ -44,7 +44,7 @@ class SpringRemotingDestinationClass extends Class { this = remotingDestination.getSpringBean().getClass() ) or - hasAnnotation("org.springframework.flex.remoting", "RemotingDestination") and + this.hasAnnotation("org.springframework.flex.remoting", "RemotingDestination") and // Must either be a live bean, or a live component. ( this.(SpringComponent).isLive() or @@ -66,11 +66,11 @@ class SpringRemotingDestinationClass extends Class { * basis, only those methods that are not marked as excluded are exported. */ predicate isIncluding() { - exists(Method m | m = getAMethod() | + exists(Method m | m = this.getAMethod() | m.hasAnnotation("org.springframework.flex.remoting", "RemotingInclude") ) or - exists(getRemotingDestinationXML().getAnIncludeMethod()) + exists(this.getRemotingDestinationXML().getAnIncludeMethod()) } /** @@ -78,13 +78,13 @@ class SpringRemotingDestinationClass extends Class { */ Method getARemotingMethod() { result = this.getAMethod() and - if isIncluding() + if this.isIncluding() then result.hasAnnotation("org.springframework.flex.remoting", "RemotingInclude") or - result.getName() = getRemotingDestinationXML().getAnIncludeMethod() + result.getName() = this.getRemotingDestinationXML().getAnIncludeMethod() else ( not result.hasAnnotation("org.springframework.flex.remoting", "RemotingExclude") and - not result.getName() = getRemotingDestinationXML().getAnExcludeMethod() + not result.getName() = this.getRemotingDestinationXML().getAnExcludeMethod() ) } } diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringProfile.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringProfile.qll index 17fedacdefe..7f284b0771f 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringProfile.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringProfile.qll @@ -26,10 +26,10 @@ class SpringProfileExpr extends string { */ predicate isActive() { ( - getProfile() instanceof AlwaysEnabledSpringProfile or - getProfile() instanceof SometimesEnabledSpringProfile + this.getProfile() instanceof AlwaysEnabledSpringProfile or + this.getProfile() instanceof SometimesEnabledSpringProfile ) and - not getProfile() instanceof NeverEnabledSpringProfile + not this.getProfile() instanceof NeverEnabledSpringProfile } } @@ -48,7 +48,7 @@ class NotSpringProfileExpr extends SpringProfileExpr { * This profile expression is active if it can ever be evaluated to true, according to our * knowledge of which profiles are sometimes/never/always enabled. */ - override predicate isActive() { not getProfile() instanceof AlwaysEnabledSpringProfile } + override predicate isActive() { not this.getProfile() instanceof AlwaysEnabledSpringProfile } } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringWeb.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringWeb.qll index dd8e660fd26..b91c6de4933 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringWeb.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringWeb.qll @@ -25,7 +25,7 @@ class SpringNativeWebRequest extends Class { */ class ModelAndView extends Class { ModelAndView() { - hasQualifiedName(["org.springframework.web.servlet", "org.springframework.web.portlet"], + this.hasQualifiedName(["org.springframework.web.servlet", "org.springframework.web.portlet"], "ModelAndView") } } @@ -33,7 +33,7 @@ class ModelAndView extends Class { /** A call to the Spring `ModelAndView.setViewName` method. */ class SpringModelAndViewSetViewNameCall extends MethodAccess { SpringModelAndViewSetViewNameCall() { - getMethod().getDeclaringType() instanceof ModelAndView and - getMethod().hasName("setViewName") + this.getMethod().getDeclaringType() instanceof ModelAndView and + this.getMethod().hasName("setViewName") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsActions.qll b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsActions.qll index 0edfaa3711c..775eb3e2b6f 100644 --- a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsActions.qll +++ b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsActions.qll @@ -86,7 +86,7 @@ class Struts2ActionClass extends Class { * Holds if this action class extends the preparable interface. */ predicate isPreparable() { - getAnAncestor().hasQualifiedName("com.opensymphony.xwork2", "Preparable") + this.getAnAncestor().hasQualifiedName("com.opensymphony.xwork2", "Preparable") } /** @@ -96,10 +96,10 @@ class Struts2ActionClass extends Class { * methods only exist if the class `isPreparable()`. */ Method getPrepareMethod() { - isPreparable() and + this.isPreparable() and exists(Struts2ActionMethod actionMethod | - actionMethod = getActionMethod() and - inherits(result) and + actionMethod = this.getActionMethod() and + this.inherits(result) and result .hasName("prepare" + actionMethod.getName().charAt(0).toUpperCase() + actionMethod.getName().suffix(1)) diff --git a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsAnnotations.qll b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsAnnotations.qll index c024f4d6b16..5ee8f25724e 100644 --- a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsAnnotations.qll +++ b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsAnnotations.qll @@ -16,7 +16,7 @@ class StrutsActionAnnotation extends StrutsAnnotation { StrutsActionAnnotation() { this.getType().hasName("Action") } Callable getActionCallable() { - result = getAnnotatedElement() + result = this.getAnnotatedElement() or exists(StrutsActionsAnnotation actions | this = actions.getAnAction() | result = actions.getAnnotatedElement() diff --git a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll index b6b62b72cef..35faa0e55ff 100644 --- a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll +++ b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll @@ -8,8 +8,8 @@ import semmle.code.xml.MavenPom */ library class Struts2ConventionDependency extends Dependency { Struts2ConventionDependency() { - getGroup().getValue() = "org.apache.struts" and - getArtifact().getValue() = "struts2-convention-plugin" + this.getGroup().getValue() = "org.apache.struts" and + this.getArtifact().getValue() = "struts2-convention-plugin" } } @@ -100,7 +100,7 @@ class Struts2ConventionActionClass extends Class { isStrutsConventionPluginUsed(this) and exists(string ancestorPackage | // Has an ancestor package on the whitelist - ancestorPackage = getPackage().getName().splitAt(".") and + ancestorPackage = this.getPackage().getName().splitAt(".") and ( ancestorPackage = "struts" or ancestorPackage = "struts2" or @@ -109,7 +109,7 @@ class Struts2ConventionActionClass extends Class { ) ) and ( - getName().matches("%" + getConventionSuffix(this)) or + this.getName().matches("%" + getConventionSuffix(this)) or this.getAnAncestor().hasQualifiedName("com.opensymphony.xwork2", "Action") ) } diff --git a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsXML.qll b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsXML.qll index 35340e890cf..8e69c5d9a83 100644 --- a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsXML.qll +++ b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsXML.qll @@ -31,18 +31,18 @@ abstract class StrutsXMLFile extends XMLFile { /** * Gets a transitively included file. */ - StrutsXMLFile getAnIncludedFile() { result = getADirectlyIncludedFile*() } + StrutsXMLFile getAnIncludedFile() { result = this.getADirectlyIncludedFile*() } /** * Gets a `<constant>` defined in this file, or an included file. */ - StrutsXMLConstant getAConstant() { result.getFile() = getAnIncludedFile() } + StrutsXMLConstant getAConstant() { result.getFile() = this.getAnIncludedFile() } /** * Gets the value of the constant with the given `name`. */ string getConstantValue(string name) { - exists(StrutsXMLConstant constant | constant = getAConstant() | + exists(StrutsXMLConstant constant | constant = this.getAConstant() | constant.getConstantName() = name and result = constant.getConstantValue() ) @@ -56,8 +56,8 @@ abstract class StrutsXMLFile extends XMLFile { */ class StrutsRootXMLFile extends StrutsXMLFile { StrutsRootXMLFile() { - getBaseName() = "struts.xml" or - getBaseName() = "struts-plugin.xml" + this.getBaseName() = "struts.xml" or + this.getBaseName() = "struts-plugin.xml" } } @@ -73,7 +73,7 @@ class StrutsIncludedXMLFile extends StrutsXMLFile { */ class StrutsFolder extends Folder { StrutsFolder() { - exists(Container c | c = getAChildContainer() | + exists(Container c | c = this.getAChildContainer() | c instanceof StrutsFolder or c instanceof StrutsXMLFile ) @@ -82,14 +82,14 @@ class StrutsFolder extends Folder { /** * Holds if this folder has a unique Struts root configuration file. */ - predicate isUnique() { count(getAStrutsRootFile()) = 1 } + predicate isUnique() { count(this.getAStrutsRootFile()) = 1 } /** * Gets a struts root configuration that applies to this folder. */ StrutsRootXMLFile getAStrutsRootFile() { - result = getAChildContainer() or - result = getAChildContainer().(StrutsFolder).getAStrutsRootFile() + result = this.getAChildContainer() or + result = this.getAChildContainer().(StrutsFolder).getAStrutsRootFile() } } @@ -102,7 +102,7 @@ class StrutsXMLElement extends XMLElement { /** * Gets the value for this element, with leading and trailing whitespace trimmed. */ - string getValue() { result = allCharactersString().trim() } + string getValue() { result = this.allCharactersString().trim() } } /** @@ -121,7 +121,7 @@ class StrutsXMLInclude extends StrutsXMLElement { * potentially be included. */ XMLFile getIncludedFile() { - exists(string file | file = getAttribute("file").getValue() | + exists(string file | file = this.getAttribute("file").getValue() | result.getAbsolutePath().matches("%" + escapeForMatch(file)) ) } @@ -157,10 +157,10 @@ class StrutsXMLAction extends StrutsXMLElement { * Gets the `Class` that is referenced by this Struts action. */ Class getActionClass() { - strutsWildcardMatching(result.getQualifiedName(), getAttribute("class").getValue()) + strutsWildcardMatching(result.getQualifiedName(), this.getAttribute("class").getValue()) } - string getMethodName() { result = getAttribute("method").getValue() } + string getMethodName() { result = this.getAttribute("method").getValue() } /** * Gets the `Method` which is referenced by this action. @@ -168,9 +168,9 @@ class StrutsXMLAction extends StrutsXMLElement { * If no method is specified in the attributes of this element, a method named `execute` is chosen. */ Method getActionMethod() { - getActionClass().inherits(result) and - if exists(getMethodName()) - then strutsWildcardMatching(result.getName(), getMethodName()) + this.getActionClass().inherits(result) and + if exists(this.getMethodName()) + then strutsWildcardMatching(result.getName(), this.getMethodName()) else result.hasName("execute") } } @@ -179,9 +179,9 @@ class StrutsXMLAction extends StrutsXMLElement { * A `<constant>` property, representing a configuration parameter to struts. */ class StrutsXMLConstant extends StrutsXMLElement { - StrutsXMLConstant() { getName() = "constant" } + StrutsXMLConstant() { this.getName() = "constant" } - string getConstantName() { result = getAttribute("name").getValue() } + string getConstantName() { result = this.getAttribute("name").getValue() } - string getConstantValue() { result = getAttribute("value").getValue() } + string getConstantValue() { result = this.getAttribute("value").getValue() } } diff --git a/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll b/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll index 79c65dd1bef..ce4e52c8eec 100755 --- a/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll +++ b/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll @@ -137,7 +137,9 @@ class MetricRefType extends RefType, MetricElement { /** Holds if the specified callable should be included in the CK cohesion computation. */ predicate includeInLackOfCohesionCK(Callable c) { not c instanceof TestMethod and - exists(Field f | c.getDeclaringType() = this and c.accesses(f) and relevantFieldForCohesion(f)) + exists(Field f | + c.getDeclaringType() = this and c.accesses(f) and this.relevantFieldForCohesion(f) + ) } pragma[noopt] @@ -152,8 +154,8 @@ class MetricRefType extends RefType, MetricElement { /** Holds if a (non-ignored) callable reads a field relevant for cohesion. */ private predicate relevantCallableAndFieldCK(Callable m, Field f) { - includeInLackOfCohesionCK(m) and - relevantFieldForCohesion(f) and + this.includeInLackOfCohesionCK(m) and + this.relevantFieldForCohesion(f) and m.accesses(f) and m.getDeclaringType() = this } @@ -180,12 +182,12 @@ class MetricRefType extends RefType, MetricElement { */ float getLackOfCohesionCK() { exists(int callables, int linked, float n | - callables = count(Callable m | includeInLackOfCohesionCK(m)) and + callables = count(Callable m | this.includeInLackOfCohesionCK(m)) and linked = count(Callable m1, Callable m2 | exists(Field f | - relevantCallableAndFieldCK(m1, f) and - relevantCallableAndFieldCK(m2, f) and + this.relevantCallableAndFieldCK(m1, f) and + this.relevantCallableAndFieldCK(m2, f) and m1 != m2 ) ) and @@ -207,7 +209,7 @@ class MetricRefType extends RefType, MetricElement { int getADepth() { this.hasQualifiedName("java.lang", "Object") and result = 0 or - not cyclic() and result = this.getASupertype().(MetricRefType).getADepth() + 1 + not this.cyclic() and result = this.getASupertype().(MetricRefType).getADepth() + 1 } /** @@ -229,10 +231,10 @@ class MetricRefType extends RefType, MetricElement { int getADepth(RefType reference) { this = reference and result = 0 or - not cyclic() and result = this.getASupertype().(MetricRefType).getADepth(reference) + 1 + not this.cyclic() and result = this.getASupertype().(MetricRefType).getADepth(reference) + 1 } - private predicate cyclic() { getASupertype+() = this } + private predicate cyclic() { this.getASupertype+() = this } /** Gets the depth of inheritance metric relative to the specified reference type. */ int getInheritanceDepth(RefType reference) { result = max(this.getADepth(reference)) } diff --git a/java/ql/lib/semmle/code/java/security/CommandArguments.qll b/java/ql/lib/semmle/code/java/security/CommandArguments.qll index c0934e49411..d8ec58e623e 100644 --- a/java/ql/lib/semmle/code/java/security/CommandArguments.qll +++ b/java/ql/lib/semmle/code/java/security/CommandArguments.qll @@ -69,10 +69,10 @@ private class CommandArgumentList extends SsaExplicitUpdate { /** Gets a use of the variable for which the list could be empty. */ private RValue getAUseBeforeFirstAdd() { - result = getAFirstUse() + result = this.getAFirstUse() or exists(RValue mid | - mid = getAUseBeforeFirstAdd() and + mid = this.getAUseBeforeFirstAdd() and adjacentUseUse(mid, result) and not exists(MethodAccess ma | mid = ma.getQualifier() and @@ -85,25 +85,25 @@ private class CommandArgumentList extends SsaExplicitUpdate { * Gets an addition to this list, i.e. a call to an `add` or `addAll` method. */ MethodAccess getAnAdd() { - result.getQualifier() = getAUse() and + result.getQualifier() = this.getAUse() and result.getMethod().getName().matches("add%") } /** Gets an addition to this list which could be its first element. */ MethodAccess getAFirstAdd() { - result = getAnAdd() and - result.getQualifier() = getAUseBeforeFirstAdd() + result = this.getAnAdd() and + result.getQualifier() = this.getAUseBeforeFirstAdd() } /** Gets an addition to this list which is not the first element. */ MethodAccess getASubsequentAdd() { - result = getAnAdd() and - not result = getAFirstAdd() + result = this.getAnAdd() and + not result = this.getAFirstAdd() } /** Holds if the first element of this list is a shell command. */ predicate isShell() { - exists(MethodAccess ma | ma = getAFirstAdd() and isShell(ma.getArgument(0))) + exists(MethodAccess ma | ma = this.getAFirstAdd() and isShell(ma.getArgument(0))) } } @@ -122,7 +122,7 @@ private predicate arrayLValue(ArrayAccess acc) { exists(Assignment a | a.getDest private class CommandArgumentArray extends SsaExplicitUpdate { CommandArgumentArray() { this.getSourceVariable().getType() instanceof ArrayOfStringType and - forall(ArrayAccess a | a.getArray() = getAUse() and arrayLValue(a) | + forall(ArrayAccess a | a.getArray() = this.getAUse() and arrayLValue(a) | a.getIndexExpr() instanceof CompileTimeConstantExpr ) } @@ -139,7 +139,7 @@ private class CommandArgumentArray extends SsaExplicitUpdate { } /** Gets an expression that is written to the given index of this array. */ - Expr getAWrite(int index) { result = getAWrite(index, _) } + Expr getAWrite(int index) { result = this.getAWrite(index, _) } } /** @@ -147,20 +147,20 @@ private class CommandArgumentArray extends SsaExplicitUpdate { */ private class CommandArgArrayImmutableFirst extends CommandArgumentArray { CommandArgArrayImmutableFirst() { - (exists(getAWrite(0)) or exists(firstElementOf(this.getDefiningExpr()))) and + (exists(this.getAWrite(0)) or exists(firstElementOf(this.getDefiningExpr()))) and forall(RValue use | exists(this.getAWrite(0, use)) | use = this.getAFirstUse()) } /** Gets the first element of this array. */ Expr getFirstElement() { - result = getAWrite(0) + result = this.getAWrite(0) or - not exists(getAWrite(0)) and - result = firstElementOf(getDefiningExpr()) + not exists(this.getAWrite(0)) and + result = firstElementOf(this.getDefiningExpr()) } /** Holds if the first element of this array is a shell command. */ - predicate isShell() { isShell(getFirstElement()) } + predicate isShell() { isShell(this.getFirstElement()) } } /** Gets the first element of an imutable array of strings */ diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index 3e65375d91f..8f4cef23ee6 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -18,7 +18,7 @@ class X509TrustManager extends RefType { } class HttpsURLConnection extends RefType { - HttpsURLConnection() { hasQualifiedName("javax.net.ssl", "HttpsURLConnection") } + HttpsURLConnection() { this.hasQualifiedName("javax.net.ssl", "HttpsURLConnection") } } class SSLSocketFactory extends RefType { @@ -26,16 +26,16 @@ class SSLSocketFactory extends RefType { } class SSLContext extends RefType { - SSLContext() { hasQualifiedName("javax.net.ssl", "SSLContext") } + SSLContext() { this.hasQualifiedName("javax.net.ssl", "SSLContext") } } /** The `javax.net.ssl.SSLSession` class. */ class SSLSession extends RefType { - SSLSession() { hasQualifiedName("javax.net.ssl", "SSLSession") } + SSLSession() { this.hasQualifiedName("javax.net.ssl", "SSLSession") } } class HostnameVerifier extends RefType { - HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") } + HostnameVerifier() { this.hasQualifiedName("javax.net.ssl", "HostnameVerifier") } } /** The Java class `javax.crypto.KeyGenerator`. */ @@ -51,10 +51,10 @@ class KeyPairGenerator extends RefType { /** The `verify` method of the class `javax.net.ssl.HostnameVerifier`. */ class HostnameVerifierVerify extends Method { HostnameVerifierVerify() { - hasName("verify") and - getDeclaringType().getASupertype*() instanceof HostnameVerifier and - getParameterType(0) instanceof TypeString and - getParameterType(1) instanceof SSLSession + this.hasName("verify") and + this.getDeclaringType().getASupertype*() instanceof HostnameVerifier and + this.getParameterType(0) instanceof TypeString and + this.getParameterType(1) instanceof SSLSession } } @@ -67,37 +67,37 @@ class TrustManagerCheckMethod extends Method { class CreateSocket extends Method { CreateSocket() { - hasName("createSocket") and - getDeclaringType() instanceof SSLSocketFactory + this.hasName("createSocket") and + this.getDeclaringType() instanceof SSLSocketFactory } } class GetSocketFactory extends Method { GetSocketFactory() { - hasName("getSocketFactory") and - getDeclaringType() instanceof SSLContext + this.hasName("getSocketFactory") and + this.getDeclaringType() instanceof SSLContext } } class SetConnectionFactoryMethod extends Method { SetConnectionFactoryMethod() { - hasName("setSSLSocketFactory") and - getDeclaringType().getASupertype*() instanceof HttpsURLConnection + this.hasName("setSSLSocketFactory") and + this.getDeclaringType().getASupertype*() instanceof HttpsURLConnection } } class SetHostnameVerifierMethod extends Method { SetHostnameVerifierMethod() { - hasName("setHostnameVerifier") and - getDeclaringType().getASupertype*() instanceof HttpsURLConnection + this.hasName("setHostnameVerifier") and + this.getDeclaringType().getASupertype*() instanceof HttpsURLConnection } } /** The `setDefaultHostnameVerifier` method of the class `javax.net.ssl.HttpsURLConnection`. */ class SetDefaultHostnameVerifierMethod extends Method { SetDefaultHostnameVerifierMethod() { - hasName("setDefaultHostnameVerifier") and - getDeclaringType().getASupertype*() instanceof HttpsURLConnection + this.hasName("setDefaultHostnameVerifier") and + this.getDeclaringType().getASupertype*() instanceof HttpsURLConnection } } diff --git a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll index f2675645a6a..3b264bd0283 100644 --- a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll +++ b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll @@ -17,38 +17,38 @@ private class DefaultSafeExternalAPIMethod extends SafeExternalAPIMethod { DefaultSafeExternalAPIMethod() { this instanceof EqualsMethod or - getName().regexpMatch("size|length|compareTo|getClass|lastIndexOf") + this.getName().regexpMatch("size|length|compareTo|getClass|lastIndexOf") or this.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "Validate") or - getQualifiedName() = "Objects.equals" + this.getQualifiedName() = "Objects.equals" or - getDeclaringType() instanceof TypeString and getName() = "equals" + this.getDeclaringType() instanceof TypeString and this.getName() = "equals" or - getDeclaringType().hasQualifiedName("com.google.common.base", "Preconditions") + this.getDeclaringType().hasQualifiedName("com.google.common.base", "Preconditions") or - getDeclaringType().getPackage().getName().matches("org.junit%") + this.getDeclaringType().getPackage().getName().matches("org.junit%") or - getDeclaringType().hasQualifiedName("com.google.common.base", "Strings") and - getName() = "isNullOrEmpty" + this.getDeclaringType().hasQualifiedName("com.google.common.base", "Strings") and + this.getName() = "isNullOrEmpty" or - getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "StringUtils") and - getName() = "isNotEmpty" + this.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "StringUtils") and + this.getName() = "isNotEmpty" or - getDeclaringType().hasQualifiedName("java.lang", "Character") and - getName() = "isDigit" + this.getDeclaringType().hasQualifiedName("java.lang", "Character") and + this.getName() = "isDigit" or - getDeclaringType().hasQualifiedName("java.lang", "String") and - getName().regexpMatch("equalsIgnoreCase|regionMatches") + this.getDeclaringType().hasQualifiedName("java.lang", "String") and + this.getName().regexpMatch("equalsIgnoreCase|regionMatches") or - getDeclaringType().hasQualifiedName("java.lang", "Boolean") and - getName() = "parseBoolean" + this.getDeclaringType().hasQualifiedName("java.lang", "Boolean") and + this.getName() = "parseBoolean" or - getDeclaringType().hasQualifiedName("org.apache.commons.io", "IOUtils") and - getName() = "closeQuietly" + this.getDeclaringType().hasQualifiedName("org.apache.commons.io", "IOUtils") and + this.getName() = "closeQuietly" or - getDeclaringType().hasQualifiedName("org.springframework.util", "StringUtils") and - getName().regexpMatch("hasText|isEmpty") + this.getDeclaringType().hasQualifiedName("org.springframework.util", "StringUtils") and + this.getName().regexpMatch("hasText|isEmpty") } } @@ -90,7 +90,8 @@ class ExternalAPIDataNode extends DataFlow::Node { /** Gets the description of the method being called. */ string getMethodDescription() { - result = getMethod().getDeclaringType().getPackage() + "." + getMethod().getQualifiedName() + result = + this.getMethod().getDeclaringType().getPackage() + "." + this.getMethod().getQualifiedName() } } @@ -130,7 +131,7 @@ class ExternalAPIUsedWithUntrustedData extends TExternalAPI { /** Gets the number of untrusted sources used with this external API. */ int getNumberOfUntrustedSources() { - result = count(getUntrustedDataNode().getAnUntrustedSource()) + result = count(this.getUntrustedDataNode().getAnUntrustedSource()) } /** Gets a textual representation of this element. */ diff --git a/java/ql/lib/semmle/code/java/security/JexlInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/JexlInjectionQuery.qll index bfb77715569..9e70be5c12f 100644 --- a/java/ql/lib/semmle/code/java/security/JexlInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/JexlInjectionQuery.qll @@ -168,7 +168,9 @@ private predicate createJexlEngineStep(DataFlow::Node fromNode, DataFlow::Node t * A method that creates a JEXL script. */ private class CreateJexlScriptMethod extends Method { - CreateJexlScriptMethod() { getDeclaringType() instanceof JexlEngine and hasName("createScript") } + CreateJexlScriptMethod() { + this.getDeclaringType() instanceof JexlEngine and this.hasName("createScript") + } } /** @@ -176,8 +178,11 @@ private class CreateJexlScriptMethod extends Method { */ private class CreateJexlTemplateMethod extends Method { CreateJexlTemplateMethod() { - (getDeclaringType() instanceof JxltEngine or getDeclaringType() instanceof UnifiedJexl) and - hasName("createTemplate") + ( + this.getDeclaringType() instanceof JxltEngine or + this.getDeclaringType() instanceof UnifiedJexl + ) and + this.hasName("createTemplate") } } @@ -186,40 +191,42 @@ private class CreateJexlTemplateMethod extends Method { */ private class CreateJexlExpressionMethod extends Method { CreateJexlExpressionMethod() { - (getDeclaringType() instanceof JexlEngine or getDeclaringType() instanceof JxltEngine) and - hasName("createExpression") + (this.getDeclaringType() instanceof JexlEngine or this.getDeclaringType() instanceof JxltEngine) and + this.hasName("createExpression") or - getDeclaringType() instanceof UnifiedJexl and hasName("parse") + this.getDeclaringType() instanceof UnifiedJexl and this.hasName("parse") } } private class JexlRefType extends RefType { - JexlRefType() { getPackage().hasName(["org.apache.commons.jexl2", "org.apache.commons.jexl3"]) } + JexlRefType() { + this.getPackage().hasName(["org.apache.commons.jexl2", "org.apache.commons.jexl3"]) + } } private class JexlBuilder extends JexlRefType { - JexlBuilder() { hasName("JexlBuilder") } + JexlBuilder() { this.hasName("JexlBuilder") } } private class JexlEngine extends JexlRefType { - JexlEngine() { hasName("JexlEngine") } + JexlEngine() { this.hasName("JexlEngine") } } private class JxltEngine extends JexlRefType { - JxltEngine() { hasName("JxltEngine") } + JxltEngine() { this.hasName("JxltEngine") } } private class UnifiedJexl extends JexlRefType { - UnifiedJexl() { hasName("UnifiedJEXL") } + UnifiedJexl() { this.hasName("UnifiedJEXL") } } private class JexlUberspect extends Interface { JexlUberspect() { - hasQualifiedName("org.apache.commons.jexl2.introspection", "Uberspect") or - hasQualifiedName("org.apache.commons.jexl3.introspection", "JexlUberspect") + this.hasQualifiedName("org.apache.commons.jexl2.introspection", "Uberspect") or + this.hasQualifiedName("org.apache.commons.jexl3.introspection", "JexlUberspect") } } private class Reader extends RefType { - Reader() { hasQualifiedName("java.io", "Reader") } + Reader() { this.hasQualifiedName("java.io", "Reader") } } diff --git a/java/ql/lib/semmle/code/java/security/MvelInjection.qll b/java/ql/lib/semmle/code/java/security/MvelInjection.qll index 984641fbd18..a75f582b72a 100644 --- a/java/ql/lib/semmle/code/java/security/MvelInjection.qll +++ b/java/ql/lib/semmle/code/java/security/MvelInjection.qll @@ -183,8 +183,8 @@ private predicate templateCompileStep(DataFlow::Node node1, DataFlow::Node node2 */ private class MvelScriptEngineCompilationMethod extends Method { MvelScriptEngineCompilationMethod() { - getDeclaringType() instanceof MvelScriptEngine and - hasName(["compile", "compiledScript"]) + this.getDeclaringType() instanceof MvelScriptEngine and + this.hasName(["compile", "compiledScript"]) } } @@ -193,8 +193,8 @@ private class MvelScriptEngineCompilationMethod extends Method { */ private class TemplateCompilerCompileMethod extends Method { TemplateCompilerCompileMethod() { - getDeclaringType() instanceof TemplateCompiler and - hasName("compile") + this.getDeclaringType() instanceof TemplateCompiler and + this.hasName("compile") } } @@ -203,31 +203,31 @@ private class TemplateCompilerCompileMethod extends Method { */ private class TemplateCompilerCompileTemplateMethod extends Method { TemplateCompilerCompileTemplateMethod() { - getDeclaringType() instanceof TemplateCompiler and - hasName("compileTemplate") + this.getDeclaringType() instanceof TemplateCompiler and + this.hasName("compileTemplate") } } private class MVEL extends RefType { - MVEL() { hasQualifiedName("org.mvel2", "MVEL") } + MVEL() { this.hasQualifiedName("org.mvel2", "MVEL") } } private class ExpressionCompiler extends RefType { - ExpressionCompiler() { hasQualifiedName("org.mvel2.compiler", "ExpressionCompiler") } + ExpressionCompiler() { this.hasQualifiedName("org.mvel2.compiler", "ExpressionCompiler") } } private class CompiledAccExpression extends RefType { - CompiledAccExpression() { hasQualifiedName("org.mvel2.compiler", "CompiledAccExpression") } + CompiledAccExpression() { this.hasQualifiedName("org.mvel2.compiler", "CompiledAccExpression") } } private class MvelScriptEngine extends RefType { - MvelScriptEngine() { hasQualifiedName("org.mvel2.jsr223", "MvelScriptEngine") } + MvelScriptEngine() { this.hasQualifiedName("org.mvel2.jsr223", "MvelScriptEngine") } } private class MvelCompiledScript extends RefType { - MvelCompiledScript() { hasQualifiedName("org.mvel2.jsr223", "MvelCompiledScript") } + MvelCompiledScript() { this.hasQualifiedName("org.mvel2.jsr223", "MvelCompiledScript") } } private class TemplateCompiler extends RefType { - TemplateCompiler() { hasQualifiedName("org.mvel2.templates", "TemplateCompiler") } + TemplateCompiler() { this.hasQualifiedName("org.mvel2.templates", "TemplateCompiler") } } diff --git a/java/ql/lib/semmle/code/java/security/RequestForgery.qll b/java/ql/lib/semmle/code/java/security/RequestForgery.qll index b23d0a855c0..268bd364b15 100644 --- a/java/ql/lib/semmle/code/java/security/RequestForgery.qll +++ b/java/ql/lib/semmle/code/java/security/RequestForgery.qll @@ -138,7 +138,7 @@ private class StringBuilderVarExt extends StringBuilderVar { private StringBuilderAppend getNextAppendIncludingAssignmentChains( StringBuilderConstructorOrAppend prev ) { - result = getNextAssignmentChainedAppend(prev) + result = this.getNextAssignmentChainedAppend(prev) or prev = this.getAnAssignedValue() and result = this.getAFirstAppendAfterAssignment() diff --git a/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll index ffccce1fbfa..0d9cdc853bb 100644 --- a/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll @@ -58,8 +58,8 @@ private class SafeEvaluationContextFlowConfig extends DataFlow2::Configuration { */ private class SafeContextSource extends DataFlow::ExprNode { SafeContextSource() { - isSimpleEvaluationContextConstructorCall(getExpr()) or - isSimpleEvaluationContextBuilderCall(getExpr()) + isSimpleEvaluationContextConstructorCall(this.getExpr()) or + isSimpleEvaluationContextBuilderCall(this.getExpr()) } } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index 41c15a83823..4152cb907ad 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -67,10 +67,10 @@ private class SafeKryo extends DataFlow2::Configuration { } override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - stepKryoPoolBuilderFactoryArgToConstructor(node1, node2) or - stepKryoPoolRunMethodAccessQualifierToFunctionalArgument(node1, node2) or - stepKryoPoolBuilderChainMethod(node1, node2) or - stepKryoPoolBorrowMethod(node1, node2) + this.stepKryoPoolBuilderFactoryArgToConstructor(node1, node2) or + this.stepKryoPoolRunMethodAccessQualifierToFunctionalArgument(node1, node2) or + this.stepKryoPoolBuilderChainMethod(node1, node2) or + this.stepKryoPoolBorrowMethod(node1, node2) } /** diff --git a/java/ql/lib/semmle/code/java/security/XSS.qll b/java/ql/lib/semmle/code/java/security/XSS.qll index 941b3c6c7fe..c2144c18921 100644 --- a/java/ql/lib/semmle/code/java/security/XSS.qll +++ b/java/ql/lib/semmle/code/java/security/XSS.qll @@ -79,7 +79,7 @@ private class XssVulnerableWriterSourceToWritingMethodFlowConfig extends TaintTr /** A method that can be used to output data to an output stream or writer. */ private class WritingMethod extends Method { WritingMethod() { - getDeclaringType().getASupertype*().hasQualifiedName("java.io", _) and + this.getDeclaringType().getASupertype*().hasQualifiedName("java.io", _) and ( this.getName().matches("print%") or this.getName() = "append" or diff --git a/java/ql/lib/semmle/code/xml/AndroidManifest.qll b/java/ql/lib/semmle/code/xml/AndroidManifest.qll index ae40b800ef9..234aacca967 100644 --- a/java/ql/lib/semmle/code/xml/AndroidManifest.qll +++ b/java/ql/lib/semmle/code/xml/AndroidManifest.qll @@ -36,7 +36,7 @@ class AndroidManifestXmlElement extends XMLElement { /** * Gets the value of the `package` attribute of this `<manifest>` element. */ - string getPackageAttributeValue() { result = getAttributeValue("package") } + string getPackageAttributeValue() { result = this.getAttributeValue("package") } } /** @@ -141,7 +141,7 @@ class AndroidComponentXmlElement extends XMLElement { */ string getComponentName() { exists(XMLAttribute attr | - attr = getAnAttribute() and + attr = this.getAnAttribute() and attr.getNamespace().getPrefix() = "android" and attr.getName() = "name" | @@ -153,12 +153,15 @@ class AndroidComponentXmlElement extends XMLElement { * Gets the resolved value of the `android:name` attribute of this component element. */ string getResolvedComponentName() { - if getComponentName().matches(".%") + if this.getComponentName().matches(".%") then result = - getParent().(XMLElement).getParent().(AndroidManifestXmlElement).getPackageAttributeValue() + - getComponentName() - else result = getComponentName() + this.getParent() + .(XMLElement) + .getParent() + .(AndroidManifestXmlElement) + .getPackageAttributeValue() + this.getComponentName() + else result = this.getComponentName() } /** @@ -166,7 +169,7 @@ class AndroidComponentXmlElement extends XMLElement { */ string getExportedAttributeValue() { exists(XMLAttribute attr | - attr = getAnAttribute() and + attr = this.getAnAttribute() and attr.getNamespace().getPrefix() = "android" and attr.getName() = "exported" | @@ -177,12 +180,12 @@ class AndroidComponentXmlElement extends XMLElement { /** * Holds if the `android:exported` attribute of this component element is `true`. */ - predicate isExported() { getExportedAttributeValue() = "true" } + predicate isExported() { this.getExportedAttributeValue() = "true" } /** * Holds if the `android:exported` attribute of this component element is explicitly set to `false`. */ - predicate isNotExported() { getExportedAttributeValue() = "false" } + predicate isNotExported() { this.getExportedAttributeValue() = "false" } } /** @@ -212,7 +215,7 @@ class AndroidActionXmlElement extends XMLElement { */ string getActionName() { exists(XMLAttribute attr | - attr = getAnAttribute() and + attr = this.getAnAttribute() and attr.getNamespace().getPrefix() = "android" and attr.getName() = "name" | diff --git a/java/ql/lib/semmle/code/xml/MavenPom.qll b/java/ql/lib/semmle/code/xml/MavenPom.qll index 921f9be0bff..6303de34348 100644 --- a/java/ql/lib/semmle/code/xml/MavenPom.qll +++ b/java/ql/lib/semmle/code/xml/MavenPom.qll @@ -32,7 +32,9 @@ class ProtoPom extends XMLElement { * tag was provided. */ string getVersionString() { - if exists(getVersion().getValue()) then result = getVersion().getValue() else result = "" + if exists(this.getVersion().getValue()) + then result = this.getVersion().getValue() + else result = "" } /** Gets a Maven coordinate of the form `groupId:artifactId`. */ @@ -78,25 +80,25 @@ class Pom extends ProtoPom { Dependencies getDependencies() { result = this.getAChild() } /** Gets a child XML element named "dependencyManagement". */ - DependencyManagement getDependencyManagement() { result = getAChild() } + DependencyManagement getDependencyManagement() { result = this.getAChild() } /** Gets a Dependency element for this POM. */ - Dependency getADependency() { result = getAChild().(Dependencies).getADependency() } + Dependency getADependency() { result = this.getAChild().(Dependencies).getADependency() } /** * Gets a property defined in the `<properties>` section of this POM. */ - PomProperty getALocalProperty() { result = getAChild().(PomProperties).getAProperty() } + PomProperty getALocalProperty() { result = this.getAChild().(PomProperties).getAProperty() } /** * Gets a property value defined for this project, either in a local `<properties>` section, or * in the `<properties>` section of an ancestor POM. */ PomProperty getAProperty() { - result = getALocalProperty() + result = this.getALocalProperty() or - result = getParentPom().getAProperty() and - not getALocalProperty().getName() = result.getName() + result = this.getParentPom().getAProperty() and + not this.getALocalProperty().getName() = result.getName() } /** @@ -105,7 +107,7 @@ class Pom extends ProtoPom { */ PomProperty getProperty(string name) { result.getName() = name and - result = getAProperty() + result = this.getAProperty() } /** @@ -114,11 +116,11 @@ class Pom extends ProtoPom { PomElement getProjectProperty() { ( // It must either be a child of the POM, or a child of the parent node of the POM - result = getAChild() + result = this.getAChild() or - result = getParentPom().getAChild() and + result = this.getParentPom().getAChild() and // The parent project property is not shadowed by a local project property - not exists(PomElement p | p = getAChild() and p.getName() = result.getName()) + not exists(PomElement p | p = this.getAChild() and p.getName() = result.getName()) ) and // Can't be a property if it has children of its own not exists(result.getAChild()) @@ -132,13 +134,13 @@ class Pom extends ProtoPom { if name.matches("project.%") then exists(PomElement p | - p = getProjectProperty() and + p = this.getProjectProperty() and "project." + p.getName() = name and result = p.getValue() ) else exists(PomProperty prop | - prop = getAProperty() and prop.getName() = name and result = prop.getValue() + prop = this.getAProperty() and prop.getName() = name and result = prop.getValue() ) } @@ -147,24 +149,24 @@ class Pom extends ProtoPom { * is transitively available, i.e. one with scope "compile". */ Dependency getAnExportedDependency() { - result = getADependency() and result.getScope() = "compile" + result = this.getADependency() and result.getScope() = "compile" } /** * Gets a POM dependency that is exported by this POM. An exported dependency is one that * is transitively available, i.e. one with scope "compile". */ - Pom getAnExportedPom() { result = getAnExportedDependency().getPom() } + Pom getAnExportedPom() { result = this.getAnExportedDependency().getPom() } /** * Gets the `<parent>` element of this POM, if any. */ - Parent getParentElement() { result = getAChild() } + Parent getParentElement() { result = this.getAChild() } /** * Gets the POM referred to by the `<parent>` element of this POM, if any. */ - Pom getParentPom() { result = getParentElement().getPom() } + Pom getParentPom() { result = this.getParentElement().getPom() } /** * Gets the version specified for dependency `dep` in a `dependencyManagement` @@ -172,11 +174,11 @@ class Pom extends ProtoPom { * is specified. */ string getVersionStringForDependency(Dependency dep) { - if exists(getDependencyManagement().getDependency(dep)) - then result = getDependencyManagement().getDependency(dep).getVersionString() + if exists(this.getDependencyManagement().getDependency(dep)) + then result = this.getDependencyManagement().getDependency(dep).getVersionString() else - if exists(getParentPom()) - then result = getParentPom().getVersionStringForDependency(dep) + if exists(this.getParentPom()) + then result = this.getParentPom().getVersionStringForDependency(dep) else result = "" } @@ -189,24 +191,24 @@ class Pom extends ProtoPom { */ Folder getSourceDirectory() { exists(string relativePath | - if exists(getProperty("sourceDirectory")) + if exists(this.getProperty("sourceDirectory")) then // A custom source directory has been specified. - relativePath = getProperty("sourceDirectory").getValue() + relativePath = this.getProperty("sourceDirectory").getValue() else // The Maven default source directory. relativePath = "src" | // Resolve the relative path against the base directory for this POM result.getAbsolutePath() = - normalize(getFile().getParentContainer().getAbsolutePath() + "/" + relativePath) + normalize(this.getFile().getParentContainer().getAbsolutePath() + "/" + relativePath) ) } /** * Gets a `RefType` contained in the source directory. */ - RefType getASourceRefType() { result.getFile().getParentContainer*() = getSourceDirectory() } + RefType getASourceRefType() { result.getFile().getParentContainer*() = this.getSourceDirectory() } } /** @@ -235,13 +237,13 @@ class Dependency extends ProtoPom { * be the string contents of that tag, otherwise it defaults to "compile". */ string getScope() { - if exists(getAChild().(Scope)) - then exists(Scope s | s = getAChild() and result = s.getValue()) + if exists(this.getAChild().(Scope)) + then exists(Scope s | s = this.getAChild() and result = s.getValue()) else result = "compile" } override string getVersionString() { - if exists(getVersion()) + if exists(this.getVersion()) then result = super.getVersionString() else if exists(Pom p | this = p.getADependency()) @@ -263,11 +265,11 @@ class PomDependency extends Dependency { source.getADependency() = this and // Consider dependencies that can be used at compile time. ( - getScope() = "compile" + this.getScope() = "compile" or // Provided dependencies are like compile time dependencies except (a) they are not packaged // when creating the jar and (b) they are not transitive. - getScope() = "provided" + this.getScope() = "provided" // We ignore "test" dependencies because they can be runtime or compile time dependencies ) ) @@ -284,11 +286,11 @@ class PomElement extends XMLElement { */ string getValue() { exists(string s | - s = allCharactersString() and + s = this.allCharactersString() and if s.matches("${%") then // Resolve the placeholder in the parent POM - result = getParent*().(Pom).resolvePlaceholder(s.substring(2, s.length() - 1)) + result = this.getParent*().(Pom).resolvePlaceholder(s.substring(2, s.length() - 1)) else result = s ) } @@ -335,18 +337,18 @@ class Dependencies extends PomElement { /** An XML element named "dependencyManagement", as found in Maven POM XML files. */ class DependencyManagement extends PomElement { - DependencyManagement() { getName() = "dependencyManagement" } + DependencyManagement() { this.getName() = "dependencyManagement" } - Dependencies getDependencies() { result = getAChild() } + Dependencies getDependencies() { result = this.getAChild() } - Dependency getADependency() { result = getDependencies().getADependency() } + Dependency getADependency() { result = this.getDependencies().getADependency() } /** * Gets a dependency declared in this `dependencyManagement` element that has * the same (short) coordinates as `dep`. */ Dependency getDependency(Dependency dep) { - result = getADependency() and + result = this.getADependency() and result.getShortCoordinate() = dep.getShortCoordinate() } } @@ -365,7 +367,7 @@ class PomProperties extends PomElement { * Represents a single property. */ class PomProperty extends PomElement { - PomProperty() { getParent() instanceof PomProperties } + PomProperty() { this.getParent() instanceof PomProperties } } /** @@ -378,7 +380,7 @@ class DeclaredRepository extends PomElement { * Gets the url for this repository. If the `url` tag is present, this will * be the string contents of that tag. */ - string getUrl() { result = getAChild("url").(PomElement).getValue() } + string getUrl() { result = this.getAChild("url").(PomElement).getValue() } } /** @@ -386,12 +388,16 @@ class DeclaredRepository extends PomElement { * "repository" with a parent name ".m2" is considered to be a Maven repository. */ class MavenRepo extends Folder { - MavenRepo() { getBaseName() = "repository" and getParentContainer().getBaseName() = ".m2" } + MavenRepo() { + this.getBaseName() = "repository" and this.getParentContainer().getBaseName() = ".m2" + } /** * Gets a Jar file contained within this repository. */ - File getAJarFile() { result = getAChildContainer*().(File) and result.getExtension() = "jar" } + File getAJarFile() { + result = this.getAChildContainer*().(File) and result.getExtension() = "jar" + } /** * Gets any jar artifacts in this repository that match the POM project definition. This is an @@ -400,7 +406,7 @@ class MavenRepo extends Folder { * For all other qualifiers, all matches are returned regardless of version. */ MavenRepoJar getAnArtifact(ProtoPom pom) { - result = getAJarFile() and + result = this.getAJarFile() and if exists(MavenRepoJar mrj | mrj.preciseMatch(pom)) or versionHardMatch(pom) then // Either a hard match qualifier, or soft and there is at least one precise match @@ -432,7 +438,7 @@ class MavenRepoJar extends File { // Assuming the standard layout, the first part of the directory structure from the Maven // repository will be the groupId converted to a path by replacing "." with "/". result = - getParentContainer() + this.getParentContainer() .getParentContainer() .getParentContainer() .getAbsolutePath() @@ -444,44 +450,44 @@ class MavenRepoJar extends File { /** * DEPRECATED: name changed to `getGroupId` for consistent use of camel-case. */ - deprecated string getGroupID() { result = getGroupId() } + deprecated string getGroupID() { result = this.getGroupId() } /** * Gets the `artifactId` of this jar. */ - string getArtifactId() { result = getParentContainer().getParentContainer().getBaseName() } + string getArtifactId() { result = this.getParentContainer().getParentContainer().getBaseName() } /** * DEPRECATED: name changed to `getArtifactId` for consistent casing and consistent spelling with Maven. */ - deprecated string getArtefactID() { result = getArtifactId() } + deprecated string getArtefactID() { result = this.getArtifactId() } /** * Gets the artifact version string of this jar. */ - string getVersion() { result = getParentContainer().getBaseName() } + string getVersion() { result = this.getParentContainer().getBaseName() } /** * Holds if this jar is an artifact for the given POM or dependency, regardless of which version it is. */ predicate artifactMatches(ProtoPom pom) { - pom.getGroup().getValue() = getGroupId() and - pom.getArtifact().getValue() = getArtifactId() + pom.getGroup().getValue() = this.getGroupId() and + pom.getArtifact().getValue() = this.getArtifactId() } /** * DEPRECATED: name changed to `artifactMatches` for consistent spelling with Maven. */ - deprecated predicate artefactMatches(ProtoPom pom) { artifactMatches(pom) } + deprecated predicate artefactMatches(ProtoPom pom) { this.artifactMatches(pom) } /** * Holds if this jar is both an artifact for the POM, and has a version string that matches the POM * version string. Only soft and hard version matches are supported. */ predicate preciseMatch(ProtoPom pom) { - artifactMatches(pom) and + this.artifactMatches(pom) and if versionHardMatch(pom) - then ("[" + getVersion() + "]").matches(pom.getVersionString() + "%") - else getVersion().matches(pom.getVersionString() + "%") + then ("[" + this.getVersion() + "]").matches(pom.getVersionString() + "%") + else this.getVersion().matches(pom.getVersionString() + "%") } } diff --git a/java/ql/lib/semmle/code/xml/WebXML.qll b/java/ql/lib/semmle/code/xml/WebXML.qll index 306f908afd5..c7dec5fd600 100644 --- a/java/ql/lib/semmle/code/xml/WebXML.qll +++ b/java/ql/lib/semmle/code/xml/WebXML.qll @@ -37,7 +37,7 @@ class WebXMLElement extends XMLElement { /** * Gets the value for this element, with leading and trailing whitespace trimmed. */ - string getValue() { result = allCharactersString().trim() } + string getValue() { result = this.allCharactersString().trim() } } /** @@ -49,33 +49,33 @@ class WebContextParameter extends WebXMLElement { /** * Gets the `<param-name>` element of this `<context-param>`. */ - WebContextParamName getParamName() { result = getAChild() } + WebContextParamName getParamName() { result = this.getAChild() } /** * Gets the `<param-value>` element of this `<context-param>`. */ - WebContextParamValue getParamValue() { result = getAChild() } + WebContextParamValue getParamValue() { result = this.getAChild() } } /** * A `<param-name>` element in a `web.xml` file. */ class WebContextParamName extends WebXMLElement { - WebContextParamName() { getName() = "param-name" } + WebContextParamName() { this.getName() = "param-name" } } /** * A `<param-value>` element in a `web.xml` file. */ class WebContextParamValue extends WebXMLElement { - WebContextParamValue() { getName() = "param-value" } + WebContextParamValue() { this.getName() = "param-value" } } /** * A `<filter>` element in a `web.xml` file. */ class WebFilter extends WebXMLElement { - WebFilter() { getName() = "filter" } + WebFilter() { this.getName() = "filter" } } /** @@ -83,18 +83,18 @@ class WebFilter extends WebXMLElement { */ class WebFilterClass extends WebXMLElement { WebFilterClass() { - getName() = "filter-class" and - getParent() instanceof WebFilter + this.getName() = "filter-class" and + this.getParent() instanceof WebFilter } - Class getClass() { result.getQualifiedName() = getValue() } + Class getClass() { result.getQualifiedName() = this.getValue() } } /** * A `<servlet>` element in a `web.xml` file. */ class WebServlet extends WebXMLElement { - WebServlet() { getName() = "servlet" } + WebServlet() { this.getName() = "servlet" } } /** @@ -102,18 +102,18 @@ class WebServlet extends WebXMLElement { */ class WebServletClass extends WebXMLElement { WebServletClass() { - getName() = "servlet-class" and - getParent() instanceof WebServlet + this.getName() = "servlet-class" and + this.getParent() instanceof WebServlet } - Class getClass() { result.getQualifiedName() = getValue() } + Class getClass() { result.getQualifiedName() = this.getValue() } } /** * A `<listener>` element in a `web.xml` file. */ class WebListener extends WebXMLElement { - WebListener() { getName() = "listener" } + WebListener() { this.getName() = "listener" } } /** @@ -121,14 +121,14 @@ class WebListener extends WebXMLElement { */ class WebListenerClass extends WebXMLElement { WebListenerClass() { - getName() = "listener-class" and - getParent() instanceof WebListener + this.getName() = "listener-class" and + this.getParent() instanceof WebListener } /** * Gets the `Class` instance associated with this element. */ - Class getClass() { result.getQualifiedName() = getValue() } + Class getClass() { result.getQualifiedName() = this.getValue() } } /** @@ -140,12 +140,12 @@ class WebErrorPage extends WebXMLElement { /** * Gets the `<exception-type>` element of this `<error-page>`. */ - WebErrorPageType getPageType() { result = getAChild() } + WebErrorPageType getPageType() { result = this.getAChild() } /** * Gets the `<location>` element of this `<error-page>`. */ - WebErrorPageLocation getPageLocation() { result = getAChild() } + WebErrorPageLocation getPageLocation() { result = this.getAChild() } } /** @@ -153,8 +153,8 @@ class WebErrorPage extends WebXMLElement { */ class WebErrorPageType extends WebXMLElement { WebErrorPageType() { - getName() = "exception-type" and - getParent() instanceof WebErrorPage + this.getName() = "exception-type" and + this.getParent() instanceof WebErrorPage } } @@ -163,7 +163,7 @@ class WebErrorPageType extends WebXMLElement { */ class WebErrorPageLocation extends WebXMLElement { WebErrorPageLocation() { - getName() = "location" and - getParent() instanceof WebErrorPage + this.getName() = "location" and + this.getParent() instanceof WebErrorPage } } diff --git a/java/ql/src/experimental/Security/CWE/CWE-016/InsecureSpringActuatorConfig.ql b/java/ql/src/experimental/Security/CWE/CWE-016/InsecureSpringActuatorConfig.ql index 52c4c9417e2..698dae57b96 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-016/InsecureSpringActuatorConfig.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-016/InsecureSpringActuatorConfig.ql @@ -58,10 +58,10 @@ class ManagementSecurityConfig extends ApplicationProperties { string getValue() { result = this.getValueElement().getValue().trim() } /** Holds if `management.security.enabled` is set to `false`. */ - predicate hasSecurityDisabled() { getValue() = "false" } + predicate hasSecurityDisabled() { this.getValue() = "false" } /** Holds if `management.security.enabled` is set to `true`. */ - predicate hasSecurityEnabled() { getValue() = "true" } + predicate hasSecurityEnabled() { this.getValue() = "true" } } /** The configuration property `management.endpoints.web.exposure.include`. */ diff --git a/java/ql/src/external/Clover.qll b/java/ql/src/external/Clover.qll index d17acfd8408..1b6fd9fe5c0 100644 --- a/java/ql/src/external/Clover.qll +++ b/java/ql/src/external/Clover.qll @@ -152,7 +152,7 @@ class CloverClass extends CloverMetricsContainer { /** Gets the Java type for this Clover class. */ RefType getRealClass() { result - .hasQualifiedName(getPackage().getAttribute("name").getValue(), + .hasQualifiedName(this.getPackage().getAttribute("name").getValue(), getAttribute("name").getValue()) } } From a0e501c3a971bc5705976c2439b60400406ff934 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 15 Oct 2021 14:34:02 +0100 Subject: [PATCH 296/361] Sync identical files. --- .../javascript/security/CryptoAlgorithms.qll | 71 +++++-------------- 1 file changed, 17 insertions(+), 54 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll index a5bfd6696be..4b3c5f2a49f 100644 --- a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll +++ b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll @@ -15,72 +15,35 @@ */ private module AlgorithmNames { predicate isStrongHashingAlgorithm(string name) { - name = "DSA" or - name = "ED25519" or - name = "ES256" or - name = "ECDSA256" or - name = "ES384" or - name = "ECDSA384" or - name = "ES512" or - name = "ECDSA512" or - name = "SHA2" or - name = "SHA224" or - name = "SHA256" or - name = "SHA384" or - name = "SHA512" or - name = "SHA3" or - name = "SHA3224" or - name = "SHA3256" or - name = "SHA3384" or - name = "SHA3512" + name = + [ + "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", + "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512" + ] } predicate isWeakHashingAlgorithm(string name) { - name = "HAVEL128" or - name = "MD2" or - name = "MD4" or - name = "MD5" or - name = "PANAMA" or - name = "RIPEMD" or - name = "RIPEMD128" or - name = "RIPEMD256" or - name = "RIPEMD160" or - name = "RIPEMD320" or - name = "SHA0" or - name = "SHA1" + name = + [ + "HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD", "RIPEMD128", "RIPEMD256", "RIPEMD160", + "RIPEMD320", "SHA0", "SHA1" + ] } predicate isStrongEncryptionAlgorithm(string name) { - name = "AES" or - name = "AES128" or - name = "AES192" or - name = "AES256" or - name = "AES512" or - name = "RSA" or - name = "RABBIT" or - name = "BLOWFISH" + name = ["AES", "AES128", "AES192", "AES256", "AES512", "RSA", "RABBIT", "BLOWFISH"] } predicate isWeakEncryptionAlgorithm(string name) { - name = "DES" or - name = "3DES" or - name = "TRIPLEDES" or - name = "TDEA" or - name = "TRIPLEDEA" or - name = "ARC2" or - name = "RC2" or - name = "ARC4" or - name = "RC4" or - name = "ARCFOUR" or - name = "ARC5" or - name = "RC5" + name = + [ + "DES", "3DES", "TRIPLEDES", "TDEA", "TRIPLEDEA", "ARC2", "RC2", "ARC4", "RC4", "ARCFOUR", + "ARC5", "RC5" + ] } predicate isStrongPasswordHashingAlgorithm(string name) { - name = "ARGON2" or - name = "PBKDF2" or - name = "BCRYPT" or - name = "SCRYPT" + name = ["ARGON2", "PBKDF2", "BCRYPT", "SCRYPT"] } predicate isWeakPasswordHashingAlgorithm(string name) { none() } From fe891746bf1d9c18ce488e178977f7fda2f5de3c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 14 Oct 2021 09:49:53 +0200 Subject: [PATCH 297/361] C++: fix implicit this --- cpp/ql/lib/external/ExternalArtifact.qll | 18 +- cpp/ql/lib/semmle/code/cpp/Class.qll | 30 +- cpp/ql/lib/semmle/code/cpp/Declaration.qll | 40 +- cpp/ql/lib/semmle/code/cpp/Element.qll | 8 +- cpp/ql/lib/semmle/code/cpp/Enum.qll | 2 +- cpp/ql/lib/semmle/code/cpp/File.qll | 22 +- cpp/ql/lib/semmle/code/cpp/Function.qll | 79 +- cpp/ql/lib/semmle/code/cpp/Include.qll | 6 +- cpp/ql/lib/semmle/code/cpp/Initializer.qll | 4 +- cpp/ql/lib/semmle/code/cpp/Location.qll | 12 +- cpp/ql/lib/semmle/code/cpp/Macro.qll | 18 +- cpp/ql/lib/semmle/code/cpp/MemberFunction.qll | 58 +- cpp/ql/lib/semmle/code/cpp/Namespace.qll | 14 +- cpp/ql/lib/semmle/code/cpp/Parameter.qll | 30 +- cpp/ql/lib/semmle/code/cpp/Preprocessor.qll | 12 +- cpp/ql/lib/semmle/code/cpp/Print.qll | 133 +-- cpp/ql/lib/semmle/code/cpp/Specifier.qll | 24 +- cpp/ql/lib/semmle/code/cpp/Struct.qll | 2 +- cpp/ql/lib/semmle/code/cpp/TestFile.qll | 14 +- cpp/ql/lib/semmle/code/cpp/Type.qll | 61 +- cpp/ql/lib/semmle/code/cpp/TypedefType.qll | 10 +- cpp/ql/lib/semmle/code/cpp/Union.qll | 2 +- cpp/ql/lib/semmle/code/cpp/UserType.qll | 20 +- cpp/ql/lib/semmle/code/cpp/Variable.qll | 43 +- .../semmle/code/cpp/commons/CommonType.qll | 16 +- .../semmle/code/cpp/commons/Dependency.qll | 2 +- cpp/ql/lib/semmle/code/cpp/commons/Printf.qll | 110 +-- cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll | 44 +- .../code/cpp/commons/Synchronization.qll | 18 +- .../code/cpp/controlflow/BasicBlocks.qll | 6 +- .../code/cpp/controlflow/ControlFlowGraph.qll | 4 +- .../semmle/code/cpp/controlflow/IRGuards.qll | 22 +- .../LocalScopeVariableReachability.qll | 62 +- .../lib/semmle/code/cpp/controlflow/SSA.qll | 2 +- .../controlflow/StackVariableReachability.qll | 62 +- .../code/cpp/controlflow/SubBasicBlocks.qll | 4 +- .../controlflow/internal/ConstantExprs.qll | 265 +++--- .../cpp/dataflow/internal/DataFlowImpl.qll | 16 +- .../cpp/dataflow/internal/DataFlowImpl2.qll | 16 +- .../cpp/dataflow/internal/DataFlowImpl3.qll | 16 +- .../cpp/dataflow/internal/DataFlowImpl4.qll | 16 +- .../dataflow/internal/DataFlowImplLocal.qll | 16 +- .../cpp/dataflow/internal/DataFlowUtil.qll | 36 +- .../code/cpp/dataflow/internal/FlowVar.qll | 8 +- .../cpp/dataflow/internal/SubBasicBlocks.qll | 4 +- cpp/ql/lib/semmle/code/cpp/exprs/Access.qll | 6 +- .../code/cpp/exprs/ArithmeticOperation.qll | 4 +- .../code/cpp/exprs/BuiltInOperations.qll | 12 +- cpp/ql/lib/semmle/code/cpp/exprs/Call.qll | 58 +- cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll | 52 +- cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll | 58 +- cpp/ql/lib/semmle/code/cpp/exprs/Lambda.qll | 8 +- cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll | 32 +- .../code/cpp/internal/QualifiedName.qll | 2 +- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 16 +- .../ir/dataflow/internal/DataFlowImpl2.qll | 16 +- .../ir/dataflow/internal/DataFlowImpl3.qll | 16 +- .../ir/dataflow/internal/DataFlowImpl4.qll | 16 +- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 4 +- .../raw/internal/TranslatedExpr.qll | 839 +++++++++--------- .../semmle/code/cpp/metrics/MetricClass.qll | 2 +- .../semmle/code/cpp/metrics/MetricFile.qll | 2 +- .../code/cpp/metrics/MetricFunction.qll | 4 +- .../cpp/models/implementations/Allocation.qll | 54 +- .../cpp/models/implementations/GetDelim.qll | 2 +- .../code/cpp/models/implementations/Gets.qll | 6 +- .../cpp/models/implementations/Memcpy.qll | 36 +- .../cpp/models/implementations/Memset.qll | 10 +- .../code/cpp/models/implementations/Pure.qll | 56 +- .../models/implementations/SmartPointer.qll | 10 +- .../cpp/models/implementations/Sscanf.qll | 14 +- .../models/implementations/StdContainer.qll | 34 +- .../cpp/models/implementations/StdMap.qll | 14 +- .../cpp/models/implementations/StdPair.qll | 6 +- .../cpp/models/implementations/StdSet.qll | 10 +- .../cpp/models/implementations/StdString.qll | 46 +- .../cpp/models/implementations/Strcat.qll | 6 +- .../cpp/models/implementations/Strcpy.qll | 50 +- .../cpp/models/implementations/Strcrement.qll | 6 +- .../code/cpp/models/implementations/Swap.qll | 2 +- .../interfaces/FunctionInputsAndOutputs.qll | 18 +- .../lib/semmle/code/cpp/padding/Padding.qll | 115 +-- .../code/cpp/rangeanalysis/RangeSSA.qll | 2 +- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 17 +- .../semmle/code/cpp/security/BufferWrite.qll | 80 +- .../semmle/code/cpp/security/FileWrite.qll | 36 +- .../semmle/code/cpp/security/FlowSources.qll | 8 +- .../cpp/security/FunctionWithWrappers.qll | 6 +- .../lib/semmle/code/cpp/security/Security.qll | 2 +- .../code/cpp/security/SensitiveExprs.qll | 4 +- .../cpp/security/boostorg/asio/protocols.qll | 2 +- cpp/ql/lib/semmle/code/cpp/stmts/Block.qll | 6 +- cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll | 44 +- .../ClassesWithManyFields.ql | 24 +- cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll | 6 +- cpp/ql/src/external/CodeDuplication.qll | 20 +- cpp/ql/src/external/MetricFilter.qll | 4 +- 97 files changed, 1739 insertions(+), 1571 deletions(-) diff --git a/cpp/ql/lib/external/ExternalArtifact.qll b/cpp/ql/lib/external/ExternalArtifact.qll index abbc96a7b47..1034f1c9ecc 100644 --- a/cpp/ql/lib/external/ExternalArtifact.qll +++ b/cpp/ql/lib/external/ExternalArtifact.qll @@ -15,7 +15,7 @@ class ExternalData extends @externalDataElement { * Gets the path of the file this data was loaded from, with its * extension replaced by `.ql`. */ - string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } + string getQueryPath() { result = this.getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } /** Gets the number of fields in this data item. */ int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) } @@ -24,22 +24,22 @@ class ExternalData extends @externalDataElement { string getField(int i) { externalData(this, _, i, result) } /** Gets the integer value of the `i`th field of this data item. */ - int getFieldAsInt(int i) { result = getField(i).toInt() } + int getFieldAsInt(int i) { result = this.getField(i).toInt() } /** Gets the floating-point value of the `i`th field of this data item. */ - float getFieldAsFloat(int i) { result = getField(i).toFloat() } + float getFieldAsFloat(int i) { result = this.getField(i).toFloat() } /** Gets the value of the `i`th field of this data item, interpreted as a date. */ - date getFieldAsDate(int i) { result = getField(i).toDate() } + date getFieldAsDate(int i) { result = this.getField(i).toDate() } /** Gets a textual representation of this data item. */ - string toString() { result = getQueryPath() + ": " + buildTupleString(0) } + string toString() { result = this.getQueryPath() + ": " + this.buildTupleString(0) } /** Gets a textual representation of this data item, starting with the `n`th field. */ private string buildTupleString(int n) { - n = getNumFields() - 1 and result = getField(n) + n = this.getNumFields() - 1 and result = this.getField(n) or - n < getNumFields() - 1 and result = getField(n) + "," + buildTupleString(n + 1) + n < this.getNumFields() - 1 and result = this.getField(n) + "," + this.buildTupleString(n + 1) } } @@ -53,8 +53,8 @@ class DefectExternalData extends ExternalData { } /** Gets the URL associated with this data item. */ - string getURL() { result = getField(0) } + string getURL() { result = this.getField(0) } /** Gets the message associated with this data item. */ - string getMessage() { result = getField(1) } + string getMessage() { result = this.getField(1) } } diff --git a/cpp/ql/lib/semmle/code/cpp/Class.qll b/cpp/ql/lib/semmle/code/cpp/Class.qll index 987ec7ffa3d..c4fdbfb40f6 100644 --- a/cpp/ql/lib/semmle/code/cpp/Class.qll +++ b/cpp/ql/lib/semmle/code/cpp/Class.qll @@ -269,13 +269,13 @@ class Class extends UserType { * DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that * `= default` members are no longer included. */ - deprecated predicate hasGeneratedCopyConstructor() { hasImplicitCopyConstructor() } + deprecated predicate hasGeneratedCopyConstructor() { this.hasImplicitCopyConstructor() } /** * DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to * reflect that `= default` members are no longer included. */ - deprecated predicate hasGeneratedCopyAssignmentOperator() { hasImplicitCopyConstructor() } + deprecated predicate hasGeneratedCopyAssignmentOperator() { this.hasImplicitCopyConstructor() } /** * Holds if this class, struct or union has an implicitly-declared copy @@ -487,7 +487,7 @@ class Class extends UserType { exists(ClassDerivation cd | // Add the offset of the direct base class and the offset of `baseClass` // within that direct base class. - cd = getADerivation() and + cd = this.getADerivation() and result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + cd.getByteOffset() ) } @@ -502,12 +502,12 @@ class Class extends UserType { */ int getABaseClassByteOffset(Class baseClass) { // Handle the non-virtual case. - result = getANonVirtualBaseClassByteOffset(baseClass) + result = this.getANonVirtualBaseClassByteOffset(baseClass) or exists(Class virtualBaseClass, int virtualBaseOffset, int offsetFromVirtualBase | // Look for the base class as a non-virtual base of a direct or indirect // virtual base, adding the two offsets. - getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and + this.getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and offsetFromVirtualBase = virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and result = virtualBaseOffset + offsetFromVirtualBase ) @@ -623,11 +623,11 @@ class Class extends UserType { * inherits one). */ predicate isPolymorphic() { - exists(MemberFunction f | f.getDeclaringType() = getABaseClass*() and f.isVirtual()) + exists(MemberFunction f | f.getDeclaringType() = this.getABaseClass*() and f.isVirtual()) } override predicate involvesTemplateParameter() { - getATemplateArgument().(Type).involvesTemplateParameter() + this.getATemplateArgument().(Type).involvesTemplateParameter() } /** Holds if this class, struct or union was declared 'final'. */ @@ -765,7 +765,7 @@ class ClassDerivation extends Locatable, @derivation { * }; * ``` */ - Class getBaseClass() { result = getBaseType().getUnderlyingType() } + Class getBaseClass() { result = this.getBaseType().getUnderlyingType() } override string getAPrimaryQlClass() { result = "ClassDerivation" } @@ -818,7 +818,7 @@ class ClassDerivation extends Locatable, @derivation { predicate hasSpecifier(string s) { this.getASpecifier().hasName(s) } /** Holds if the derivation is for a virtual base class. */ - predicate isVirtual() { hasSpecifier("virtual") } + predicate isVirtual() { this.hasSpecifier("virtual") } /** Gets the location of the derivation. */ override Location getLocation() { derivations(underlyingElement(this), _, _, _, result) } @@ -846,7 +846,7 @@ class ClassDerivation extends Locatable, @derivation { * ``` */ class LocalClass extends Class { - LocalClass() { isLocal() } + LocalClass() { this.isLocal() } override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" } @@ -989,9 +989,9 @@ class ClassTemplateSpecialization extends Class { TemplateClass getPrimaryTemplate() { // Ignoring template arguments, the primary template has the same name // as each of its specializations. - result.getSimpleName() = getSimpleName() and + result.getSimpleName() = this.getSimpleName() and // It is in the same namespace as its specializations. - result.getNamespace() = getNamespace() and + result.getNamespace() = this.getNamespace() and // It is distinguished by the fact that each of its template arguments // is a distinct template parameter. count(TemplateParameter tp | tp = result.getATemplateArgument()) = @@ -1108,7 +1108,7 @@ deprecated class Interface extends Class { * ``` */ class VirtualClassDerivation extends ClassDerivation { - VirtualClassDerivation() { hasSpecifier("virtual") } + VirtualClassDerivation() { this.hasSpecifier("virtual") } override string getAPrimaryQlClass() { result = "VirtualClassDerivation" } } @@ -1136,7 +1136,7 @@ class VirtualBaseClass extends Class { VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this } /** A class/struct that is derived from this one using virtual inheritance. */ - Class getAVirtuallyDerivedClass() { result = getAVirtualDerivation().getDerivedClass() } + Class getAVirtuallyDerivedClass() { result = this.getAVirtualDerivation().getDerivedClass() } } /** @@ -1155,7 +1155,7 @@ class ProxyClass extends UserType { override string getAPrimaryQlClass() { result = "ProxyClass" } /** Gets the location of the proxy class. */ - override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() } + override Location getLocation() { result = this.getTemplateParameter().getDefinitionLocation() } /** Gets the template parameter for which this is the proxy class. */ TemplateParameter getTemplateParameter() { diff --git a/cpp/ql/lib/semmle/code/cpp/Declaration.qll b/cpp/ql/lib/semmle/code/cpp/Declaration.qll index b1422aa6342..0433be1f120 100644 --- a/cpp/ql/lib/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/lib/semmle/code/cpp/Declaration.qll @@ -184,7 +184,7 @@ class Declaration extends Locatable, @declaration { predicate hasDefinition() { exists(this.getDefinition()) } /** DEPRECATED: Use `hasDefinition` instead. */ - predicate isDefined() { hasDefinition() } + predicate isDefined() { this.hasDefinition() } /** Gets the preferred location of this declaration, if any. */ override Location getLocation() { none() } @@ -209,7 +209,7 @@ class Declaration extends Locatable, @declaration { predicate isStatic() { this.hasSpecifier("static") } /** Holds if this declaration is a member of a class/struct/union. */ - predicate isMember() { hasDeclaringType() } + predicate isMember() { this.hasDeclaringType() } /** Holds if this declaration is a member of a class/struct/union. */ predicate hasDeclaringType() { exists(this.getDeclaringType()) } @@ -226,14 +226,14 @@ class Declaration extends Locatable, @declaration { * When called on a template, this will return a template parameter type for * both typed and non-typed parameters. */ - final Locatable getATemplateArgument() { result = getTemplateArgument(_) } + final Locatable getATemplateArgument() { result = this.getTemplateArgument(_) } /** * Gets a template argument used to instantiate this declaration from a template. * When called on a template, this will return a non-typed template * parameter value. */ - final Locatable getATemplateArgumentKind() { result = getTemplateArgumentKind(_) } + final Locatable getATemplateArgumentKind() { result = this.getTemplateArgumentKind(_) } /** * Gets the `i`th template argument used to instantiate this declaration from a @@ -252,9 +252,9 @@ class Declaration extends Locatable, @declaration { * `getTemplateArgument(1)` return `1`. */ final Locatable getTemplateArgument(int index) { - if exists(getTemplateArgumentValue(index)) - then result = getTemplateArgumentValue(index) - else result = getTemplateArgumentType(index) + if exists(this.getTemplateArgumentValue(index)) + then result = this.getTemplateArgumentValue(index) + else result = this.getTemplateArgumentType(index) } /** @@ -275,13 +275,13 @@ class Declaration extends Locatable, @declaration { * `getTemplateArgumentKind(0)`. */ final Locatable getTemplateArgumentKind(int index) { - exists(getTemplateArgumentValue(index)) and - result = getTemplateArgumentType(index) + exists(this.getTemplateArgumentValue(index)) and + result = this.getTemplateArgumentType(index) } /** Gets the number of template arguments for this declaration. */ final int getNumberOfTemplateArguments() { - result = count(int i | exists(getTemplateArgument(i))) + result = count(int i | exists(this.getTemplateArgument(i))) } private Type getTemplateArgumentType(int index) { @@ -327,9 +327,9 @@ class DeclarationEntry extends Locatable, TDeclarationEntry { * available), or the name declared by this entry otherwise. */ string getCanonicalName() { - if getDeclaration().hasDefinition() - then result = getDeclaration().getDefinition().getName() - else result = getName() + if this.getDeclaration().hasDefinition() + then result = this.getDeclaration().getDefinition().getName() + else result = this.getName() } /** @@ -370,18 +370,18 @@ class DeclarationEntry extends Locatable, TDeclarationEntry { /** * Holds if this declaration entry has a specifier with the given name. */ - predicate hasSpecifier(string specifier) { getASpecifier() = specifier } + predicate hasSpecifier(string specifier) { this.getASpecifier() = specifier } /** Holds if this declaration entry is a definition. */ predicate isDefinition() { none() } // overridden in subclasses override string toString() { - if isDefinition() - then result = "definition of " + getName() + if this.isDefinition() + then result = "definition of " + this.getName() else - if getName() = getCanonicalName() - then result = "declaration of " + getName() - else result = "declaration of " + getCanonicalName() + " as " + getName() + if this.getName() = this.getCanonicalName() + then result = "declaration of " + this.getName() + else result = "declaration of " + this.getCanonicalName() + " as " + this.getName() } } @@ -580,7 +580,7 @@ private class DirectAccessHolder extends Element { // transitive closure with a restricted base case. this.thisCanAccessClassStep(base, derived) or - exists(Class between | thisCanAccessClassTrans(base, between) | + exists(Class between | this.thisCanAccessClassTrans(base, between) | isDirectPublicBaseOf(between, derived) or this.thisCanAccessClassStep(between, derived) ) diff --git a/cpp/ql/lib/semmle/code/cpp/Element.qll b/cpp/ql/lib/semmle/code/cpp/Element.qll index 1f547adccaa..9273d1b31bf 100644 --- a/cpp/ql/lib/semmle/code/cpp/Element.qll +++ b/cpp/ql/lib/semmle/code/cpp/Element.qll @@ -61,7 +61,7 @@ class ElementBase extends @element { /** * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */ - final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") } + final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") } /** * Gets the name of a primary CodeQL class to which this element belongs. @@ -206,9 +206,9 @@ class Element extends ElementBase { /** Gets the closest `Element` enclosing this one. */ cached Element getEnclosingElement() { - result = getEnclosingElementPref() + result = this.getEnclosingElementPref() or - not exists(getEnclosingElementPref()) and + not exists(this.getEnclosingElementPref()) and ( this = result.(Class).getAMember() or @@ -281,7 +281,7 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) { * ``` */ class StaticAssert extends Locatable, @static_assert { - override string toString() { result = "static_assert(..., \"" + getMessage() + "\")" } + override string toString() { result = "static_assert(..., \"" + this.getMessage() + "\")" } /** * Gets the expression which this static assertion ensures is true. diff --git a/cpp/ql/lib/semmle/code/cpp/Enum.qll b/cpp/ql/lib/semmle/code/cpp/Enum.qll index 9cddeb78f9b..38263dacf7a 100644 --- a/cpp/ql/lib/semmle/code/cpp/Enum.qll +++ b/cpp/ql/lib/semmle/code/cpp/Enum.qll @@ -85,7 +85,7 @@ class Enum extends UserType, IntegralOrEnumType { * ``` */ class LocalEnum extends Enum { - LocalEnum() { isLocal() } + LocalEnum() { this.isLocal() } override string getAPrimaryQlClass() { result = "LocalEnum" } } diff --git a/cpp/ql/lib/semmle/code/cpp/File.qll b/cpp/ql/lib/semmle/code/cpp/File.qll index f486dd8d3c5..3b72533b4f4 100644 --- a/cpp/ql/lib/semmle/code/cpp/File.qll +++ b/cpp/ql/lib/semmle/code/cpp/File.qll @@ -52,7 +52,7 @@ class Container extends Locatable, @container { */ string getRelativePath() { exists(string absPath, string pref | - absPath = getAbsolutePath() and sourceLocationPrefix(pref) + absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) | absPath = pref and result = "" or @@ -79,7 +79,7 @@ class Container extends Locatable, @container { * </table> */ string getBaseName() { - result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) + result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) } /** @@ -105,7 +105,9 @@ class Container extends Locatable, @container { * <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr> * </table> */ - string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } + string getExtension() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) + } /** * Gets the stem of this container, that is, the prefix of its base name up to @@ -124,7 +126,9 @@ class Container extends Locatable, @container { * <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr> * </table> */ - string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } + string getStem() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) + } /** Gets the parent container of this file or folder, if any. */ Container getParentContainer() { @@ -135,20 +139,20 @@ class Container extends Locatable, @container { Container getAChildContainer() { this = result.getParentContainer() } /** Gets a file in this container. */ - File getAFile() { result = getAChildContainer() } + File getAFile() { result = this.getAChildContainer() } /** Gets the file in this container that has the given `baseName`, if any. */ File getFile(string baseName) { - result = getAFile() and + result = this.getAFile() and result.getBaseName() = baseName } /** Gets a sub-folder in this container. */ - Folder getAFolder() { result = getAChildContainer() } + Folder getAFolder() { result = this.getAChildContainer() } /** Gets the sub-folder in this container that has the given `baseName`, if any. */ Folder getFolder(string baseName) { - result = getAFolder() and + result = this.getAFolder() and result.getBaseName() = baseName } @@ -157,7 +161,7 @@ class Container extends Locatable, @container { * * This is the absolute path of the container. */ - override string toString() { result = getAbsolutePath() } + override string toString() { result = this.getAbsolutePath() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/Function.qll b/cpp/ql/lib/semmle/code/cpp/Function.qll index 6cae134645f..0f1de2b512c 100644 --- a/cpp/ql/lib/semmle/code/cpp/Function.qll +++ b/cpp/ql/lib/semmle/code/cpp/Function.qll @@ -43,26 +43,26 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { */ string getFullSignature() { exists(string name, string templateArgs, string args | - result = name + templateArgs + args + " -> " + getType().toString() and - name = getQualifiedName() and + result = name + templateArgs + args + " -> " + this.getType().toString() and + name = this.getQualifiedName() and ( - if exists(getATemplateArgument()) + if exists(this.getATemplateArgument()) then templateArgs = "<" + concat(int i | - exists(getTemplateArgument(i)) + exists(this.getTemplateArgument(i)) | - getTemplateArgument(i).toString(), ", " order by i + this.getTemplateArgument(i).toString(), ", " order by i ) + ">" else templateArgs = "" ) and args = "(" + concat(int i | - exists(getParameter(i)) + exists(this.getParameter(i)) | - getParameter(i).getType().toString(), ", " order by i + this.getParameter(i).getType().toString(), ", " order by i ) + ")" ) } @@ -70,7 +70,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { /** Gets a specifier of this function. */ override Specifier getASpecifier() { funspecifiers(underlyingElement(this), unresolveElement(result)) or - result.hasName(getADeclarationEntry().getASpecifier()) + result.hasName(this.getADeclarationEntry().getASpecifier()) } /** Gets an attribute of this function. */ @@ -149,7 +149,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * Holds if this function is declared with `__attribute__((naked))` or * `__declspec(naked)`. */ - predicate isNaked() { getAnAttribute().hasName("naked") } + predicate isNaked() { this.getAnAttribute().hasName("naked") } /** * Holds if this function has a trailing return type. @@ -172,7 +172,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * Gets the return type of this function after specifiers have been deeply * stripped and typedefs have been resolved. */ - Type getUnspecifiedType() { result = getType().getUnspecifiedType() } + Type getUnspecifiedType() { result = this.getType().getUnspecifiedType() } /** * Gets the nth parameter of this function. There is no result for the @@ -206,7 +206,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { int getEffectiveNumberOfParameters() { // This method is overridden in `MemberFunction`, where the result is // adjusted to account for the implicit `this` parameter. - result = getNumberOfParameters() + result = this.getNumberOfParameters() } /** @@ -216,7 +216,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * return `int p1, int p2`. */ string getParameterString() { - result = concat(int i | | min(getParameter(i).getTypedName()), ", " order by i) + result = concat(int i | | min(this.getParameter(i).getTypedName()), ", " order by i) } /** Gets a call to this function. */ @@ -229,7 +229,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { */ override FunctionDeclarationEntry getADeclarationEntry() { if fun_decls(_, underlyingElement(this), _, _, _) - then declEntry(result) + then this.declEntry(result) else exists(Function f | this.isConstructedFrom(f) and @@ -250,7 +250,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * Gets the location of a `FunctionDeclarationEntry` corresponding to this * declaration. */ - override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } + override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() } /** Holds if this Function is a Template specialization. */ predicate isSpecialization() { @@ -265,14 +265,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * definition, if any. */ override FunctionDeclarationEntry getDefinition() { - result = getADeclarationEntry() and + result = this.getADeclarationEntry() and result.isDefinition() } /** Gets the location of the definition, if any. */ override Location getDefinitionLocation() { - if exists(getDefinition()) - then result = getDefinition().getLocation() + if exists(this.getDefinition()) + then result = this.getDefinition().getLocation() else exists(Function f | this.isConstructedFrom(f) and result = f.getDefinition().getLocation()) } @@ -281,7 +281,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * definition, if possible.) */ override Location getLocation() { - if exists(getDefinition()) + if exists(this.getDefinition()) then result = this.getDefinitionLocation() else result = this.getADeclarationLocation() } @@ -299,7 +299,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { BlockStmt getBlock() { result.getParentScope() = this } /** Holds if this function has an entry point. */ - predicate hasEntryPoint() { exists(getEntryPoint()) } + predicate hasEntryPoint() { exists(this.getEntryPoint()) } /** * Gets the first node in this function's control flow graph. @@ -392,7 +392,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * Holds if this function has C linkage, as specified by one of its * declaration entries. For example: `extern "C" void foo();`. */ - predicate hasCLinkage() { getADeclarationEntry().hasCLinkage() } + predicate hasCLinkage() { this.getADeclarationEntry().hasCLinkage() } /** * Holds if this function is constructed from `f` as a result @@ -409,27 +409,27 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * several functions that are not linked together have been compiled. An * example would be a project with many 'main' functions. */ - predicate isMultiplyDefined() { strictcount(getFile()) > 1 } + predicate isMultiplyDefined() { strictcount(this.getFile()) > 1 } /** Holds if this function is a varargs function. */ - predicate isVarargs() { hasSpecifier("varargs") } + predicate isVarargs() { this.hasSpecifier("varargs") } /** Gets a type that is specified to be thrown by the function. */ - Type getAThrownType() { result = getADeclarationEntry().getAThrownType() } + Type getAThrownType() { result = this.getADeclarationEntry().getAThrownType() } /** * Gets the `i`th type specified to be thrown by the function. */ - Type getThrownType(int i) { result = getADeclarationEntry().getThrownType(i) } + Type getThrownType(int i) { result = this.getADeclarationEntry().getThrownType(i) } /** Holds if the function has an exception specification. */ - predicate hasExceptionSpecification() { getADeclarationEntry().hasExceptionSpecification() } + predicate hasExceptionSpecification() { this.getADeclarationEntry().hasExceptionSpecification() } /** Holds if this function has a `throw()` exception specification. */ - predicate isNoThrow() { getADeclarationEntry().isNoThrow() } + predicate isNoThrow() { this.getADeclarationEntry().isNoThrow() } /** Holds if this function has a `noexcept` exception specification. */ - predicate isNoExcept() { getADeclarationEntry().isNoExcept() } + predicate isNoExcept() { this.getADeclarationEntry().isNoExcept() } /** * Gets a function that overloads this one. @@ -539,7 +539,7 @@ private predicate candGetAnOverloadNonMember(string name, Namespace namespace, F */ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { /** Gets the function which is being declared or defined. */ - override Function getDeclaration() { result = getFunction() } + override Function getDeclaration() { result = this.getFunction() } override string getAPrimaryQlClass() { result = "FunctionDeclarationEntry" } @@ -586,7 +586,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * case, catch) plus the number of branching expressions (`?`, `&&`, * `||`) plus one. */ - int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(getBlock()) } + int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(this.getBlock()) } /** * If this is a function definition, get the block containing the @@ -594,7 +594,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { */ BlockStmt getBlock() { this.isDefinition() and - result = getFunction().getBlock() and + result = this.getFunction().getBlock() and result.getFile() = this.getFile() } @@ -604,7 +604,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { */ pragma[noopt] int getNumberOfLines() { - exists(BlockStmt b, Location l, int start, int end, int diff | b = getBlock() | + exists(BlockStmt b, Location l, int start, int end, int diff | b = this.getBlock() | l = b.getLocation() and start = l.getStartLine() and end = l.getEndLine() and @@ -618,7 +618,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * declaration. */ ParameterDeclarationEntry getAParameterDeclarationEntry() { - result = getParameterDeclarationEntry(_) + result = this.getParameterDeclarationEntry(_) } /** @@ -639,7 +639,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * return 'int p1, int p2'. */ string getParameterString() { - result = concat(int i | | min(getParameterDeclarationEntry(i).getTypedName()), ", " order by i) + result = + concat(int i | | min(this.getParameterDeclarationEntry(i).getTypedName()), ", " order by i) } /** @@ -647,10 +648,10 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * * `extern "C" void foo();` */ - predicate hasCLinkage() { getASpecifier() = "c_linkage" } + predicate hasCLinkage() { this.getASpecifier() = "c_linkage" } /** Holds if this declaration entry has a void parameter list. */ - predicate hasVoidParamList() { getASpecifier() = "void_param_list" } + predicate hasVoidParamList() { this.getASpecifier() = "void_param_list" } /** Holds if this declaration is also a definition of its function. */ override predicate isDefinition() { fun_def(underlyingElement(this)) } @@ -665,7 +666,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { predicate isImplicit() { fun_implicit(underlyingElement(this)) } /** Gets a type that is specified to be thrown by the declared function. */ - Type getAThrownType() { result = getThrownType(_) } + Type getAThrownType() { result = this.getThrownType(_) } /** * Gets the `i`th type specified to be thrown by the declared function @@ -690,8 +691,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { predicate hasExceptionSpecification() { fun_decl_throws(underlyingElement(this), _, _) or fun_decl_noexcept(underlyingElement(this), _) or - isNoThrow() or - isNoExcept() + this.isNoThrow() or + this.isNoExcept() } /** @@ -763,7 +764,7 @@ class Operator extends Function { */ class TemplateFunction extends Function { TemplateFunction() { - is_function_template(underlyingElement(this)) and exists(getATemplateArgument()) + is_function_template(underlyingElement(this)) and exists(this.getATemplateArgument()) } override string getAPrimaryQlClass() { result = "TemplateFunction" } diff --git a/cpp/ql/lib/semmle/code/cpp/Include.qll b/cpp/ql/lib/semmle/code/cpp/Include.qll index f21edb2651d..9a120b1013c 100644 --- a/cpp/ql/lib/semmle/code/cpp/Include.qll +++ b/cpp/ql/lib/semmle/code/cpp/Include.qll @@ -23,7 +23,7 @@ class Include extends PreprocessorDirective, @ppd_include { * Gets the token which occurs after `#include`, for example `"filename"` * or `<filename>`. */ - string getIncludeText() { result = getHead() } + string getIncludeText() { result = this.getHead() } /** Gets the file directly included by this `#include`. */ File getIncludedFile() { includes(underlyingElement(this), unresolveElement(result)) } @@ -53,7 +53,7 @@ class Include extends PreprocessorDirective, @ppd_include { * ``` */ class IncludeNext extends Include, @ppd_include_next { - override string toString() { result = "#include_next " + getIncludeText() } + override string toString() { result = "#include_next " + this.getIncludeText() } } /** @@ -65,5 +65,5 @@ class IncludeNext extends Include, @ppd_include_next { * ``` */ class Import extends Include, @ppd_objc_import { - override string toString() { result = "#import " + getIncludeText() } + override string toString() { result = "#import " + this.getIncludeText() } } diff --git a/cpp/ql/lib/semmle/code/cpp/Initializer.qll b/cpp/ql/lib/semmle/code/cpp/Initializer.qll index 64607af3393..62af72c1803 100644 --- a/cpp/ql/lib/semmle/code/cpp/Initializer.qll +++ b/cpp/ql/lib/semmle/code/cpp/Initializer.qll @@ -34,8 +34,8 @@ class Initializer extends ControlFlowNode, @initialiser { override predicate fromSource() { not this.getLocation() instanceof UnknownLocation } override string toString() { - if exists(getDeclaration()) - then result = "initializer for " + max(getDeclaration().getName()) + if exists(this.getDeclaration()) + then result = "initializer for " + max(this.getDeclaration().getName()) else result = "initializer" } diff --git a/cpp/ql/lib/semmle/code/cpp/Location.qll b/cpp/ql/lib/semmle/code/cpp/Location.qll index 15ae2121255..92b358d474c 100644 --- a/cpp/ql/lib/semmle/code/cpp/Location.qll +++ b/cpp/ql/lib/semmle/code/cpp/Location.qll @@ -79,8 +79,8 @@ class Location extends @location { /** Holds if location `l` is completely contained within this one. */ predicate subsumes(Location l) { - exists(File f | f = getFile() | - exists(int thisStart, int thisEnd | charLoc(f, thisStart, thisEnd) | + exists(File f | f = this.getFile() | + exists(int thisStart, int thisEnd | this.charLoc(f, thisStart, thisEnd) | exists(int lStart, int lEnd | l.charLoc(f, lStart, lEnd) | thisStart <= lStart and lEnd <= thisEnd ) @@ -97,10 +97,10 @@ class Location extends @location { * see `subsumes`. */ predicate charLoc(File f, int start, int end) { - f = getFile() and + f = this.getFile() and exists(int maxCols | maxCols = maxCols(f) | - start = getStartLine() * maxCols + getStartColumn() and - end = getEndLine() * maxCols + getEndColumn() + start = this.getStartLine() * maxCols + this.getStartColumn() and + end = this.getEndLine() * maxCols + this.getEndColumn() ) } } @@ -144,7 +144,7 @@ class Locatable extends Element { } * expressions, one for statements and one for other program elements. */ class UnknownLocation extends Location { - UnknownLocation() { getFile().getAbsolutePath() = "" } + UnknownLocation() { this.getFile().getAbsolutePath() = "" } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/Macro.qll b/cpp/ql/lib/semmle/code/cpp/Macro.qll index aa4b8d41999..6d61ae7be7c 100644 --- a/cpp/ql/lib/semmle/code/cpp/Macro.qll +++ b/cpp/ql/lib/semmle/code/cpp/Macro.qll @@ -44,10 +44,10 @@ class Macro extends PreprocessorDirective, @ppd_define { * Gets the name of the macro. For example, `MAX` in * `#define MAX(x,y) (((x)>(y))?(x):(y))`. */ - string getName() { result = getHead().splitAt("(", 0) } + string getName() { result = this.getHead().splitAt("(", 0) } /** Holds if the macro has name `name`. */ - predicate hasName(string name) { getName() = name } + predicate hasName(string name) { this.getName() = name } } /** @@ -130,7 +130,7 @@ class MacroAccess extends Locatable, @macroinvocation { override string toString() { result = this.getMacro().getHead() } /** Gets the name of the accessed macro. */ - string getMacroName() { result = getMacro().getName() } + string getMacroName() { result = this.getMacro().getName() } } /** @@ -197,8 +197,8 @@ class MacroInvocation extends MacroAccess { * expression. In other cases, it may have multiple results or no results. */ Expr getExpr() { - result = getAnExpandedElement() and - not result.getParent() = getAnExpandedElement() and + result = this.getAnExpandedElement() and + not result.getParent() = this.getAnExpandedElement() and not result instanceof Conversion } @@ -208,8 +208,8 @@ class MacroInvocation extends MacroAccess { * element is not a statement (for example if it is an expression). */ Stmt getStmt() { - result = getAnExpandedElement() and - not result.getParent() = getAnExpandedElement() + result = this.getAnExpandedElement() and + not result.getParent() = this.getAnExpandedElement() } /** @@ -278,7 +278,7 @@ deprecated class MacroInvocationExpr extends Expr { MacroInvocation getInvocation() { result.getExpr() = this } /** Gets the name of the invoked macro. */ - string getMacroName() { result = getInvocation().getMacroName() } + string getMacroName() { result = this.getInvocation().getMacroName() } } /** @@ -298,7 +298,7 @@ deprecated class MacroInvocationStmt extends Stmt { MacroInvocation getInvocation() { result.getStmt() = this } /** Gets the name of the invoked macro. */ - string getMacroName() { result = getInvocation().getMacroName() } + string getMacroName() { result = this.getInvocation().getMacroName() } } /** Holds if `l` is the location of a macro. */ diff --git a/cpp/ql/lib/semmle/code/cpp/MemberFunction.qll b/cpp/ql/lib/semmle/code/cpp/MemberFunction.qll index 63c1406d8a5..03b1704549f 100644 --- a/cpp/ql/lib/semmle/code/cpp/MemberFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/MemberFunction.qll @@ -36,7 +36,9 @@ class MemberFunction extends Function { * `this` parameter. */ override int getEffectiveNumberOfParameters() { - if isStatic() then result = getNumberOfParameters() else result = getNumberOfParameters() + 1 + if this.isStatic() + then result = this.getNumberOfParameters() + else result = this.getNumberOfParameters() + 1 } /** Holds if this member is private. */ @@ -49,13 +51,13 @@ class MemberFunction extends Function { predicate isPublic() { this.hasSpecifier("public") } /** Holds if this declaration has the lvalue ref-qualifier */ - predicate isLValueRefQualified() { hasSpecifier("&") } + predicate isLValueRefQualified() { this.hasSpecifier("&") } /** Holds if this declaration has the rvalue ref-qualifier */ - predicate isRValueRefQualified() { hasSpecifier("&&") } + predicate isRValueRefQualified() { this.hasSpecifier("&&") } /** Holds if this declaration has a ref-qualifier */ - predicate isRefQualified() { isLValueRefQualified() or isRValueRefQualified() } + predicate isRefQualified() { this.isLValueRefQualified() or this.isRValueRefQualified() } /** Holds if this function overrides that function. */ predicate overrides(MemberFunction that) { @@ -73,10 +75,10 @@ class MemberFunction extends Function { * class body. */ FunctionDeclarationEntry getClassBodyDeclarationEntry() { - if strictcount(getADeclarationEntry()) = 1 - then result = getDefinition() + if strictcount(this.getADeclarationEntry()) = 1 + then result = this.getDefinition() else ( - result = getADeclarationEntry() and result != getDefinition() + result = this.getADeclarationEntry() and result != this.getDefinition() ) } @@ -198,7 +200,7 @@ class Constructor extends MemberFunction { * compiler-generated action which initializes a base class or member * variable. */ - ConstructorInit getAnInitializer() { result = getInitializer(_) } + ConstructorInit getAnInitializer() { result = this.getInitializer(_) } /** * Gets an entry in the constructor's initializer list, or a @@ -220,8 +222,8 @@ class ImplicitConversionFunction extends MemberFunction { functions(underlyingElement(this), _, 4) or // ConversionConstructor (deprecated) - strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and - not hasSpecifier("explicit") + strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and + not this.hasSpecifier("explicit") } /** Gets the type this `ImplicitConversionFunction` takes as input. */ @@ -248,8 +250,8 @@ class ImplicitConversionFunction extends MemberFunction { */ deprecated class ConversionConstructor extends Constructor, ImplicitConversionFunction { ConversionConstructor() { - strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and - not hasSpecifier("explicit") + strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and + not this.hasSpecifier("explicit") } override string getAPrimaryQlClass() { @@ -301,15 +303,15 @@ class CopyConstructor extends Constructor { hasCopySignature(this) and ( // The rest of the parameters all have default values - forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer()) + forall(int i | i > 0 and exists(this.getParameter(i)) | this.getParameter(i).hasInitializer()) or // or this is a template class, in which case the default values have // not been extracted even if they exist. In that case, we assume that // there are default values present since that is the most common case // in real-world code. - getDeclaringType() instanceof TemplateClass + this.getDeclaringType() instanceof TemplateClass ) and - not exists(getATemplateArgument()) + not exists(this.getATemplateArgument()) } override string getAPrimaryQlClass() { result = "CopyConstructor" } @@ -325,8 +327,8 @@ class CopyConstructor extends Constructor { // type-checked for each template instantiation; if an argument in an // instantiation fails to type-check then the corresponding parameter has // no default argument in the instantiation. - getDeclaringType() instanceof TemplateClass and - getNumberOfParameters() > 1 + this.getDeclaringType() instanceof TemplateClass and + this.getNumberOfParameters() > 1 } } @@ -358,15 +360,15 @@ class MoveConstructor extends Constructor { hasMoveSignature(this) and ( // The rest of the parameters all have default values - forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer()) + forall(int i | i > 0 and exists(this.getParameter(i)) | this.getParameter(i).hasInitializer()) or // or this is a template class, in which case the default values have // not been extracted even if they exist. In that case, we assume that // there are default values present since that is the most common case // in real-world code. - getDeclaringType() instanceof TemplateClass + this.getDeclaringType() instanceof TemplateClass ) and - not exists(getATemplateArgument()) + not exists(this.getATemplateArgument()) } override string getAPrimaryQlClass() { result = "MoveConstructor" } @@ -382,8 +384,8 @@ class MoveConstructor extends Constructor { // type-checked for each template instantiation; if an argument in an // instantiation fails to type-check then the corresponding parameter has // no default argument in the instantiation. - getDeclaringType() instanceof TemplateClass and - getNumberOfParameters() > 1 + this.getDeclaringType() instanceof TemplateClass and + this.getNumberOfParameters() > 1 } } @@ -426,7 +428,7 @@ class Destructor extends MemberFunction { * Gets a compiler-generated action which destructs a base class or member * variable. */ - DestructorDestruction getADestruction() { result = getDestruction(_) } + DestructorDestruction getADestruction() { result = this.getDestruction(_) } /** * Gets a compiler-generated action which destructs a base class or member @@ -475,16 +477,16 @@ class ConversionOperator extends MemberFunction, ImplicitConversionFunction { */ class CopyAssignmentOperator extends Operator { CopyAssignmentOperator() { - hasName("operator=") and + this.hasName("operator=") and ( hasCopySignature(this) or // Unlike CopyConstructor, this member allows a non-reference // parameter. - getParameter(0).getUnspecifiedType() = getDeclaringType() + this.getParameter(0).getUnspecifiedType() = this.getDeclaringType() ) and not exists(this.getParameter(1)) and - not exists(getATemplateArgument()) + not exists(this.getATemplateArgument()) } override string getAPrimaryQlClass() { result = "CopyAssignmentOperator" } @@ -507,10 +509,10 @@ class CopyAssignmentOperator extends Operator { */ class MoveAssignmentOperator extends Operator { MoveAssignmentOperator() { - hasName("operator=") and + this.hasName("operator=") and hasMoveSignature(this) and not exists(this.getParameter(1)) and - not exists(getATemplateArgument()) + not exists(this.getATemplateArgument()) } override string getAPrimaryQlClass() { result = "MoveAssignmentOperator" } diff --git a/cpp/ql/lib/semmle/code/cpp/Namespace.qll b/cpp/ql/lib/semmle/code/cpp/Namespace.qll index d46abc6b4db..47ebc9d35c5 100644 --- a/cpp/ql/lib/semmle/code/cpp/Namespace.qll +++ b/cpp/ql/lib/semmle/code/cpp/Namespace.qll @@ -38,8 +38,8 @@ class Namespace extends NameQualifyingElement, @namespace { * unless the namespace has exactly one declaration entry. */ override Location getLocation() { - if strictcount(getADeclarationEntry()) = 1 - then result = getADeclarationEntry().getLocation() + if strictcount(this.getADeclarationEntry()) = 1 + then result = this.getADeclarationEntry().getLocation() else result instanceof UnknownDefaultLocation } @@ -50,7 +50,7 @@ class Namespace extends NameQualifyingElement, @namespace { predicate hasName(string name) { name = this.getName() } /** Holds if this namespace is anonymous. */ - predicate isAnonymous() { hasName("(unnamed namespace)") } + predicate isAnonymous() { this.hasName("(unnamed namespace)") } /** Gets the name of the parent namespace, if it exists. */ private string getParentName() { @@ -60,9 +60,9 @@ class Namespace extends NameQualifyingElement, @namespace { /** Gets the qualified name of this namespace. For example: `a::b`. */ string getQualifiedName() { - if exists(getParentName()) - then result = getParentNamespace().getQualifiedName() + "::" + getName() - else result = getName() + if exists(this.getParentName()) + then result = this.getParentNamespace().getQualifiedName() + "::" + this.getName() + else result = this.getName() } /** Gets the parent namespace, if any. */ @@ -99,7 +99,7 @@ class Namespace extends NameQualifyingElement, @namespace { /** Gets a version of the `QualifiedName` that is more suitable for display purposes. */ string getFriendlyName() { result = this.getQualifiedName() } - final override string toString() { result = getFriendlyName() } + final override string toString() { result = this.getFriendlyName() } /** Gets a declaration of (part of) this namespace. */ NamespaceDeclarationEntry getADeclarationEntry() { result.getNamespace() = this } diff --git a/cpp/ql/lib/semmle/code/cpp/Parameter.qll b/cpp/ql/lib/semmle/code/cpp/Parameter.qll index b87bfe6a4c7..47b77b542c1 100644 --- a/cpp/ql/lib/semmle/code/cpp/Parameter.qll +++ b/cpp/ql/lib/semmle/code/cpp/Parameter.qll @@ -40,12 +40,12 @@ class Parameter extends LocalScopeVariable, @parameter { */ override string getName() { exists(VariableDeclarationEntry vde | - vde = getANamedDeclarationEntry() and result = vde.getName() + vde = this.getANamedDeclarationEntry() and result = vde.getName() | - vde.isDefinition() or not getANamedDeclarationEntry().isDefinition() + vde.isDefinition() or not this.getANamedDeclarationEntry().isDefinition() ) or - not exists(getANamedDeclarationEntry()) and + not exists(this.getANamedDeclarationEntry()) and result = "(unnamed parameter " + this.getIndex().toString() + ")" } @@ -58,8 +58,12 @@ class Parameter extends LocalScopeVariable, @parameter { */ string getTypedName() { exists(string typeString, string nameString | - (if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and - (if exists(getName()) then nameString = getName() else nameString = "") and + ( + if exists(this.getType().getName()) + then typeString = this.getType().getName() + else typeString = "" + ) and + (if exists(this.getName()) then nameString = this.getName() else nameString = "") and ( if typeString != "" and nameString != "" then result = typeString + " " + nameString @@ -69,7 +73,7 @@ class Parameter extends LocalScopeVariable, @parameter { } private VariableDeclarationEntry getANamedDeclarationEntry() { - result = getAnEffectiveDeclarationEntry() and result.getName() != "" + result = this.getAnEffectiveDeclarationEntry() and result.getName() != "" } /** @@ -82,13 +86,13 @@ class Parameter extends LocalScopeVariable, @parameter { * own). */ private VariableDeclarationEntry getAnEffectiveDeclarationEntry() { - if getFunction().isConstructedFrom(_) + if this.getFunction().isConstructedFrom(_) then exists(Function prototypeInstantiation | - prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and - getFunction().isConstructedFrom(prototypeInstantiation) + prototypeInstantiation.getParameter(this.getIndex()) = result.getVariable() and + this.getFunction().isConstructedFrom(prototypeInstantiation) ) - else result = getADeclarationEntry() + else result = this.getADeclarationEntry() } /** @@ -114,7 +118,7 @@ class Parameter extends LocalScopeVariable, @parameter { * `getName()` is not "(unnamed parameter i)" (where `i` is the index * of the parameter). */ - predicate isNamed() { exists(getANamedDeclarationEntry()) } + predicate isNamed() { exists(this.getANamedDeclarationEntry()) } /** * Gets the function to which this parameter belongs, if it is a function @@ -157,9 +161,9 @@ class Parameter extends LocalScopeVariable, @parameter { */ override Location getLocation() { exists(VariableDeclarationEntry vde | - vde = getAnEffectiveDeclarationEntry() and result = vde.getLocation() + vde = this.getAnEffectiveDeclarationEntry() and result = vde.getLocation() | - vde.isDefinition() or not getAnEffectiveDeclarationEntry().isDefinition() + vde.isDefinition() or not this.getAnEffectiveDeclarationEntry().isDefinition() ) } } diff --git a/cpp/ql/lib/semmle/code/cpp/Preprocessor.qll b/cpp/ql/lib/semmle/code/cpp/Preprocessor.qll index 2389db07f2a..91b7aa1aab9 100644 --- a/cpp/ql/lib/semmle/code/cpp/Preprocessor.qll +++ b/cpp/ql/lib/semmle/code/cpp/Preprocessor.qll @@ -29,8 +29,8 @@ class PreprocessorDirective extends Locatable, @preprocdirect { PreprocessorBranch getAGuard() { exists(PreprocessorEndif e, int line | result.getEndIf() = e and - e.getFile() = getFile() and - result.getFile() = getFile() and + e.getFile() = this.getFile() and + result.getFile() = this.getFile() and line = this.getLocation().getStartLine() and result.getLocation().getStartLine() < line and line < e.getLocation().getEndLine() @@ -69,7 +69,9 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr * directives in different translation units, then there can be more than * one result. */ - PreprocessorEndif getEndIf() { preprocpair(unresolveElement(getIf()), unresolveElement(result)) } + PreprocessorEndif getEndIf() { + preprocpair(unresolveElement(this.getIf()), unresolveElement(result)) + } /** * Gets the next `#elif`, `#else` or `#endif` matching this branching @@ -137,7 +139,7 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch { * which evaluated it, or was not taken by any translation unit which * evaluated it. */ - predicate wasPredictable() { not (wasTaken() and wasNotTaken()) } + predicate wasPredictable() { not (this.wasTaken() and this.wasNotTaken()) } } /** @@ -268,7 +270,7 @@ class PreprocessorUndef extends PreprocessorDirective, @ppd_undef { /** * Gets the name of the macro that is undefined. */ - string getName() { result = getHead() } + string getName() { result = this.getHead() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/Print.qll b/cpp/ql/lib/semmle/code/cpp/Print.qll index f8d30f55a88..64ae5b960d1 100644 --- a/cpp/ql/lib/semmle/code/cpp/Print.qll +++ b/cpp/ql/lib/semmle/code/cpp/Print.qll @@ -105,8 +105,8 @@ private class DumpType extends Type { // for a `SpecifiedType`, insert the qualifiers after // `getDeclaratorSuffixBeforeQualifiers()`. result = - getTypeSpecifier() + getDeclaratorPrefix() + getDeclaratorSuffixBeforeQualifiers() + - getDeclaratorSuffix() + this.getTypeSpecifier() + this.getDeclaratorPrefix() + + this.getDeclaratorSuffixBeforeQualifiers() + this.getDeclaratorSuffix() } /** @@ -147,29 +147,35 @@ private class DumpType extends Type { } private class BuiltInDumpType extends DumpType, BuiltInType { - override string getTypeSpecifier() { result = toString() } + override string getTypeSpecifier() { result = this.toString() } } private class IntegralDumpType extends BuiltInDumpType, IntegralType { - override string getTypeSpecifier() { result = getCanonicalArithmeticType().toString() } + override string getTypeSpecifier() { result = this.getCanonicalArithmeticType().toString() } } private class DerivedDumpType extends DumpType, DerivedType { - override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } + override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() } override string getDeclaratorSuffixBeforeQualifiers() { - result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + result = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() } - override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } + override string getDeclaratorSuffix() { + result = this.getBaseType().(DumpType).getDeclaratorSuffix() + } } private class DecltypeDumpType extends DumpType, Decltype { - override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } + override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() } - override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() } + override string getDeclaratorPrefix() { + result = this.getBaseType().(DumpType).getDeclaratorPrefix() + } - override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } + override string getDeclaratorSuffix() { + result = this.getBaseType().(DumpType).getDeclaratorSuffix() + } } private class PointerIshDumpType extends DerivedDumpType { @@ -180,10 +186,10 @@ private class PointerIshDumpType extends DerivedDumpType { override string getDeclaratorPrefix() { exists(string declarator | - result = getBaseType().(DumpType).getDeclaratorPrefix() + declarator and - if getBaseType().getUnspecifiedType() instanceof ArrayType - then declarator = "(" + getDeclaratorToken() + ")" - else declarator = getDeclaratorToken() + result = this.getBaseType().(DumpType).getDeclaratorPrefix() + declarator and + if this.getBaseType().getUnspecifiedType() instanceof ArrayType + then declarator = "(" + this.getDeclaratorToken() + ")" + else declarator = this.getDeclaratorToken() ) } @@ -206,13 +212,13 @@ private class RValueReferenceDumpType extends PointerIshDumpType, RValueReferenc } private class PointerToMemberDumpType extends DumpType, PointerToMemberType { - override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } + override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() } override string getDeclaratorPrefix() { exists(string declarator, string parenDeclarator, Type baseType | - declarator = getClass().(DumpType).getTypeIdentityString() + "::*" and - result = getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and - baseType = getBaseType().getUnspecifiedType() and + declarator = this.getClass().(DumpType).getTypeIdentityString() + "::*" and + result = this.getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and + baseType = this.getBaseType().getUnspecifiedType() and if baseType instanceof ArrayType or baseType instanceof RoutineType then parenDeclarator = "(" + declarator else parenDeclarator = declarator @@ -221,38 +227,44 @@ private class PointerToMemberDumpType extends DumpType, PointerToMemberType { override string getDeclaratorSuffixBeforeQualifiers() { exists(Type baseType | - baseType = getBaseType().getUnspecifiedType() and + baseType = this.getBaseType().getUnspecifiedType() and if baseType instanceof ArrayType or baseType instanceof RoutineType - then result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() - else result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + then result = ")" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + else result = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() ) } - override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } + override string getDeclaratorSuffix() { + result = this.getBaseType().(DumpType).getDeclaratorSuffix() + } } private class ArrayDumpType extends DerivedDumpType, ArrayType { - override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() } + override string getDeclaratorPrefix() { + result = this.getBaseType().(DumpType).getDeclaratorPrefix() + } override string getDeclaratorSuffixBeforeQualifiers() { - if exists(getArraySize()) + if exists(this.getArraySize()) then result = - "[" + getArraySize().toString() + "]" + - getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() - else result = "[]" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + "[" + this.getArraySize().toString() + "]" + + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + else result = "[]" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() } } private class FunctionPointerIshDumpType extends DerivedDumpType, FunctionPointerIshType { override string getDeclaratorSuffixBeforeQualifiers() { - result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + result = ")" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() } - override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } + override string getDeclaratorSuffix() { + result = this.getBaseType().(DumpType).getDeclaratorSuffix() + } override string getDeclaratorPrefix() { - result = getBaseType().(DumpType).getDeclaratorPrefix() + "(" + getDeclaratorToken() + result = this.getBaseType().(DumpType).getDeclaratorPrefix() + "(" + this.getDeclaratorToken() } /** @@ -274,10 +286,10 @@ private class BlockDumpType extends FunctionPointerIshDumpType, BlockType { } private class RoutineDumpType extends DumpType, RoutineType { - override string getTypeSpecifier() { result = getReturnType().(DumpType).getTypeSpecifier() } + override string getTypeSpecifier() { result = this.getReturnType().(DumpType).getTypeSpecifier() } override string getDeclaratorPrefix() { - result = getReturnType().(DumpType).getDeclaratorPrefix() + result = this.getReturnType().(DumpType).getDeclaratorPrefix() } language[monotonicAggregates] @@ -285,39 +297,41 @@ private class RoutineDumpType extends DumpType, RoutineType { result = "(" + concat(int i | - exists(getParameterType(i)) + exists(this.getParameterType(i)) | - getParameterTypeString(getParameterType(i)), ", " order by i + getParameterTypeString(this.getParameterType(i)), ", " order by i ) + ")" } override string getDeclaratorSuffix() { result = - getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + - getReturnType().(DumpType).getDeclaratorSuffix() + this.getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + + this.getReturnType().(DumpType).getDeclaratorSuffix() } } private class SpecifiedDumpType extends DerivedDumpType, SpecifiedType { override string getDeclaratorPrefix() { exists(string basePrefix | - basePrefix = getBaseType().(DumpType).getDeclaratorPrefix() and - if getBaseType().getUnspecifiedType() instanceof RoutineType + basePrefix = this.getBaseType().(DumpType).getDeclaratorPrefix() and + if this.getBaseType().getUnspecifiedType() instanceof RoutineType then result = basePrefix - else result = basePrefix + " " + getSpecifierString() + else result = basePrefix + " " + this.getSpecifierString() ) } override string getDeclaratorSuffixBeforeQualifiers() { exists(string baseSuffix | - baseSuffix = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and - if getBaseType().getUnspecifiedType() instanceof RoutineType - then result = baseSuffix + " " + getSpecifierString() + baseSuffix = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and + if this.getBaseType().getUnspecifiedType() instanceof RoutineType + then result = baseSuffix + " " + this.getSpecifierString() else result = baseSuffix ) } - override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } + override string getDeclaratorSuffix() { + result = this.getBaseType().(DumpType).getDeclaratorSuffix() + } } private class UserDumpType extends DumpType, DumpDeclaration, UserType { @@ -330,18 +344,18 @@ private class UserDumpType extends DumpType, DumpDeclaration, UserType { // "lambda [] type at line 12, col. 40" // Use `min(getSimpleName())` to work around an extractor bug where a lambda can have different names // from different compilation units. - simpleName = "(" + min(getSimpleName()) + ")" - else simpleName = getSimpleName() + simpleName = "(" + min(this.getSimpleName()) + ")" + else simpleName = this.getSimpleName() ) and - result = getScopePrefix(this) + simpleName + getTemplateArgumentsString() + result = getScopePrefix(this) + simpleName + this.getTemplateArgumentsString() ) } - override string getTypeSpecifier() { result = getIdentityString() } + override string getTypeSpecifier() { result = this.getIdentityString() } } private class DumpProxyClass extends UserDumpType, ProxyClass { - override string getIdentityString() { result = getName() } + override string getIdentityString() { result = this.getName() } } private class DumpVariable extends DumpDeclaration, Variable { @@ -360,9 +374,9 @@ private class DumpVariable extends DumpDeclaration, Variable { private class DumpFunction extends DumpDeclaration, Function { override string getIdentityString() { result = - getType().(DumpType).getTypeSpecifier() + getType().(DumpType).getDeclaratorPrefix() + " " + - getScopePrefix(this) + getName() + getTemplateArgumentsString() + - getDeclaratorSuffixBeforeQualifiers() + getDeclaratorSuffix() + this.getType().(DumpType).getTypeSpecifier() + this.getType().(DumpType).getDeclaratorPrefix() + + " " + getScopePrefix(this) + this.getName() + this.getTemplateArgumentsString() + + this.getDeclaratorSuffixBeforeQualifiers() + this.getDeclaratorSuffix() } language[monotonicAggregates] @@ -370,28 +384,29 @@ private class DumpFunction extends DumpDeclaration, Function { result = "(" + concat(int i | - exists(getParameter(i).getType()) + exists(this.getParameter(i).getType()) | - getParameterTypeString(getParameter(i).getType()), ", " order by i - ) + ")" + getQualifierString() + getParameterTypeString(this.getParameter(i).getType()), ", " order by i + ) + ")" + this.getQualifierString() } private string getQualifierString() { - if exists(getACVQualifier()) + if exists(this.getACVQualifier()) then - result = " " + strictconcat(string qualifier | qualifier = getACVQualifier() | qualifier, " ") + result = + " " + strictconcat(string qualifier | qualifier = this.getACVQualifier() | qualifier, " ") else result = "" } private string getACVQualifier() { - result = getASpecifier().getName() and + result = this.getASpecifier().getName() and result = ["const", "volatile"] } private string getDeclaratorSuffix() { result = - getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + - getType().(DumpType).getDeclaratorSuffix() + this.getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + + this.getType().(DumpType).getDeclaratorSuffix() } } diff --git a/cpp/ql/lib/semmle/code/cpp/Specifier.qll b/cpp/ql/lib/semmle/code/cpp/Specifier.qll index 4a425b690f4..52abfb097cc 100644 --- a/cpp/ql/lib/semmle/code/cpp/Specifier.qll +++ b/cpp/ql/lib/semmle/code/cpp/Specifier.qll @@ -140,7 +140,7 @@ class Attribute extends Element, @attribute { AttributeArgument getArgument(int i) { result.getAttribute() = this and result.getIndex() = i } /** Gets an argument of the attribute. */ - AttributeArgument getAnArgument() { result = getArgument(_) } + AttributeArgument getAnArgument() { result = this.getArgument(_) } } /** @@ -166,7 +166,7 @@ class StdAttribute extends Attribute, @stdattribute { * Holds if this attribute has the given namespace and name. */ predicate hasQualifiedName(string namespace, string name) { - namespace = getNamespace() and hasName(name) + namespace = this.getNamespace() and this.hasName(name) } } @@ -184,7 +184,7 @@ class Declspec extends Attribute, @declspec { } */ class MicrosoftAttribute extends Attribute, @msattribute { AttributeArgument getNamedArgument(string name) { - result = getAnArgument() and result.getName() = name + result = this.getAnArgument() and result.getName() = name } } @@ -212,13 +212,13 @@ class AlignAs extends Attribute, @alignas { * ``` */ class FormatAttribute extends GnuAttribute { - FormatAttribute() { getName() = "format" } + FormatAttribute() { this.getName() = "format" } /** * Gets the archetype of this format attribute, for example * `"printf"`. */ - string getArchetype() { result = getArgument(0).getValueText() } + string getArchetype() { result = this.getArgument(0).getValueText() } /** * Gets the index in (1-based) format attribute notation associated @@ -236,7 +236,7 @@ class FormatAttribute extends GnuAttribute { * Gets the (0-based) index of the format string, * according to this attribute. */ - int getFormatIndex() { result = getArgument(1).getValueInt() - firstArgumentNumber() } + int getFormatIndex() { result = this.getArgument(1).getValueInt() - this.firstArgumentNumber() } /** * Gets the (0-based) index of the first format argument (if any), @@ -244,8 +244,8 @@ class FormatAttribute extends GnuAttribute { */ int getFirstFormatArgIndex() { exists(int val | - val = getArgument(2).getValueInt() and - result = val - firstArgumentNumber() and + val = this.getArgument(2).getValueInt() and + result = val - this.firstArgumentNumber() and not val = 0 // indicates a `vprintf` style format function with arguments not directly available. ) } @@ -277,7 +277,7 @@ class AttributeArgument extends Element, @attribute_arg { /** * Gets the value of this argument, if its value is integral. */ - int getValueInt() { result = getValueText().toInt() } + int getValueInt() { result = this.getValueText().toInt() } /** * Gets the value of this argument, if its value is a type. @@ -304,11 +304,11 @@ class AttributeArgument extends Element, @attribute_arg { then result = "empty argument" else exists(string prefix, string tail | - (if exists(getName()) then prefix = getName() + "=" else prefix = "") and + (if exists(this.getName()) then prefix = this.getName() + "=" else prefix = "") and ( if exists(@attribute_arg_type self | self = underlyingElement(this)) - then tail = getValueType().getName() - else tail = getValueText() + then tail = this.getValueType().getName() + else tail = this.getValueText() ) and result = prefix + tail ) diff --git a/cpp/ql/lib/semmle/code/cpp/Struct.qll b/cpp/ql/lib/semmle/code/cpp/Struct.qll index 50a208894b4..5465472374f 100644 --- a/cpp/ql/lib/semmle/code/cpp/Struct.qll +++ b/cpp/ql/lib/semmle/code/cpp/Struct.qll @@ -41,7 +41,7 @@ class Struct extends Class { * ``` */ class LocalStruct extends Struct { - LocalStruct() { isLocal() } + LocalStruct() { this.isLocal() } override string getAPrimaryQlClass() { not this instanceof LocalUnion and result = "LocalStruct" } } diff --git a/cpp/ql/lib/semmle/code/cpp/TestFile.qll b/cpp/ql/lib/semmle/code/cpp/TestFile.qll index b9e3fe3a614..a2e496ab019 100644 --- a/cpp/ql/lib/semmle/code/cpp/TestFile.qll +++ b/cpp/ql/lib/semmle/code/cpp/TestFile.qll @@ -10,8 +10,8 @@ import semmle.code.cpp.File */ private class GoogleTestHeader extends File { GoogleTestHeader() { - getBaseName() = "gtest.h" and - getParentContainer().getBaseName() = "gtest" + this.getBaseName() = "gtest.h" and + this.getParentContainer().getBaseName() = "gtest" } } @@ -30,8 +30,8 @@ private class GoogleTest extends MacroInvocation { */ private class BoostTestFolder extends Folder { BoostTestFolder() { - getBaseName() = "test" and - getParentContainer().getBaseName() = "boost" + this.getBaseName() = "test" and + this.getParentContainer().getBaseName() = "boost" } } @@ -49,7 +49,7 @@ private class BoostTest extends MacroInvocation { * The `cppunit` directory. */ private class CppUnitFolder extends Folder { - CppUnitFolder() { getBaseName() = "cppunit" } + CppUnitFolder() { this.getBaseName() = "cppunit" } } /** @@ -57,8 +57,8 @@ private class CppUnitFolder extends Folder { */ private class CppUnitClass extends Class { CppUnitClass() { - getFile().getParentContainer+() instanceof CppUnitFolder and - getNamespace().getParentNamespace*().getName() = "CppUnit" + this.getFile().getParentContainer+() instanceof CppUnitFolder and + this.getNamespace().getParentNamespace*().getName() = "CppUnit" } } diff --git a/cpp/ql/lib/semmle/code/cpp/Type.qll b/cpp/ql/lib/semmle/code/cpp/Type.qll index b390e24a0fa..f8552144ea8 100644 --- a/cpp/ql/lib/semmle/code/cpp/Type.qll +++ b/cpp/ql/lib/semmle/code/cpp/Type.qll @@ -81,7 +81,7 @@ class Type extends Locatable, @type { * Holds if this type refers to type `t` (by default, * a type always refers to itself). */ - predicate refersTo(Type t) { refersToDirectly*(t) } + predicate refersTo(Type t) { this.refersToDirectly*(t) } /** * Holds if this type refers to type `t` directly. @@ -1080,11 +1080,11 @@ class DerivedType extends Type, @derivedtype { override predicate refersToDirectly(Type t) { t = this.getBaseType() } - override predicate involvesReference() { getBaseType().involvesReference() } + override predicate involvesReference() { this.getBaseType().involvesReference() } - override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } + override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() } - override Type stripType() { result = getBaseType().stripType() } + override Type stripType() { result = this.getBaseType().stripType() } /** * Holds if this type has the `__autoreleasing` specifier or if it points to @@ -1165,33 +1165,35 @@ class Decltype extends Type, @decltype { */ predicate parenthesesWouldChangeMeaning() { decltypes(underlyingElement(this), _, _, true) } - override Type getUnderlyingType() { result = getBaseType().getUnderlyingType() } + override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() } - override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } + override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() } - override Type stripType() { result = getBaseType().stripType() } + override Type stripType() { result = this.getBaseType().stripType() } - override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() } + override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() } - override Location getLocation() { result = getExpr().getLocation() } + override Location getLocation() { result = this.getExpr().getLocation() } override string toString() { result = "decltype(...)" } override string getName() { none() } - override int getSize() { result = getBaseType().getSize() } + override int getSize() { result = this.getBaseType().getSize() } - override int getAlignment() { result = getBaseType().getAlignment() } + override int getAlignment() { result = this.getBaseType().getAlignment() } - override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } + override int getPointerIndirectionLevel() { + result = this.getBaseType().getPointerIndirectionLevel() + } override string explain() { result = "decltype resulting in {" + this.getBaseType().explain() + "}" } - override predicate involvesReference() { getBaseType().involvesReference() } + override predicate involvesReference() { this.getBaseType().involvesReference() } - override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } + override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() } override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() } @@ -1223,7 +1225,7 @@ class PointerType extends DerivedType { override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } override Type resolveTypedefs() { - result.(PointerType).getBaseType() = getBaseType().resolveTypedefs() + result.(PointerType).getBaseType() = this.getBaseType().resolveTypedefs() } } @@ -1240,7 +1242,9 @@ class ReferenceType extends DerivedType { override string getAPrimaryQlClass() { result = "ReferenceType" } - override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } + override int getPointerIndirectionLevel() { + result = this.getBaseType().getPointerIndirectionLevel() + } override string explain() { result = "reference to {" + this.getBaseType().explain() + "}" } @@ -1251,7 +1255,7 @@ class ReferenceType extends DerivedType { override predicate involvesReference() { any() } override Type resolveTypedefs() { - result.(ReferenceType).getBaseType() = getBaseType().resolveTypedefs() + result.(ReferenceType).getBaseType() = this.getBaseType().resolveTypedefs() } } @@ -1330,11 +1334,11 @@ class SpecifiedType extends DerivedType { } override Type resolveTypedefs() { - result.(SpecifiedType).getBaseType() = getBaseType().resolveTypedefs() and - result.getASpecifier() = getASpecifier() + result.(SpecifiedType).getBaseType() = this.getBaseType().resolveTypedefs() and + result.getASpecifier() = this.getASpecifier() } - override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } + override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() } } /** @@ -1433,7 +1437,8 @@ class GNUVectorType extends DerivedType { override int getAlignment() { arraysizes(underlyingElement(this), _, _, result) } override string explain() { - result = "GNU " + getNumElements() + " element vector of {" + this.getBaseType().explain() + "}" + result = + "GNU " + this.getNumElements() + " element vector of {" + this.getBaseType().explain() + "}" } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } @@ -1468,7 +1473,9 @@ class FunctionReferenceType extends FunctionPointerIshType { override string getAPrimaryQlClass() { result = "FunctionReferenceType" } - override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } + override int getPointerIndirectionLevel() { + result = this.getBaseType().getPointerIndirectionLevel() + } override string explain() { result = "reference to {" + this.getBaseType().(RoutineType).explain() + "}" @@ -1535,8 +1542,8 @@ class FunctionPointerIshType extends DerivedType { int getNumberOfParameters() { result = count(int i | exists(this.getParameterType(i))) } override predicate involvesTemplateParameter() { - getReturnType().involvesTemplateParameter() or - getAParameterType().involvesTemplateParameter() + this.getReturnType().involvesTemplateParameter() or + this.getAParameterType().involvesTemplateParameter() } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } @@ -1581,7 +1588,7 @@ class PointerToMemberType extends Type, @ptrtomember { this.getBaseType().explain() + "}" } - override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } + override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } } @@ -1670,8 +1677,8 @@ class RoutineType extends Type, @routinetype { override predicate isDeeplyConstBelow() { none() } // Current limitation: no such thing as a const routine type override predicate involvesTemplateParameter() { - getReturnType().involvesTemplateParameter() or - getAParameterType().involvesTemplateParameter() + this.getReturnType().involvesTemplateParameter() or + this.getAParameterType().involvesTemplateParameter() } } diff --git a/cpp/ql/lib/semmle/code/cpp/TypedefType.qll b/cpp/ql/lib/semmle/code/cpp/TypedefType.qll index aaf452ce4bb..51bcf6f6127 100644 --- a/cpp/ql/lib/semmle/code/cpp/TypedefType.qll +++ b/cpp/ql/lib/semmle/code/cpp/TypedefType.qll @@ -25,7 +25,7 @@ class TypedefType extends UserType { override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() } - override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } + override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() } override int getSize() { result = this.getBaseType().getSize() } @@ -43,11 +43,11 @@ class TypedefType extends UserType { result = this.getBaseType().getASpecifier() } - override predicate involvesReference() { getBaseType().involvesReference() } + override predicate involvesReference() { this.getBaseType().involvesReference() } - override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() } + override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() } - override Type stripType() { result = getBaseType().stripType() } + override Type stripType() { result = this.getBaseType().stripType() } } /** @@ -90,7 +90,7 @@ class UsingAliasTypedefType extends TypedefType { * ``` */ class LocalTypedefType extends TypedefType { - LocalTypedefType() { isLocal() } + LocalTypedefType() { this.isLocal() } override string getAPrimaryQlClass() { result = "LocalTypedefType" } } diff --git a/cpp/ql/lib/semmle/code/cpp/Union.qll b/cpp/ql/lib/semmle/code/cpp/Union.qll index 6dcb2f0796c..2f1b5b07b25 100644 --- a/cpp/ql/lib/semmle/code/cpp/Union.qll +++ b/cpp/ql/lib/semmle/code/cpp/Union.qll @@ -37,7 +37,7 @@ class Union extends Struct { * ``` */ class LocalUnion extends Union { - LocalUnion() { isLocal() } + LocalUnion() { this.isLocal() } override string getAPrimaryQlClass() { result = "LocalUnion" } } diff --git a/cpp/ql/lib/semmle/code/cpp/UserType.qll b/cpp/ql/lib/semmle/code/cpp/UserType.qll index 2ab0603f06c..13697722190 100644 --- a/cpp/ql/lib/semmle/code/cpp/UserType.qll +++ b/cpp/ql/lib/semmle/code/cpp/UserType.qll @@ -30,19 +30,19 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ * Gets the simple name of this type, without any template parameters. For example * if the name of the type is `"myType<int>"`, the simple name is just `"myType"`. */ - string getSimpleName() { result = getName().regexpReplaceAll("<.*", "") } + string getSimpleName() { result = this.getName().regexpReplaceAll("<.*", "") } override predicate hasName(string name) { usertypes(underlyingElement(this), name, _) } /** Holds if this type is anonymous. */ - predicate isAnonymous() { getName().matches("(unnamed%") } + predicate isAnonymous() { this.getName().matches("(unnamed%") } override predicate hasSpecifier(string s) { Type.super.hasSpecifier(s) } override Specifier getASpecifier() { result = Type.super.getASpecifier() } override Location getLocation() { - if hasDefinition() + if this.hasDefinition() then result = this.getDefinitionLocation() else result = this.getADeclarationLocation() } @@ -53,16 +53,16 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry()) } - override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } + override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() } override TypeDeclarationEntry getDefinition() { - result = getADeclarationEntry() and + result = this.getADeclarationEntry() and result.isDefinition() } override Location getDefinitionLocation() { - if exists(getDefinition()) - then result = getDefinition().getLocation() + if exists(this.getDefinition()) + then result = this.getDefinition().getLocation() else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getDefinition().getLocation() @@ -80,7 +80,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ * Holds if this is a local type (that is, a type that has a directly-enclosing * function). */ - predicate isLocal() { exists(getEnclosingFunction()) } + predicate isLocal() { exists(this.getEnclosingFunction()) } /* * Dummy implementations of inherited methods. This class must not be @@ -107,9 +107,9 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ * ``` */ class TypeDeclarationEntry extends DeclarationEntry, @type_decl { - override UserType getDeclaration() { result = getType() } + override UserType getDeclaration() { result = this.getType() } - override string getName() { result = getType().getName() } + override string getName() { result = this.getType().getName() } override string getAPrimaryQlClass() { result = "TypeDeclarationEntry" } diff --git a/cpp/ql/lib/semmle/code/cpp/Variable.qll b/cpp/ql/lib/semmle/code/cpp/Variable.qll index 12e25f33afe..b0c9bac7f66 100644 --- a/cpp/ql/lib/semmle/code/cpp/Variable.qll +++ b/cpp/ql/lib/semmle/code/cpp/Variable.qll @@ -104,17 +104,17 @@ class Variable extends Declaration, @variable { override VariableDeclarationEntry getADeclarationEntry() { result.getDeclaration() = this } - override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } + override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() } override VariableDeclarationEntry getDefinition() { - result = getADeclarationEntry() and + result = this.getADeclarationEntry() and result.isDefinition() } - override Location getDefinitionLocation() { result = getDefinition().getLocation() } + override Location getDefinitionLocation() { result = this.getDefinition().getLocation() } override Location getLocation() { - if exists(getDefinition()) + if exists(this.getDefinition()) then result = this.getDefinitionLocation() else result = this.getADeclarationLocation() } @@ -199,7 +199,7 @@ class Variable extends Declaration, @variable { * ``` */ class VariableDeclarationEntry extends DeclarationEntry, @var_decl { - override Variable getDeclaration() { result = getVariable() } + override Variable getDeclaration() { result = this.getVariable() } override string getAPrimaryQlClass() { result = "VariableDeclarationEntry" } @@ -276,32 +276,33 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry { int getIndex() { param_decl_bind(underlyingElement(this), result, _) } private string getAnonymousParameterDescription() { - not exists(getName()) and + not exists(this.getName()) and exists(string idx | idx = - ((getIndex() + 1).toString() + "th") + ((this.getIndex() + 1).toString() + "th") .replaceAll("1th", "1st") .replaceAll("2th", "2nd") .replaceAll("3th", "3rd") .replaceAll("11st", "11th") .replaceAll("12nd", "12th") .replaceAll("13rd", "13th") and - if exists(getCanonicalName()) - then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter" + if exists(this.getCanonicalName()) + then + result = "declaration of " + this.getCanonicalName() + " as anonymous " + idx + " parameter" else result = "declaration of " + idx + " parameter" ) } override string toString() { - isDefinition() and - result = "definition of " + getName() + this.isDefinition() and + result = "definition of " + this.getName() or - not isDefinition() and - if getName() = getCanonicalName() - then result = "declaration of " + getName() - else result = "declaration of " + getCanonicalName() + " as " + getName() + not this.isDefinition() and + if this.getName() = this.getCanonicalName() + then result = "declaration of " + this.getName() + else result = "declaration of " + this.getCanonicalName() + " as " + this.getName() or - result = getAnonymousParameterDescription() + result = this.getAnonymousParameterDescription() } /** @@ -311,8 +312,12 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry { */ string getTypedName() { exists(string typeString, string nameString | - (if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and - (if exists(getName()) then nameString = getName() else nameString = "") and + ( + if exists(this.getType().getName()) + then typeString = this.getType().getName() + else typeString = "" + ) and + (if exists(this.getName()) then nameString = this.getName() else nameString = "") and if typeString != "" and nameString != "" then result = typeString + " " + nameString else result = typeString + nameString @@ -540,7 +545,7 @@ class MemberVariable extends Variable, @membervariable { } /** Holds if this member is mutable. */ - predicate isMutable() { getADeclarationEntry().hasSpecifier("mutable") } + predicate isMutable() { this.getADeclarationEntry().hasSpecifier("mutable") } private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) } } diff --git a/cpp/ql/lib/semmle/code/cpp/commons/CommonType.qll b/cpp/ql/lib/semmle/code/cpp/commons/CommonType.qll index 5d6c64630a6..26e60538ec6 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/CommonType.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/CommonType.qll @@ -375,8 +375,8 @@ class Wchar_t extends Type { class MicrosoftInt8Type extends IntegralType { MicrosoftInt8Type() { this instanceof CharType and - not isExplicitlyUnsigned() and - not isExplicitlySigned() + not this.isExplicitlyUnsigned() and + not this.isExplicitlySigned() } } @@ -391,8 +391,8 @@ class MicrosoftInt8Type extends IntegralType { class MicrosoftInt16Type extends IntegralType { MicrosoftInt16Type() { this instanceof ShortType and - not isExplicitlyUnsigned() and - not isExplicitlySigned() + not this.isExplicitlyUnsigned() and + not this.isExplicitlySigned() } } @@ -407,8 +407,8 @@ class MicrosoftInt16Type extends IntegralType { class MicrosoftInt32Type extends IntegralType { MicrosoftInt32Type() { this instanceof IntType and - not isExplicitlyUnsigned() and - not isExplicitlySigned() + not this.isExplicitlyUnsigned() and + not this.isExplicitlySigned() } } @@ -423,8 +423,8 @@ class MicrosoftInt32Type extends IntegralType { class MicrosoftInt64Type extends IntegralType { MicrosoftInt64Type() { this instanceof LongLongType and - not isExplicitlyUnsigned() and - not isExplicitlySigned() + not this.isExplicitlyUnsigned() and + not this.isExplicitlySigned() } } diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll b/cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll index 1b885fb8f5f..59776d5b87a 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll @@ -33,7 +33,7 @@ DependencyOptions getDependencyOptions() { any() } class DependsSource extends Element { DependsSource() { // not inside a template instantiation - not exists(Element other | isFromTemplateInstantiation(other)) or + not exists(Element other | this.isFromTemplateInstantiation(other)) or // allow DeclarationEntrys of template specializations this.(DeclarationEntry).getDeclaration().(Function).isConstructedFrom(_) or this.(DeclarationEntry).getDeclaration().(Class).isConstructedFrom(_) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll index 46ca9ccf009..a7c72a5db8d 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.commons.StringAnalysis import semmle.code.cpp.models.interfaces.FormattingFunction class PrintfFormatAttribute extends FormatAttribute { - PrintfFormatAttribute() { getArchetype() = ["printf", "__printf__"] } + PrintfFormatAttribute() { this.getArchetype() = ["printf", "__printf__"] } } /** @@ -20,13 +20,13 @@ class AttributeFormattingFunction extends FormattingFunction { AttributeFormattingFunction() { exists(PrintfFormatAttribute printf_attrib | - printf_attrib = getAnAttribute() and + printf_attrib = this.getAnAttribute() and exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions ) } override int getFormatParameterIndex() { - forex(PrintfFormatAttribute printf_attrib | printf_attrib = getAnAttribute() | + forex(PrintfFormatAttribute printf_attrib | printf_attrib = this.getAnAttribute() | result = printf_attrib.getFormatIndex() ) } @@ -132,7 +132,7 @@ deprecated predicate variadicFormatter(Function f, int formatParamIndex) { class UserDefinedFormattingFunction extends FormattingFunction { override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" } - UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _, _, _) } + UserDefinedFormattingFunction() { this.isVarargs() and callsVariadicFormatter(this, _, _, _) } override int getFormatParameterIndex() { callsVariadicFormatter(this, _, result, _) } @@ -191,7 +191,7 @@ class FormattingFunctionCall extends Expr { exists(int i | result = this.getArgument(i) and n >= 0 and - n = i - getTarget().(FormattingFunction).getFirstFormatArgumentIndex() + n = i - this.getTarget().(FormattingFunction).getFirstFormatArgumentIndex() ) } @@ -251,7 +251,7 @@ class FormattingFunctionCall extends Expr { int getNumFormatArgument() { result = count(this.getFormatArgument(_)) and // format arguments must be known - exists(getTarget().(FormattingFunction).getFirstFormatArgumentIndex()) + exists(this.getTarget().(FormattingFunction).getFirstFormatArgumentIndex()) } /** @@ -290,7 +290,7 @@ class FormatLiteral extends Literal { * DEPRECATED: Use getDefaultCharType() instead. */ deprecated predicate isWideCharDefault() { - getUse().getTarget().(FormattingFunction).isWideCharDefault() + this.getUse().getTarget().(FormattingFunction).isWideCharDefault() } /** @@ -298,7 +298,7 @@ class FormatLiteral extends Literal { * `char` or `wchar_t`. */ Type getDefaultCharType() { - result = getUse().getTarget().(FormattingFunction).getDefaultCharType() + result = this.getUse().getTarget().(FormattingFunction).getDefaultCharType() } /** @@ -307,7 +307,7 @@ class FormatLiteral extends Literal { * which is correct for a particular function. */ Type getNonDefaultCharType() { - result = getUse().getTarget().(FormattingFunction).getNonDefaultCharType() + result = this.getUse().getTarget().(FormattingFunction).getNonDefaultCharType() } /** @@ -315,7 +315,9 @@ class FormatLiteral extends Literal { * snapshots there may be multiple results where we can't tell which is correct for a * particular function. */ - Type getWideCharType() { result = getUse().getTarget().(FormattingFunction).getWideCharType() } + Type getWideCharType() { + result = this.getUse().getTarget().(FormattingFunction).getWideCharType() + } /** * Holds if this `FormatLiteral` is in a context that supports @@ -353,7 +355,7 @@ class FormatLiteral extends Literal { } private string getFlagRegexp() { - if isMicrosoft() then result = "[-+ #0']*" else result = "[-+ #0'I]*" + if this.isMicrosoft() then result = "[-+ #0']*" else result = "[-+ #0'I]*" } private string getFieldWidthRegexp() { result = "(?:[1-9][0-9]*|\\*|\\*[0-9]+\\$)?" } @@ -361,13 +363,13 @@ class FormatLiteral extends Literal { private string getPrecRegexp() { result = "(?:\\.(?:[0-9]*|\\*|\\*[0-9]+\\$))?" } private string getLengthRegexp() { - if isMicrosoft() + if this.isMicrosoft() then result = "(?:hh?|ll?|L|q|j|z|t|w|I32|I64|I)?" else result = "(?:hh?|ll?|L|q|j|z|Z|t)?" } private string getConvCharRegexp() { - if isMicrosoft() + if this.isMicrosoft() then result = "[aAcCdeEfFgGimnopsSuxXZ@]" else result = "[aAcCdeEfFgGimnopsSuxX@]" } @@ -747,16 +749,16 @@ class FormatLiteral extends Literal { * Gets the argument type required by the nth conversion specifier. */ Type getConversionType(int n) { - result = getConversionType1(n) or - result = getConversionType1b(n) or - result = getConversionType2(n) or - result = getConversionType3(n) or - result = getConversionType4(n) or - result = getConversionType6(n) or - result = getConversionType7(n) or - result = getConversionType8(n) or - result = getConversionType9(n) or - result = getConversionType10(n) + result = this.getConversionType1(n) or + result = this.getConversionType1b(n) or + result = this.getConversionType2(n) or + result = this.getConversionType3(n) or + result = this.getConversionType4(n) or + result = this.getConversionType6(n) or + result = this.getConversionType7(n) or + result = this.getConversionType8(n) or + result = this.getConversionType9(n) or + result = this.getConversionType10(n) } private Type getConversionType1(int n) { @@ -786,15 +788,15 @@ class FormatLiteral extends Literal { or conv = ["c", "C"] and len = ["l", "w"] and - result = getWideCharType() + result = this.getWideCharType() or conv = "c" and (len != "l" and len != "w" and len != "h") and - result = getDefaultCharType() + result = this.getDefaultCharType() or conv = "C" and (len != "l" and len != "w" and len != "h") and - result = getNonDefaultCharType() + result = this.getNonDefaultCharType() ) ) } @@ -831,15 +833,15 @@ class FormatLiteral extends Literal { or conv = ["s", "S"] and len = ["l", "w"] and - result.(PointerType).getBaseType() = getWideCharType() + result.(PointerType).getBaseType() = this.getWideCharType() or conv = "s" and (len != "l" and len != "w" and len != "h") and - result.(PointerType).getBaseType() = getDefaultCharType() + result.(PointerType).getBaseType() = this.getDefaultCharType() or conv = "S" and (len != "l" and len != "w" and len != "h") and - result.(PointerType).getBaseType() = getNonDefaultCharType() + result.(PointerType).getBaseType() = this.getNonDefaultCharType() ) ) } @@ -894,19 +896,19 @@ class FormatLiteral extends Literal { exists(string len, string conv | this.parseConvSpec(n, _, _, _, _, _, len, conv) and (len != "l" and len != "w" and len != "h") and - getUse().getTarget().(FormattingFunction).getFormatCharType().getSize() > 1 and // wide function + this.getUse().getTarget().(FormattingFunction).getFormatCharType().getSize() > 1 and // wide function ( conv = "c" and - result = getNonDefaultCharType() + result = this.getNonDefaultCharType() or conv = "C" and - result = getDefaultCharType() + result = this.getDefaultCharType() or conv = "s" and - result.(PointerType).getBaseType() = getNonDefaultCharType() + result.(PointerType).getBaseType() = this.getNonDefaultCharType() or conv = "S" and - result.(PointerType).getBaseType() = getDefaultCharType() + result.(PointerType).getBaseType() = this.getDefaultCharType() ) ) } @@ -939,9 +941,13 @@ class FormatLiteral extends Literal { * not account for positional arguments (`$`). */ int getFormatArgumentIndexFor(int n, int mode) { - hasFormatArgumentIndexFor(n, mode) and + this.hasFormatArgumentIndexFor(n, mode) and (3 * n) + mode = - rank[result + 1](int n2, int mode2 | hasFormatArgumentIndexFor(n2, mode2) | (3 * n2) + mode2) + rank[result + 1](int n2, int mode2 | + this.hasFormatArgumentIndexFor(n2, mode2) + | + (3 * n2) + mode2 + ) } /** @@ -951,7 +957,7 @@ class FormatLiteral extends Literal { int getNumArgNeeded(int n) { exists(this.getConvSpecOffset(n)) and exists(this.getConversionChar(n)) and - result = count(int mode | hasFormatArgumentIndexFor(n, mode)) + result = count(int mode | this.hasFormatArgumentIndexFor(n, mode)) } /** @@ -963,7 +969,7 @@ class FormatLiteral extends Literal { // At least one conversion specifier has a parameter field, in which case, // they all should have. result = max(string s | this.getParameterField(_) = s + "$" | s.toInt()) - else result = count(int n, int mode | hasFormatArgumentIndexFor(n, mode)) + else result = count(int n, int mode | this.hasFormatArgumentIndexFor(n, mode)) } /** @@ -1053,10 +1059,10 @@ class FormatLiteral extends Literal { exists(int sizeBits | sizeBits = min(int bits | - bits = getIntegralDisplayType(n).getSize() * 8 + bits = this.getIntegralDisplayType(n).getSize() * 8 or exists(IntegralType t | - t = getUse().getConversionArgument(n).getType().getUnderlyingType() + t = this.getUse().getConversionArgument(n).getType().getUnderlyingType() | t.isSigned() and bits = t.getSize() * 8 ) @@ -1071,10 +1077,10 @@ class FormatLiteral extends Literal { exists(int sizeBits | sizeBits = min(int bits | - bits = getIntegralDisplayType(n).getSize() * 8 + bits = this.getIntegralDisplayType(n).getSize() * 8 or exists(IntegralType t | - t = getUse().getConversionArgument(n).getType().getUnderlyingType() + t = this.getUse().getConversionArgument(n).getType().getUnderlyingType() | t.isUnsigned() and bits = t.getSize() * 8 ) @@ -1089,26 +1095,26 @@ class FormatLiteral extends Literal { exists(int sizeBytes, int baseLen | sizeBytes = min(int bytes | - bytes = getIntegralDisplayType(n).getSize() + bytes = this.getIntegralDisplayType(n).getSize() or exists(IntegralType t | - t = getUse().getConversionArgument(n).getType().getUnderlyingType() + t = this.getUse().getConversionArgument(n).getType().getUnderlyingType() | t.isUnsigned() and bytes = t.getSize() ) ) and baseLen = sizeBytes * 2 and ( - if hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x" + if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x" ) ) or this.getConversionChar(n).toLowerCase() = "p" and exists(PointerType ptrType, int baseLen | - ptrType = getFullyConverted().getType() and + ptrType = this.getFullyConverted().getType() and baseLen = max(ptrType.getSize() * 2) and // e.g. "0x1234567812345678"; exact format is platform dependent ( - if hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x" + if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x" ) ) or @@ -1117,17 +1123,17 @@ class FormatLiteral extends Literal { exists(int sizeBits, int baseLen | sizeBits = min(int bits | - bits = getIntegralDisplayType(n).getSize() * 8 + bits = this.getIntegralDisplayType(n).getSize() * 8 or exists(IntegralType t | - t = getUse().getConversionArgument(n).getType().getUnderlyingType() + t = this.getUse().getConversionArgument(n).getType().getUnderlyingType() | t.isUnsigned() and bits = t.getSize() * 8 ) ) and baseLen = (sizeBits / 3.0).ceil() and ( - if hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0" + if this.hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0" ) ) or @@ -1150,8 +1156,8 @@ class FormatLiteral extends Literal { */ int getMaxConvertedLengthLimited(int n) { if this.getConversionChar(n).toLowerCase() = "f" - then result = getMaxConvertedLength(n).minimum(8) - else result = getMaxConvertedLength(n) + then result = this.getMaxConvertedLength(n).minimum(8) + else result = this.getMaxConvertedLength(n) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll b/cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll index 461030f389d..58d980318d9 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll @@ -24,7 +24,7 @@ abstract class ScanfFunction extends Function { * Holds if the default meaning of `%s` is a `wchar_t*` string * (rather than a `char*`). */ - predicate isWideCharDefault() { exists(getName().indexOf("wscanf")) } + predicate isWideCharDefault() { exists(this.getName().indexOf("wscanf")) } } /** @@ -34,10 +34,10 @@ class Scanf extends ScanfFunction { Scanf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...) - hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...) - hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...) - hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...) + this.hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...) + this.hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...) + this.hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...) + this.hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...) ) } @@ -53,10 +53,10 @@ class Fscanf extends ScanfFunction { Fscanf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...) - hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...) - hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) - hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...) + this.hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...) + this.hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...) + this.hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) + this.hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...) ) } @@ -72,10 +72,10 @@ class Sscanf extends ScanfFunction { Sscanf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...) - hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...) - hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) - hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...) + this.hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...) + this.hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...) + this.hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) + this.hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...) ) } @@ -91,10 +91,10 @@ class Snscanf extends ScanfFunction { Snscanf() { this instanceof TopLevelFunction and ( - hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...) - hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...) - hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...) - hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...) + this.hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...) + this.hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...) + this.hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...) + this.hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...) // note that the max_amount is not a limit on the output length, it's an input length // limit used with non null-terminated strings. ) @@ -120,18 +120,18 @@ class ScanfFunctionCall extends FunctionCall { /** * Gets the `scanf`-like function that is called. */ - ScanfFunction getScanfFunction() { result = getTarget() } + ScanfFunction getScanfFunction() { result = this.getTarget() } /** * Gets the position at which the input string or stream parameter occurs, * if this function call does not read from standard input. */ - int getInputParameterIndex() { result = getScanfFunction().getInputParameterIndex() } + int getInputParameterIndex() { result = this.getScanfFunction().getInputParameterIndex() } /** * Gets the position at which the format parameter occurs. */ - int getFormatParameterIndex() { result = getScanfFunction().getFormatParameterIndex() } + int getFormatParameterIndex() { result = this.getScanfFunction().getFormatParameterIndex() } /** * Gets the format expression used in this call. @@ -142,7 +142,7 @@ class ScanfFunctionCall extends FunctionCall { * Holds if the default meaning of `%s` is a `wchar_t*` string * (rather than a `char*`). */ - predicate isWideCharDefault() { getScanfFunction().isWideCharDefault() } + predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() } } /** @@ -158,7 +158,7 @@ class ScanfFormatLiteral extends Expr { ScanfFunctionCall getUse() { result.getFormat() = this } /** Holds if the default meaning of `%s` is a `wchar_t*` (rather than a `char*`). */ - predicate isWideCharDefault() { getUse().getTarget().(ScanfFunction).isWideCharDefault() } + predicate isWideCharDefault() { this.getUse().getTarget().(ScanfFunction).isWideCharDefault() } /** * Gets the format string itself, transformed as follows: diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll b/cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll index 92955ae3580..f1b9cf80d64 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll @@ -40,8 +40,8 @@ abstract class MutexType extends Type { * Gets a call that locks or tries to lock any mutex of this type. */ FunctionCall getLockAccess() { - result = getMustlockAccess() or - result = getTrylockAccess() + result = this.getMustlockAccess() or + result = this.getTrylockAccess() } /** @@ -63,22 +63,22 @@ abstract class MutexType extends Type { /** * DEPRECATED: use mustlockAccess(fc, arg) instead. */ - deprecated Function getMustlockFunction() { result = getMustlockAccess().getTarget() } + deprecated Function getMustlockFunction() { result = this.getMustlockAccess().getTarget() } /** * DEPRECATED: use trylockAccess(fc, arg) instead. */ - deprecated Function getTrylockFunction() { result = getTrylockAccess().getTarget() } + deprecated Function getTrylockFunction() { result = this.getTrylockAccess().getTarget() } /** * DEPRECATED: use lockAccess(fc, arg) instead. */ - deprecated Function getLockFunction() { result = getLockAccess().getTarget() } + deprecated Function getLockFunction() { result = this.getLockAccess().getTarget() } /** * DEPRECATED: use unlockAccess(fc, arg) instead. */ - deprecated Function getUnlockFunction() { result = getUnlockAccess().getTarget() } + deprecated Function getUnlockFunction() { result = this.getUnlockAccess().getTarget() } } /** @@ -155,17 +155,17 @@ class DefaultMutexType extends MutexType { override predicate mustlockAccess(FunctionCall fc, Expr arg) { fc.getTarget() = mustlockCandidate() and - lockArgType(fc, arg) + this.lockArgType(fc, arg) } override predicate trylockAccess(FunctionCall fc, Expr arg) { fc.getTarget() = trylockCandidate() and - lockArgType(fc, arg) + this.lockArgType(fc, arg) } override predicate unlockAccess(FunctionCall fc, Expr arg) { fc.getTarget() = unlockCandidate() and - lockArgType(fc, arg) + this.lockArgType(fc, arg) } } diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/BasicBlocks.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/BasicBlocks.qll index e235eba355b..34373d943af 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/BasicBlocks.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/BasicBlocks.qll @@ -201,7 +201,7 @@ class BasicBlock extends ControlFlowNodeBase { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn) + this.hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn) } pragma[noinline] @@ -276,7 +276,7 @@ class EntryBasicBlock extends BasicBlock { */ class ExitBasicBlock extends BasicBlock { ExitBasicBlock() { - getEnd() instanceof Function or - aborting(getEnd()) + this.getEnd() instanceof Function or + aborting(this.getEnd()) } } diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/ControlFlowGraph.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/ControlFlowGraph.qll index bac051f6474..c7b3d1dc16f 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/ControlFlowGraph.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/ControlFlowGraph.qll @@ -66,7 +66,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase { */ ControlFlowNode getATrueSuccessor() { qlCFGTrueSuccessor(this, result) and - result = getASuccessor() + result = this.getASuccessor() } /** @@ -75,7 +75,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase { */ ControlFlowNode getAFalseSuccessor() { qlCFGFalseSuccessor(this, result) and - result = getASuccessor() + result = this.getASuccessor() } /** Gets the `BasicBlock` containing this control-flow node. */ diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll index d96fc34259c..9aee2556c1d 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll @@ -121,7 +121,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { exists(boolean testIsTrue | - comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) + this.comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) ) } @@ -135,7 +135,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { exists(boolean testIsTrue | - comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) + this.comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) ) } } @@ -147,27 +147,29 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr { GuardConditionFromShortCircuitNot() { not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and - exists(IRGuardCondition ir | getOperand() = ir.getAST()) + exists(IRGuardCondition ir | this.getOperand() = ir.getAST()) } override predicate controls(BasicBlock controlled, boolean testIsTrue) { - getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot()) + this.getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot()) } override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { - getOperand().(GuardCondition).comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot()) + this.getOperand() + .(GuardCondition) + .comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot()) } override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { - getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot()) + this.getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot()) } override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { - getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot()) + this.getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot()) } override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { - getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot()) + this.getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot()) } } @@ -303,9 +305,9 @@ class IRGuardCondition extends Instruction { cached predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) { pred.getASuccessor() = succ and - controls(pred, testIsTrue) + this.controls(pred, testIsTrue) or - succ = getBranchSuccessor(testIsTrue) and + succ = this.getBranchSuccessor(testIsTrue) and branch.getCondition() = this and branch.getBlock() = pred } diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/LocalScopeVariableReachability.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/LocalScopeVariableReachability.qll index 32857146029..f6685865830 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/LocalScopeVariableReachability.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/LocalScopeVariableReachability.qll @@ -73,19 +73,19 @@ abstract deprecated class LocalScopeVariableReachability extends string { */ exists(BasicBlock bb, int i | - isSource(source, v) and + this.isSource(source, v) and bb.getNode(i) = source and not bb.isUnreachable() | exists(int j | j > i and sink = bb.getNode(j) and - isSink(sink, v) and - not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1]) + this.isSink(sink, v) and + not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1]) ) or - not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and - bbSuccessorEntryReaches(bb, v, sink, _) + not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and + this.bbSuccessorEntryReaches(bb, v, sink, _) ) } @@ -97,11 +97,11 @@ abstract deprecated class LocalScopeVariableReachability extends string { bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) | - bbEntryReachesLocally(succ, v, node) and + this.bbEntryReachesLocally(succ, v, node) and succSkipsFirstLoopAlwaysTrueUponEntry = false or - not isBarrier(succ.getNode(_), v) and - bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) + not this.isBarrier(succ.getNode(_), v) and + this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) ) } @@ -110,7 +110,7 @@ abstract deprecated class LocalScopeVariableReachability extends string { ) { exists(int n | node = bb.getNode(n) and - isSink(node, v) + this.isSink(node, v) | not exists(this.firstBarrierIndexIn(bb, v)) or @@ -119,7 +119,7 @@ abstract deprecated class LocalScopeVariableReachability extends string { } private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) { - result = min(int m | isBarrier(bb.getNode(m), v)) + result = min(int m | this.isBarrier(bb.getNode(m), v)) } } @@ -271,7 +271,7 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends * accounts for loops where the condition is provably true upon entry. */ override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { - reachesTo(source, v, sink, _) + this.reachesTo(source, v, sink, _) } /** @@ -281,21 +281,21 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0 ) { exists(ControlFlowNode def | - actualSourceReaches(source, v, def, v0) and + this.actualSourceReaches(source, v, def, v0) and LocalScopeVariableReachability.super.reaches(def, v0, sink) and - isSinkActual(sink, v0) + this.isSinkActual(sink, v0) ) } private predicate actualSourceReaches( ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0 ) { - isSourceActual(source, v) and def = source and v0 = v + this.isSourceActual(source, v) and def = source and v0 = v or exists(ControlFlowNode source1, SemanticStackVariable v1 | - actualSourceReaches(source, v, source1, v1) + this.actualSourceReaches(source, v, source1, v1) | - reassignment(source1, v1, def, v0) + this.reassignment(source1, v1, def, v0) ) } @@ -307,14 +307,14 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends } final override predicate isSource(ControlFlowNode node, LocalScopeVariable v) { - isSourceActual(node, v) + this.isSourceActual(node, v) or // Reassignment generates a new (non-actual) source - reassignment(_, _, node, v) + this.reassignment(_, _, node, v) } final override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { - isSinkActual(node, v) + this.isSinkActual(node, v) or // Reassignment generates a new (non-actual) sink exprDefinition(_, node, v.getAnAccess()) @@ -347,21 +347,21 @@ abstract deprecated class LocalScopeVariableReachabilityExt extends string { /** See `LocalScopeVariableReachability.reaches`. */ predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { exists(BasicBlock bb, int i | - isSource(source, v) and + this.isSource(source, v) and bb.getNode(i) = source and not bb.isUnreachable() | exists(int j | j > i and sink = bb.getNode(j) and - isSink(sink, v) and - not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | + this.isSink(sink, v) and + not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k in [i .. j - 1] ) ) or - not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and - bbSuccessorEntryReaches(source, bb, v, sink, _) + not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and + this.bbSuccessorEntryReaches(source, bb, v, sink, _) ) } @@ -372,22 +372,22 @@ abstract deprecated class LocalScopeVariableReachabilityExt extends string { exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) and - not isBarrier(source, bb.getEnd(), succ.getStart(), v) + not this.isBarrier(source, bb.getEnd(), succ.getStart(), v) | - bbEntryReachesLocally(source, succ, v, node) and + this.bbEntryReachesLocally(source, succ, v, node) and succSkipsFirstLoopAlwaysTrueUponEntry = false or - not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and - bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) + not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and + this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) ) } private predicate bbEntryReachesLocally( ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node ) { - isSource(source, v) and - exists(int n | node = bb.getNode(n) and isSink(node, v) | - not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v)) + this.isSource(source, v) and + exists(int n | node = bb.getNode(n) and this.isSink(node, v) | + not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v)) ) } } diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/SSA.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/SSA.qll index 5c0f6b3ac14..49805b9fb3c 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/SSA.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/SSA.qll @@ -59,7 +59,7 @@ class SsaDefinition extends ControlFlowNodeBase { ControlFlowNode getDefinition() { result = this } /** Gets the `BasicBlock` containing this definition. */ - BasicBlock getBasicBlock() { result.contains(getDefinition()) } + BasicBlock getBasicBlock() { result.contains(this.getDefinition()) } /** Holds if this definition is a phi node for variable `v`. */ predicate isPhiNode(StackVariable v) { exists(StandardSSA x | x.phi_node(v, this.(BasicBlock))) } diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/StackVariableReachability.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/StackVariableReachability.qll index 6c50d254faa..7b5fcd504b1 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/StackVariableReachability.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/StackVariableReachability.qll @@ -72,19 +72,19 @@ abstract class StackVariableReachability extends string { */ exists(BasicBlock bb, int i | - isSource(source, v) and + this.isSource(source, v) and bb.getNode(i) = source and not bb.isUnreachable() | exists(int j | j > i and sink = bb.getNode(j) and - isSink(sink, v) and - not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1]) + this.isSink(sink, v) and + not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1]) ) or - not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and - bbSuccessorEntryReaches(bb, v, sink, _) + not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and + this.bbSuccessorEntryReaches(bb, v, sink, _) ) } @@ -96,11 +96,11 @@ abstract class StackVariableReachability extends string { bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) | - bbEntryReachesLocally(succ, v, node) and + this.bbEntryReachesLocally(succ, v, node) and succSkipsFirstLoopAlwaysTrueUponEntry = false or - not isBarrier(succ.getNode(_), v) and - bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) + not this.isBarrier(succ.getNode(_), v) and + this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) ) } @@ -109,7 +109,7 @@ abstract class StackVariableReachability extends string { ) { exists(int n | node = bb.getNode(n) and - isSink(node, v) + this.isSink(node, v) | not exists(this.firstBarrierIndexIn(bb, v)) or @@ -118,7 +118,7 @@ abstract class StackVariableReachability extends string { } private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) { - result = min(int m | isBarrier(bb.getNode(m), v)) + result = min(int m | this.isBarrier(bb.getNode(m), v)) } } @@ -268,7 +268,7 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe * accounts for loops where the condition is provably true upon entry. */ override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { - reachesTo(source, v, sink, _) + this.reachesTo(source, v, sink, _) } /** @@ -278,21 +278,21 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0 ) { exists(ControlFlowNode def | - actualSourceReaches(source, v, def, v0) and + this.actualSourceReaches(source, v, def, v0) and StackVariableReachability.super.reaches(def, v0, sink) and - isSinkActual(sink, v0) + this.isSinkActual(sink, v0) ) } private predicate actualSourceReaches( ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0 ) { - isSourceActual(source, v) and def = source and v0 = v + this.isSourceActual(source, v) and def = source and v0 = v or exists(ControlFlowNode source1, SemanticStackVariable v1 | - actualSourceReaches(source, v, source1, v1) + this.actualSourceReaches(source, v, source1, v1) | - reassignment(source1, v1, def, v0) + this.reassignment(source1, v1, def, v0) ) } @@ -304,14 +304,14 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe } final override predicate isSource(ControlFlowNode node, StackVariable v) { - isSourceActual(node, v) + this.isSourceActual(node, v) or // Reassignment generates a new (non-actual) source - reassignment(_, _, node, v) + this.reassignment(_, _, node, v) } final override predicate isSink(ControlFlowNode node, StackVariable v) { - isSinkActual(node, v) + this.isSinkActual(node, v) or // Reassignment generates a new (non-actual) sink exprDefinition(_, node, v.getAnAccess()) @@ -342,21 +342,21 @@ abstract class StackVariableReachabilityExt extends string { /** See `StackVariableReachability.reaches`. */ predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { exists(BasicBlock bb, int i | - isSource(source, v) and + this.isSource(source, v) and bb.getNode(i) = source and not bb.isUnreachable() | exists(int j | j > i and sink = bb.getNode(j) and - isSink(sink, v) and - not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | + this.isSink(sink, v) and + not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k in [i .. j - 1] ) ) or - not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and - bbSuccessorEntryReaches(source, bb, v, sink, _) + not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and + this.bbSuccessorEntryReaches(source, bb, v, sink, _) ) } @@ -367,22 +367,22 @@ abstract class StackVariableReachabilityExt extends string { exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) and - not isBarrier(source, bb.getEnd(), succ.getStart(), v) + not this.isBarrier(source, bb.getEnd(), succ.getStart(), v) | - bbEntryReachesLocally(source, succ, v, node) and + this.bbEntryReachesLocally(source, succ, v, node) and succSkipsFirstLoopAlwaysTrueUponEntry = false or - not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and - bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) + not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and + this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) ) } private predicate bbEntryReachesLocally( ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node ) { - isSource(source, v) and - exists(int n | node = bb.getNode(n) and isSink(node, v) | - not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v)) + this.isSource(source, v) and + exists(int n | node = bb.getNode(n) and this.isSink(node, v) | + not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v)) ) } } diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll index fa9d2e94081..4fbea43b805 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll @@ -80,7 +80,7 @@ class SubBasicBlock extends ControlFlowNodeBase { * returns a 0-based position, while `getRankInBasicBlock` returns a 1-based * position. */ - deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 } + deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 } pragma[noinline] private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) } @@ -102,7 +102,7 @@ class SubBasicBlock extends ControlFlowNodeBase { exists(BasicBlock bb | exists(int outerIndex | result = bb.getNode(outerIndex) and - index = outerToInnerIndex(bb, outerIndex) + index = this.outerToInnerIndex(bb, outerIndex) ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll index ff27baae965..da5204bb063 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll @@ -385,7 +385,7 @@ library class ExprEvaluator extends int { abstract predicate interesting(Expr e); /** Gets the value of (interesting) expression `e`, if any. */ - int getValue(Expr e) { result = getValueInternal(e, e) } + int getValue(Expr e) { result = this.getValueInternal(e, e) } /** * When evaluating a syntactic subexpression of `e`, we may @@ -425,9 +425,9 @@ library class ExprEvaluator extends int { * calculates the values bottom-up. */ predicate interestingInternal(Expr e, Expr req, boolean sub) { - interesting(e) and req = e and sub = true + this.interesting(e) and req = e and sub = true or - exists(Expr mid | interestingInternal(e, mid, sub) | + exists(Expr mid | this.interestingInternal(e, mid, sub) | req = mid.(NotExpr).getOperand() or req = mid.(BinaryLogicalOperation).getAnOperand() or req = mid.(RelationalOperation).getAnOperand() or @@ -442,36 +442,36 @@ library class ExprEvaluator extends int { ) or exists(VariableAccess va, Variable v, boolean sub1 | - interestingVariableAccess(e, va, v, sub1) and + this.interestingVariableAccess(e, va, v, sub1) and req = v.getAnAssignedValue() and - (sub1 = true implies not ignoreVariableAssignment(e, v, req)) and + (sub1 = true implies not this.ignoreVariableAssignment(e, v, req)) and sub = false ) or exists(Function f | - interestingFunction(e, f) and + this.interestingFunction(e, f) and returnStmt(f, req) and sub = false ) } private predicate interestingVariableAccess(Expr e, VariableAccess va, Variable v, boolean sub) { - interestingInternal(e, va, sub) and + this.interestingInternal(e, va, sub) and v = getVariableTarget(va) and ( v.hasInitializer() or - sub = true and allowVariableWithoutInitializer(e, v) + sub = true and this.allowVariableWithoutInitializer(e, v) ) and tractableVariable(v) and forall(StmtParent def | nonAnalyzableVariableDefinition(v, def) | sub = true and - ignoreNonAnalyzableVariableDefinition(e, v, def) + this.ignoreNonAnalyzableVariableDefinition(e, v, def) ) } private predicate interestingFunction(Expr e, Function f) { - exists(FunctionCall fc | interestingInternal(e, fc, _) | + exists(FunctionCall fc | this.interestingInternal(e, fc, _) | f = fc.getTarget() and not obviouslyNonConstant(f) and not f.getUnspecifiedType() instanceof VoidType @@ -481,10 +481,10 @@ library class ExprEvaluator extends int { /** Gets the value of subexpressions `req` for expression `e`, if any. */ private int getValueInternal(Expr e, Expr req) { ( - interestingInternal(e, req, true) and + this.interestingInternal(e, req, true) and ( result = req.(CompileTimeConstantInt).getIntValue() or - result = getCompoundValue(e, req.(CompileTimeVariableExpr)) + result = this.getCompoundValue(e, req.(CompileTimeVariableExpr)) ) and ( req.getUnderlyingType().(IntegralType).isSigned() or @@ -495,109 +495,126 @@ library class ExprEvaluator extends int { /** Gets the value of compound subexpressions `val` for expression `e`, if any. */ private int getCompoundValue(Expr e, CompileTimeVariableExpr val) { - interestingInternal(e, val, true) and + this.interestingInternal(e, val, true) and ( exists(NotExpr req | req = val | - result = 1 and getValueInternal(e, req.getOperand()) = 0 + result = 1 and this.getValueInternal(e, req.getOperand()) = 0 or - result = 0 and getValueInternal(e, req.getOperand()) != 0 + result = 0 and this.getValueInternal(e, req.getOperand()) != 0 ) or exists(LogicalAndExpr req | req = val | result = 1 and - getValueInternal(e, req.getLeftOperand()) != 0 and - getValueInternal(e, req.getRightOperand()) != 0 + this.getValueInternal(e, req.getLeftOperand()) != 0 and + this.getValueInternal(e, req.getRightOperand()) != 0 or - result = 0 and getValueInternal(e, req.getAnOperand()) = 0 + result = 0 and this.getValueInternal(e, req.getAnOperand()) = 0 ) or exists(LogicalOrExpr req | req = val | - result = 1 and getValueInternal(e, req.getAnOperand()) != 0 + result = 1 and this.getValueInternal(e, req.getAnOperand()) != 0 or result = 0 and - getValueInternal(e, req.getLeftOperand()) = 0 and - getValueInternal(e, req.getRightOperand()) = 0 + this.getValueInternal(e, req.getLeftOperand()) = 0 and + this.getValueInternal(e, req.getRightOperand()) = 0 ) or exists(LTExpr req | req = val | result = 1 and - getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) < + this.getValueInternal(e, req.getRightOperand()) or result = 0 and - getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) >= + this.getValueInternal(e, req.getRightOperand()) ) or exists(GTExpr req | req = val | result = 1 and - getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) > + this.getValueInternal(e, req.getRightOperand()) or result = 0 and - getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) <= + this.getValueInternal(e, req.getRightOperand()) ) or exists(LEExpr req | req = val | result = 1 and - getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) <= + this.getValueInternal(e, req.getRightOperand()) or result = 0 and - getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) > + this.getValueInternal(e, req.getRightOperand()) ) or exists(GEExpr req | req = val | result = 1 and - getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) >= + this.getValueInternal(e, req.getRightOperand()) or result = 0 and - getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) < + this.getValueInternal(e, req.getRightOperand()) ) or exists(EQExpr req | req = val | result = 1 and - getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) = + this.getValueInternal(e, req.getRightOperand()) or result = 0 and - getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) != + this.getValueInternal(e, req.getRightOperand()) ) or exists(NEExpr req | req = val | result = 0 and - getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) = + this.getValueInternal(e, req.getRightOperand()) or result = 1 and - getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) != + this.getValueInternal(e, req.getRightOperand()) ) or exists(AddExpr req | req = val | result = - getValueInternal(e, req.getLeftOperand()) + getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) + + this.getValueInternal(e, req.getRightOperand()) ) or exists(SubExpr req | req = val | result = - getValueInternal(e, req.getLeftOperand()) - getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) - + this.getValueInternal(e, req.getRightOperand()) ) or exists(MulExpr req | req = val | result = - getValueInternal(e, req.getLeftOperand()) * getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) * + this.getValueInternal(e, req.getRightOperand()) ) or exists(RemExpr req | req = val | result = - getValueInternal(e, req.getLeftOperand()) % getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) % + this.getValueInternal(e, req.getRightOperand()) ) or exists(DivExpr req | req = val | result = - getValueInternal(e, req.getLeftOperand()) / getValueInternal(e, req.getRightOperand()) + this.getValueInternal(e, req.getLeftOperand()) / + this.getValueInternal(e, req.getRightOperand()) ) or - exists(AssignExpr req | req = val | result = getValueInternal(e, req.getRValue())) + exists(AssignExpr req | req = val | result = this.getValueInternal(e, req.getRValue())) or - result = getVariableValue(e, val.(VariableAccess)) + result = this.getVariableValue(e, val.(VariableAccess)) or exists(FunctionCall call | call = val and not callWithMultipleTargets(call) | - result = getFunctionValue(call.getTarget()) + result = this.getFunctionValue(call.getTarget()) ) ) } @@ -605,7 +622,7 @@ library class ExprEvaluator extends int { language[monotonicAggregates] private int getVariableValue(Expr e, VariableAccess va) { exists(Variable v | - interestingVariableAccess(e, va, v, true) and + this.interestingVariableAccess(e, va, v, true) and // All assignments must have the same int value result = unique(Expr value | @@ -619,14 +636,16 @@ library class ExprEvaluator extends int { /** Holds if the function `f` is considered by the analysis and may return `ret`. */ pragma[noinline] private predicate interestingReturnValue(Function f, Expr ret) { - interestingFunction(_, f) and + this.interestingFunction(_, f) and returnStmt(f, ret) } private int getFunctionValue(Function f) { // All returns must have the same int value // And it must have at least one return - forex(Expr ret | interestingReturnValue(f, ret) | result = getValueInternalNonSubExpr(ret)) + forex(Expr ret | this.interestingReturnValue(f, ret) | + result = this.getValueInternalNonSubExpr(ret) + ) } /** @@ -641,10 +660,10 @@ library class ExprEvaluator extends int { * omitted). */ private int getValueInternalNonSubExpr(Expr req) { - interestingInternal(_, req, false) and + this.interestingInternal(_, req, false) and ( result = req.(CompileTimeConstantInt).getIntValue() or - result = getCompoundValueNonSubExpr(req.(CompileTimeVariableExpr)) + result = this.getCompoundValueNonSubExpr(req.(CompileTimeVariableExpr)) ) and ( req.getUnderlyingType().(IntegralType).isSigned() or @@ -655,131 +674,131 @@ library class ExprEvaluator extends int { private int getCompoundValueNonSubExpr(CompileTimeVariableExpr val) { ( exists(NotExpr req | req = val | - result = 1 and getValueInternalNonSubExpr(req.getOperand()) = 0 + result = 1 and this.getValueInternalNonSubExpr(req.getOperand()) = 0 or - result = 0 and getValueInternalNonSubExpr(req.getOperand()) != 0 + result = 0 and this.getValueInternalNonSubExpr(req.getOperand()) != 0 ) or exists(LogicalAndExpr req | req = val | result = 1 and - getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and - getValueInternalNonSubExpr(req.getRightOperand()) != 0 + this.getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and + this.getValueInternalNonSubExpr(req.getRightOperand()) != 0 or - result = 0 and getValueInternalNonSubExpr(req.getAnOperand()) = 0 + result = 0 and this.getValueInternalNonSubExpr(req.getAnOperand()) = 0 ) or exists(LogicalOrExpr req | req = val | - result = 1 and getValueInternalNonSubExpr(req.getAnOperand()) != 0 + result = 1 and this.getValueInternalNonSubExpr(req.getAnOperand()) != 0 or result = 0 and - getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and - getValueInternalNonSubExpr(req.getRightOperand()) = 0 + this.getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and + this.getValueInternalNonSubExpr(req.getRightOperand()) = 0 ) or exists(LTExpr req | req = val | result = 1 and - getValueInternalNonSubExpr(req.getLeftOperand()) < - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) < + this.getValueInternalNonSubExpr(req.getRightOperand()) or result = 0 and - getValueInternalNonSubExpr(req.getLeftOperand()) >= - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) >= + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(GTExpr req | req = val | result = 1 and - getValueInternalNonSubExpr(req.getLeftOperand()) > - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) > + this.getValueInternalNonSubExpr(req.getRightOperand()) or result = 0 and - getValueInternalNonSubExpr(req.getLeftOperand()) <= - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) <= + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(LEExpr req | req = val | result = 1 and - getValueInternalNonSubExpr(req.getLeftOperand()) <= - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) <= + this.getValueInternalNonSubExpr(req.getRightOperand()) or result = 0 and - getValueInternalNonSubExpr(req.getLeftOperand()) > - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) > + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(GEExpr req | req = val | result = 1 and - getValueInternalNonSubExpr(req.getLeftOperand()) >= - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) >= + this.getValueInternalNonSubExpr(req.getRightOperand()) or result = 0 and - getValueInternalNonSubExpr(req.getLeftOperand()) < - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) < + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(EQExpr req | req = val | result = 1 and - getValueInternalNonSubExpr(req.getLeftOperand()) = - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) = + this.getValueInternalNonSubExpr(req.getRightOperand()) or result = 0 and - getValueInternalNonSubExpr(req.getLeftOperand()) != - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) != + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(NEExpr req | req = val | result = 0 and - getValueInternalNonSubExpr(req.getLeftOperand()) = - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) = + this.getValueInternalNonSubExpr(req.getRightOperand()) or result = 1 and - getValueInternalNonSubExpr(req.getLeftOperand()) != - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) != + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(AddExpr req | req = val | result = - getValueInternalNonSubExpr(req.getLeftOperand()) + - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) + + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(SubExpr req | req = val | result = - getValueInternalNonSubExpr(req.getLeftOperand()) - - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) - + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(MulExpr req | req = val | result = - getValueInternalNonSubExpr(req.getLeftOperand()) * - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) * + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(RemExpr req | req = val | result = - getValueInternalNonSubExpr(req.getLeftOperand()) % - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) % + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or exists(DivExpr req | req = val | result = - getValueInternalNonSubExpr(req.getLeftOperand()) / - getValueInternalNonSubExpr(req.getRightOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) / + this.getValueInternalNonSubExpr(req.getRightOperand()) ) or - exists(AssignExpr req | req = val | result = getValueInternalNonSubExpr(req.getRValue())) + exists(AssignExpr req | req = val | result = this.getValueInternalNonSubExpr(req.getRValue())) or - result = getVariableValueNonSubExpr(val.(VariableAccess)) + result = this.getVariableValueNonSubExpr(val.(VariableAccess)) or exists(FunctionCall call | call = val and not callWithMultipleTargets(call) | - result = getFunctionValue(call.getTarget()) + result = this.getFunctionValue(call.getTarget()) ) ) } private int getVariableValueNonSubExpr(VariableAccess va) { // All assignments must have the same int value - result = getMinVariableValueNonSubExpr(va) and - result = getMaxVariableValueNonSubExpr(va) + result = this.getMinVariableValueNonSubExpr(va) and + result = this.getMaxVariableValueNonSubExpr(va) } /** @@ -790,8 +809,9 @@ library class ExprEvaluator extends int { pragma[noopt] private int getMinVariableValueNonSubExpr(VariableAccess va) { exists(Variable v | - interestingVariableAccess(_, va, v, false) and - result = min(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value)) + this.interestingVariableAccess(_, va, v, false) and + result = + min(Expr value | value = v.getAnAssignedValue() | this.getValueInternalNonSubExpr(value)) ) } @@ -803,8 +823,9 @@ library class ExprEvaluator extends int { pragma[noopt] private int getMaxVariableValueNonSubExpr(VariableAccess va) { exists(Variable v | - interestingVariableAccess(_, va, v, false) and - result = max(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value)) + this.interestingVariableAccess(_, va, v, false) and + result = + max(Expr value | value = v.getAnAssignedValue() | this.getValueInternalNonSubExpr(value)) ) } } @@ -967,9 +988,9 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { abstract predicate isLoopBody(Expr e, StmtParent s); private predicate isLoopBodyDescendant(Expr e, StmtParent s) { - isLoopBody(e, s) + this.isLoopBody(e, s) or - exists(StmtParent mid | isLoopBodyDescendant(e, mid) | + exists(StmtParent mid | this.isLoopBodyDescendant(e, mid) | s = mid.(Stmt).getAChild() or s = mid.(Expr).getAChild() ) @@ -977,13 +998,13 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { // Same as `interestingInternal(e, sub, true)` but avoids negative recursion private predicate interestingSubExpr(Expr e, Expr sub) { - interesting(e) and e = sub + this.interesting(e) and e = sub or - exists(Expr mid | interestingSubExpr(e, mid) and sub = mid.getAChild()) + exists(Expr mid | this.interestingSubExpr(e, mid) and sub = mid.getAChild()) } private predicate maybeInterestingVariable(Expr e, Variable v) { - exists(VariableAccess va | interestingSubExpr(e, va) | va.getTarget() = v) + exists(VariableAccess va | this.interestingSubExpr(e, va) | va.getTarget() = v) } /** @@ -995,9 +1016,9 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { * definition of `v`. */ private predicate reachesLoopEntryFromLoopBody(Expr e, Variable v, StmtParent valueOrDef) { - maybeInterestingVariable(e, v) and + this.maybeInterestingVariable(e, v) and (valueOrDef = v.getAnAssignedValue() or nonAnalyzableVariableDefinition(v, valueOrDef)) and - isLoopBodyDescendant(e, valueOrDef) and + this.isLoopBodyDescendant(e, valueOrDef) and /* * Use primitive basic blocks in reachability analysis for better performance. * This is similar to the pattern used in e.g. `DefinitionsAndUses` and @@ -1007,16 +1028,16 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { exists(PrimitiveBasicBlock bb1, int pos1 | bb1.getNode(pos1) = valueOrDef | // Reaches in same basic block exists(int pos2 | - loopEntryAt(bb1, pos2, e) and + this.loopEntryAt(bb1, pos2, e) and pos2 > pos1 and - not exists(int k | assignmentAt(bb1, k, v) | k in [pos1 + 1 .. pos2 - 1]) + not exists(int k | this.assignmentAt(bb1, k, v) | k in [pos1 + 1 .. pos2 - 1]) ) or // Reaches in a successor block exists(PrimitiveBasicBlock bb2 | bb2 = bb1.getASuccessor() and - not exists(int pos3 | assignmentAt(bb1, pos3, v) and pos3 > pos1) and - bbReachesLoopEntry(bb2, e, v) + not exists(int pos3 | this.assignmentAt(bb1, pos3, v) and pos3 > pos1) and + this.bbReachesLoopEntry(bb2, e, v) ) ) } @@ -1024,12 +1045,12 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { private predicate loopEntryAt(PrimitiveBasicBlock bb, int pos, Expr e) { exists(Node cfn | bb.getNode(pos) = cfn and - isLoopEntry(e, cfn) + this.isLoopEntry(e, cfn) ) } private predicate assignmentAt(PrimitiveBasicBlock bb, int pos, Variable v) { - maybeInterestingVariable(_, v) and + this.maybeInterestingVariable(_, v) and bb.getNode(pos) = v.getAnAssignedValue() } @@ -1038,19 +1059,19 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { * the loop belonging to `e` without crossing an assignment to `v`. */ private predicate bbReachesLoopEntry(PrimitiveBasicBlock bb, Expr e, Variable v) { - bbReachesLoopEntryLocally(bb, e, v) + this.bbReachesLoopEntryLocally(bb, e, v) or exists(PrimitiveBasicBlock succ | succ = bb.getASuccessor() | - bbReachesLoopEntry(succ, e, v) and - not assignmentAt(bb, _, v) + this.bbReachesLoopEntry(succ, e, v) and + not this.assignmentAt(bb, _, v) ) } private predicate bbReachesLoopEntryLocally(PrimitiveBasicBlock bb, Expr e, Variable v) { exists(int pos | - loopEntryAt(bb, pos, e) and - maybeInterestingVariable(e, v) and - not exists(int pos1 | assignmentAt(bb, pos1, v) | pos1 < pos) + this.loopEntryAt(bb, pos, e) and + this.maybeInterestingVariable(e, v) and + not exists(int pos1 | this.assignmentAt(bb, pos1, v) | pos1 < pos) ) } @@ -1084,10 +1105,10 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { * ``` */ override predicate ignoreNonAnalyzableVariableDefinition(Expr e, Variable v, StmtParent def) { - maybeInterestingVariable(e, v) and + this.maybeInterestingVariable(e, v) and nonAnalyzableVariableDefinition(v, def) and - isLoopBodyDescendant(e, def) and - not reachesLoopEntryFromLoopBody(e, v, def) + this.isLoopBodyDescendant(e, def) and + not this.reachesLoopEntryFromLoopBody(e, v, def) } /** @@ -1120,10 +1141,10 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { * ``` */ override predicate ignoreVariableAssignment(Expr e, Variable v, Expr value) { - maybeInterestingVariable(e, v) and + this.maybeInterestingVariable(e, v) and value = v.getAnAssignedValue() and - isLoopBodyDescendant(e, value) and - not reachesLoopEntryFromLoopBody(e, v, value) + this.isLoopBodyDescendant(e, value) and + not this.reachesLoopEntryFromLoopBody(e, v, value) } } 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 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index 2dfd02d14ef..c67374c3db9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -106,13 +106,13 @@ class Node extends TNode { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } /** * Gets an upper bound on the type of this node. */ - Type getTypeBound() { result = getType() } + Type getTypeBound() { result = this.getType() } } /** @@ -293,11 +293,11 @@ abstract class PostUpdateNode extends Node { */ abstract Node getPreUpdateNode(); - override Function getFunction() { result = getPreUpdateNode().getFunction() } + override Function getFunction() { result = this.getPreUpdateNode().getFunction() } - override Type getType() { result = getPreUpdateNode().getType() } + override Type getType() { result = this.getPreUpdateNode().getType() } - override Location getLocation() { result = getPreUpdateNode().getLocation() } + override Location getLocation() { result = this.getPreUpdateNode().getLocation() } } abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { @@ -309,7 +309,7 @@ abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDef PartialDefinition getPartialDefinition() { result = pd } - override string toString() { result = getPreUpdateNode().toString() + " [post update]" } + override string toString() { result = this.getPreUpdateNode().toString() + " [post update]" } } private class VariablePartialDefinitionNode extends PartialDefinitionNode { @@ -380,13 +380,13 @@ private class ObjectInitializerNode extends PostUpdateNode, TExprNode { class PreObjectInitializerNode extends Node, TPreObjectInitializerNode { Expr getExpr() { this = TPreObjectInitializerNode(result) } - override Function getFunction() { result = getExpr().getEnclosingFunction() } + override Function getFunction() { result = this.getExpr().getEnclosingFunction() } - override Type getType() { result = getExpr().getType() } + override Type getType() { result = this.getExpr().getType() } - override Location getLocation() { result = getExpr().getLocation() } + override Location getLocation() { result = this.getExpr().getLocation() } - override string toString() { result = getExpr().toString() + " [pre init]" } + override string toString() { result = this.getExpr().toString() + " [pre init]" } } /** @@ -401,7 +401,7 @@ private class PostConstructorInitThis extends PostUpdateNode, TPostConstructorIn } override string toString() { - result = getPreUpdateNode().getConstructorFieldInit().toString() + " [post-this]" + result = this.getPreUpdateNode().getConstructorFieldInit().toString() + " [post-this]" } } @@ -416,15 +416,17 @@ private class PostConstructorInitThis extends PostUpdateNode, TPostConstructorIn class PreConstructorInitThis extends Node, TPreConstructorInitThis { ConstructorFieldInit getConstructorFieldInit() { this = TPreConstructorInitThis(result) } - override Constructor getFunction() { result = getConstructorFieldInit().getEnclosingFunction() } - - override PointerType getType() { - result.getBaseType() = getConstructorFieldInit().getEnclosingFunction().getDeclaringType() + override Constructor getFunction() { + result = this.getConstructorFieldInit().getEnclosingFunction() } - override Location getLocation() { result = getConstructorFieldInit().getLocation() } + override PointerType getType() { + result.getBaseType() = this.getConstructorFieldInit().getEnclosingFunction().getDeclaringType() + } - override string toString() { result = getConstructorFieldInit().toString() + " [pre-this]" } + override Location getLocation() { result = this.getConstructorFieldInit().getLocation() } + + override string toString() { result = this.getConstructorFieldInit().toString() + " [pre-this]" } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll index e3f8b6f68fb..c01edf0429a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -354,7 +354,7 @@ module FlowVar_internal { result = def.getAUse(v) or exists(SsaDefinition descendentDef | - getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and + this.getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and result = descendentDef.getAUse(v) ) ) @@ -515,7 +515,7 @@ module FlowVar_internal { this.bbInLoopCondition(bbInside) and not this.bbInLoop(bbOutside) and bbOutside = bbInside.getASuccessor() and - not reachesWithoutAssignment(bbInside, v) + not this.reachesWithoutAssignment(bbInside, v) } /** @@ -546,7 +546,7 @@ module FlowVar_internal { private predicate bbInLoop(BasicBlock bb) { bbDominates(this.(Loop).getStmt(), bb) or - bbInLoopCondition(bb) + this.bbInLoopCondition(bb) } /** Holds if `sbb` is inside this loop. */ @@ -563,7 +563,7 @@ module FlowVar_internal { bb = this.(Loop).getStmt() and v = this.getARelevantVariable() or - reachesWithoutAssignment(bb.getAPredecessor(), v) and + this.reachesWithoutAssignment(bb.getAPredecessor(), v) and this.bbInLoop(bb) ) and not assignsToVar(bb, v) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll index fa9d2e94081..4fbea43b805 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll @@ -80,7 +80,7 @@ class SubBasicBlock extends ControlFlowNodeBase { * returns a 0-based position, while `getRankInBasicBlock` returns a 1-based * position. */ - deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 } + deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 } pragma[noinline] private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) } @@ -102,7 +102,7 @@ class SubBasicBlock extends ControlFlowNodeBase { exists(BasicBlock bb | exists(int outerIndex | result = bb.getNode(outerIndex) and - index = outerToInnerIndex(bb, outerIndex) + index = this.outerToInnerIndex(bb, outerIndex) ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll index e18c0c78dc6..35cf1974127 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll @@ -203,7 +203,7 @@ class PointerFieldAccess extends FieldAccess { PointerFieldAccess() { exists(PointerType t | - t = getQualifier().getFullyConverted().getUnspecifiedType() and + t = this.getQualifier().getFullyConverted().getUnspecifiedType() and t.getBaseType() instanceof Class ) } @@ -218,7 +218,9 @@ class PointerFieldAccess extends FieldAccess { class DotFieldAccess extends FieldAccess { override string getAPrimaryQlClass() { result = "DotFieldAccess" } - DotFieldAccess() { exists(Class c | c = getQualifier().getFullyConverted().getUnspecifiedType()) } + DotFieldAccess() { + exists(Class c | c = this.getQualifier().getFullyConverted().getUnspecifiedType()) + } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/ArithmeticOperation.qll b/cpp/ql/lib/semmle/code/cpp/exprs/ArithmeticOperation.qll index b94c9cee724..615192c86a7 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/ArithmeticOperation.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/ArithmeticOperation.qll @@ -148,7 +148,7 @@ class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @post override int getPrecedence() { result = 17 } - override string toString() { result = "... " + getOperator() } + override string toString() { result = "... " + this.getOperator() } } /** @@ -166,7 +166,7 @@ class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @post override int getPrecedence() { result = 17 } - override string toString() { result = "... " + getOperator() } + override string toString() { result = "... " + this.getOperator() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/BuiltInOperations.qll b/cpp/ql/lib/semmle/code/cpp/exprs/BuiltInOperations.qll index b1f97f18802..dcbedde4475 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/BuiltInOperations.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/BuiltInOperations.qll @@ -35,12 +35,12 @@ class BuiltInVarArgsStart extends VarArgsExpr, @vastartexpr { /** * Gets the `va_list` argument. */ - final Expr getVAList() { result = getChild(0) } + final Expr getVAList() { result = this.getChild(0) } /** * Gets the argument that specifies the last named parameter before the ellipsis. */ - final VariableAccess getLastNamedParameter() { result = getChild(1) } + final VariableAccess getLastNamedParameter() { result = this.getChild(1) } } /** @@ -60,7 +60,7 @@ class BuiltInVarArgsEnd extends VarArgsExpr, @vaendexpr { /** * Gets the `va_list` argument. */ - final Expr getVAList() { result = getChild(0) } + final Expr getVAList() { result = this.getChild(0) } } /** @@ -78,7 +78,7 @@ class BuiltInVarArg extends VarArgsExpr, @vaargexpr { /** * Gets the `va_list` argument. */ - final Expr getVAList() { result = getChild(0) } + final Expr getVAList() { result = this.getChild(0) } } /** @@ -98,12 +98,12 @@ class BuiltInVarArgCopy extends VarArgsExpr, @vacopyexpr { /** * Gets the destination `va_list` argument. */ - final Expr getDestinationVAList() { result = getChild(0) } + final Expr getDestinationVAList() { result = this.getChild(0) } /** * Gets the the source `va_list` argument. */ - final Expr getSourceVAList() { result = getChild(1) } + final Expr getSourceVAList() { result = this.getChild(1) } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll index 6f6f710ac4b..b4761dffe9a 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll @@ -71,10 +71,10 @@ class Call extends Expr, NameQualifiableElement, TCall { * at index 2, respectively. */ Expr getAnArgumentSubExpr(int index) { - result = getArgument(index) + result = this.getArgument(index) or exists(Expr mid | - mid = getAnArgumentSubExpr(index) and + mid = this.getAnArgumentSubExpr(index) and not mid instanceof Call and not mid instanceof SizeofOperator and result = mid.getAChild() @@ -167,27 +167,27 @@ class FunctionCall extends Call, @funbindexpr { override string getAPrimaryQlClass() { result = "FunctionCall" } /** Gets an explicit template argument for this call. */ - Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } + Locatable getAnExplicitTemplateArgument() { result = this.getExplicitTemplateArgument(_) } /** Gets an explicit template argument value for this call. */ - Locatable getAnExplicitTemplateArgumentKind() { result = getExplicitTemplateArgumentKind(_) } + Locatable getAnExplicitTemplateArgumentKind() { result = this.getExplicitTemplateArgumentKind(_) } /** Gets a template argument for this call. */ - Locatable getATemplateArgument() { result = getTarget().getATemplateArgument() } + Locatable getATemplateArgument() { result = this.getTarget().getATemplateArgument() } /** Gets a template argument value for this call. */ - Locatable getATemplateArgumentKind() { result = getTarget().getATemplateArgumentKind() } + Locatable getATemplateArgumentKind() { result = this.getTarget().getATemplateArgumentKind() } /** Gets the nth explicit template argument for this call. */ Locatable getExplicitTemplateArgument(int n) { - n < getNumberOfExplicitTemplateArguments() and - result = getTemplateArgument(n) + n < this.getNumberOfExplicitTemplateArguments() and + result = this.getTemplateArgument(n) } /** Gets the nth explicit template argument value for this call. */ Locatable getExplicitTemplateArgumentKind(int n) { - n < getNumberOfExplicitTemplateArguments() and - result = getTemplateArgumentKind(n) + n < this.getNumberOfExplicitTemplateArguments() and + result = this.getTemplateArgumentKind(n) } /** Gets the number of explicit template arguments for this call. */ @@ -198,19 +198,19 @@ class FunctionCall extends Call, @funbindexpr { } /** Gets the number of template arguments for this call. */ - int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } + int getNumberOfTemplateArguments() { result = count(int i | exists(this.getTemplateArgument(i))) } /** Gets the nth template argument for this call (indexed from 0). */ - Locatable getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } + Locatable getTemplateArgument(int n) { result = this.getTarget().getTemplateArgument(n) } /** Gets the nth template argument value for this call (indexed from 0). */ - Locatable getTemplateArgumentKind(int n) { result = getTarget().getTemplateArgumentKind(n) } + Locatable getTemplateArgumentKind(int n) { result = this.getTarget().getTemplateArgumentKind(n) } /** Holds if any template arguments for this call are implicit / deduced. */ predicate hasImplicitTemplateArguments() { exists(int i | - exists(getTemplateArgument(i)) and - not exists(getExplicitTemplateArgument(i)) + exists(this.getTemplateArgument(i)) and + not exists(this.getExplicitTemplateArgument(i)) ) } @@ -233,9 +233,9 @@ class FunctionCall extends Call, @funbindexpr { * visible at the call site. */ Type getExpectedReturnType() { - if getTargetType() instanceof RoutineType - then result = getTargetType().(RoutineType).getReturnType() - else result = getTarget().getType() + if this.getTargetType() instanceof RoutineType + then result = this.getTargetType().(RoutineType).getReturnType() + else result = this.getTarget().getType() } /** @@ -247,9 +247,9 @@ class FunctionCall extends Call, @funbindexpr { * was visible at the call site. */ Type getExpectedParameterType(int n) { - if getTargetType() instanceof RoutineType - then result = getTargetType().(RoutineType).getParameterType(n) - else result = getTarget().getParameter(n).getType() + if this.getTargetType() instanceof RoutineType + then result = this.getTargetType().(RoutineType).getParameterType(n) + else result = this.getTarget().getParameter(n).getType() } /** @@ -263,7 +263,7 @@ class FunctionCall extends Call, @funbindexpr { /** * Gets the type of this expression, that is, the return type of the function being called. */ - override Type getType() { result = getExpectedReturnType() } + override Type getType() { result = this.getExpectedReturnType() } /** * Holds if this is a call to a virtual function. @@ -280,7 +280,7 @@ class FunctionCall extends Call, @funbindexpr { /** Gets a textual representation of this function call. */ override string toString() { - if exists(getTarget()) + if exists(this.getTarget()) then result = "call to " + this.getTarget().getName() else result = "call to unknown function" } @@ -288,15 +288,15 @@ class FunctionCall extends Call, @funbindexpr { override predicate mayBeImpure() { this.getChild(_).mayBeImpure() or this.getTarget().mayHaveSideEffects() or - isVirtual() or - getTarget().getAnAttribute().getName() = "weak" + this.isVirtual() or + this.getTarget().getAnAttribute().getName() = "weak" } override predicate mayBeGloballyImpure() { this.getChild(_).mayBeGloballyImpure() or this.getTarget().mayHaveSideEffects() or - isVirtual() or - getTarget().getAnAttribute().getName() = "weak" + this.isVirtual() or + this.getTarget().getAnAttribute().getName() = "weak" } } @@ -367,7 +367,7 @@ class OverloadedPointerDereferenceExpr extends FunctionCall { * ``` */ class OverloadedArrayExpr extends FunctionCall { - OverloadedArrayExpr() { getTarget().hasName("operator[]") } + OverloadedArrayExpr() { this.getTarget().hasName("operator[]") } override string getAPrimaryQlClass() { result = "OverloadedArrayExpr" } @@ -585,7 +585,7 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit { */ Expr getExpr() { result = this.getChild(0) } - override string toString() { result = "constructor init of field " + getTarget().getName() } + override string toString() { result = "constructor init of field " + this.getTarget().getName() } override predicate mayBeImpure() { this.getExpr().mayBeImpure() } diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll index ebe88ddf71c..273023a8229 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll @@ -188,8 +188,8 @@ private predicate isPointerToMemberOrNullPointer(Type type) { class ArithmeticConversion extends Cast { ArithmeticConversion() { conversionkinds(underlyingElement(this), 0) and - isArithmeticOrEnum(getUnspecifiedType()) and - isArithmeticOrEnum(getExpr().getUnspecifiedType()) + isArithmeticOrEnum(this.getUnspecifiedType()) and + isArithmeticOrEnum(this.getExpr().getUnspecifiedType()) } override string getSemanticConversionString() { result = "arithmetic conversion" } @@ -204,8 +204,8 @@ class ArithmeticConversion extends Cast { */ class IntegralConversion extends ArithmeticConversion { IntegralConversion() { - isIntegralOrEnum(getUnspecifiedType()) and - isIntegralOrEnum(getExpr().getUnspecifiedType()) + isIntegralOrEnum(this.getUnspecifiedType()) and + isIntegralOrEnum(this.getExpr().getUnspecifiedType()) } override string getAPrimaryQlClass() { @@ -224,8 +224,8 @@ class IntegralConversion extends ArithmeticConversion { */ class FloatingPointConversion extends ArithmeticConversion { FloatingPointConversion() { - getUnspecifiedType() instanceof FloatingPointType and - getExpr().getUnspecifiedType() instanceof FloatingPointType + this.getUnspecifiedType() instanceof FloatingPointType and + this.getExpr().getUnspecifiedType() instanceof FloatingPointType } override string getAPrimaryQlClass() { @@ -244,8 +244,8 @@ class FloatingPointConversion extends ArithmeticConversion { */ class FloatingPointToIntegralConversion extends ArithmeticConversion { FloatingPointToIntegralConversion() { - isIntegralOrEnum(getUnspecifiedType()) and - getExpr().getUnspecifiedType() instanceof FloatingPointType + isIntegralOrEnum(this.getUnspecifiedType()) and + this.getExpr().getUnspecifiedType() instanceof FloatingPointType } override string getAPrimaryQlClass() { @@ -264,8 +264,8 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion { */ class IntegralToFloatingPointConversion extends ArithmeticConversion { IntegralToFloatingPointConversion() { - getUnspecifiedType() instanceof FloatingPointType and - isIntegralOrEnum(getExpr().getUnspecifiedType()) + this.getUnspecifiedType() instanceof FloatingPointType and + isIntegralOrEnum(this.getExpr().getUnspecifiedType()) } override string getAPrimaryQlClass() { @@ -290,8 +290,8 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion { class PointerConversion extends Cast { PointerConversion() { conversionkinds(underlyingElement(this), 0) and - isPointerOrNullPointer(getUnspecifiedType()) and - isPointerOrNullPointer(getExpr().getUnspecifiedType()) + isPointerOrNullPointer(this.getUnspecifiedType()) and + isPointerOrNullPointer(this.getExpr().getUnspecifiedType()) } override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "PointerConversion" } @@ -315,8 +315,8 @@ class PointerToMemberConversion extends Cast { PointerToMemberConversion() { conversionkinds(underlyingElement(this), 0) and exists(Type fromType, Type toType | - fromType = getExpr().getUnspecifiedType() and - toType = getUnspecifiedType() and + fromType = this.getExpr().getUnspecifiedType() and + toType = this.getUnspecifiedType() and isPointerToMemberOrNullPointer(fromType) and isPointerToMemberOrNullPointer(toType) and // A conversion from nullptr to nullptr is a `PointerConversion`, not a @@ -345,8 +345,8 @@ class PointerToMemberConversion extends Cast { class PointerToIntegralConversion extends Cast { PointerToIntegralConversion() { conversionkinds(underlyingElement(this), 0) and - isIntegralOrEnum(getUnspecifiedType()) and - isPointerOrNullPointer(getExpr().getUnspecifiedType()) + isIntegralOrEnum(this.getUnspecifiedType()) and + isPointerOrNullPointer(this.getExpr().getUnspecifiedType()) } override string getAPrimaryQlClass() { @@ -366,8 +366,8 @@ class PointerToIntegralConversion extends Cast { class IntegralToPointerConversion extends Cast { IntegralToPointerConversion() { conversionkinds(underlyingElement(this), 0) and - isPointerOrNullPointer(getUnspecifiedType()) and - isIntegralOrEnum(getExpr().getUnspecifiedType()) + isPointerOrNullPointer(this.getUnspecifiedType()) and + isIntegralOrEnum(this.getExpr().getUnspecifiedType()) } override string getAPrimaryQlClass() { @@ -403,7 +403,7 @@ class BoolConversion extends Cast { class VoidConversion extends Cast { VoidConversion() { conversionkinds(underlyingElement(this), 0) and - getUnspecifiedType() instanceof VoidType + this.getUnspecifiedType() instanceof VoidType } override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "VoidConversion" } @@ -434,8 +434,8 @@ class InheritanceConversion extends Cast { * conversion is to an indirect virtual base class. */ final ClassDerivation getDerivation() { - result.getBaseClass() = getBaseClass() and - result.getDerivedClass() = getDerivedClass() + result.getBaseClass() = this.getBaseClass() and + result.getDerivedClass() = this.getDerivedClass() } /** @@ -490,12 +490,12 @@ class BaseClassConversion extends InheritanceConversion { override Class getBaseClass() { result = getConversionClass(this) } - override Class getDerivedClass() { result = getConversionClass(getExpr()) } + override Class getDerivedClass() { result = getConversionClass(this.getExpr()) } /** * Holds if this conversion is to a virtual base class. */ - predicate isVirtual() { getDerivation().isVirtual() or not exists(getDerivation()) } + predicate isVirtual() { this.getDerivation().isVirtual() or not exists(this.getDerivation()) } } /** @@ -515,7 +515,7 @@ class DerivedClassConversion extends InheritanceConversion { override string getSemanticConversionString() { result = "derived class conversion" } - override Class getBaseClass() { result = getConversionClass(getExpr()) } + override Class getBaseClass() { result = getConversionClass(this.getExpr()) } override Class getDerivedClass() { result = getConversionClass(this) } } @@ -637,8 +637,8 @@ class DynamicCast extends Cast, @dynamic_cast { */ class UuidofOperator extends Expr, @uuidof { override string toString() { - if exists(getTypeOperand()) - then result = "__uuidof(" + getTypeOperand().getName() + ")" + if exists(this.getTypeOperand()) + then result = "__uuidof(" + this.getTypeOperand().getName() + ")" else result = "__uuidof(0)" } diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll index f77518c2f56..2811d1703aa 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll @@ -26,7 +26,7 @@ class Expr extends StmtParent, @expr { Function getEnclosingFunction() { result = exprEnclosingElement(this) } /** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */ - BlockStmt getEnclosingBlock() { result = getEnclosingStmt().getEnclosingBlock() } + BlockStmt getEnclosingBlock() { result = this.getEnclosingStmt().getEnclosingBlock() } override Stmt getEnclosingStmt() { result = this.getParent().(Expr).getEnclosingStmt() @@ -219,13 +219,13 @@ class Expr extends StmtParent, @expr { * Holds if this expression is a _glvalue_. A _glvalue_ is either an _lvalue_ or an * _xvalue_. */ - predicate isGLValueCategory() { isLValueCategory() or isXValueCategory() } + predicate isGLValueCategory() { this.isLValueCategory() or this.isXValueCategory() } /** * Holds if this expression is an _rvalue_. An _rvalue_ is either a _prvalue_ or an * _xvalue_. */ - predicate isRValueCategory() { isPRValueCategory() or isXValueCategory() } + predicate isRValueCategory() { this.isPRValueCategory() or this.isXValueCategory() } /** * Gets a string representation of the value category of the expression. @@ -240,15 +240,15 @@ class Expr extends StmtParent, @expr { * `hasLValueToRvalueConversion()` holds. */ string getValueCategoryString() { - isLValueCategory() and + this.isLValueCategory() and result = "lvalue" or - isXValueCategory() and + this.isXValueCategory() and result = "xvalue" or ( - isPRValueCategory() and - if hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue" + this.isPRValueCategory() and + if this.hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue" ) } @@ -263,7 +263,7 @@ class Expr extends StmtParent, @expr { * such as an expression inside a sizeof. */ predicate isUnevaluated() { - exists(Element e | e = getParentWithConversions+() | + exists(Element e | e = this.getParentWithConversions+() | e instanceof SizeofOperator or exists(Expr e2 | @@ -279,7 +279,7 @@ class Expr extends StmtParent, @expr { e instanceof AlignofOperator ) or - exists(Decltype d | d.getExpr() = getParentWithConversions*()) + exists(Decltype d | d.getExpr() = this.getParentWithConversions*()) } /** @@ -725,7 +725,7 @@ class PointerDereferenceExpr extends UnaryOperation, @indirect { * * Gets the expression that is being dereferenced. */ - deprecated Expr getExpr() { result = getOperand() } + deprecated Expr getExpr() { result = this.getOperand() } override string getOperator() { result = "*" } @@ -780,15 +780,15 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr { * Gets the alignment argument passed to the allocation function, if any. */ Expr getAlignmentArgument() { - hasAlignedAllocation() and + this.hasAlignedAllocation() and ( // If we have an allocator call, the alignment is the second argument to // that call. - result = getAllocatorCall().getArgument(1) + result = this.getAllocatorCall().getArgument(1) or // Otherwise, the alignment winds up as child number 3 of the `new` // itself. - result = getChild(3) + result = this.getChild(3) ) } @@ -916,7 +916,7 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr { * Gets the element type of the array being allocated. */ Type getAllocatedElementType() { - result = getType().getUnderlyingType().(PointerType).getBaseType() + result = this.getType().getUnderlyingType().(PointerType).getBaseType() } /** @@ -946,7 +946,12 @@ class DeleteExpr extends Expr, @delete_expr { */ Type getDeletedObjectType() { result = - getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() + this.getExpr() + .getFullyConverted() + .getType() + .stripTopLevelSpecifiers() + .(PointerType) + .getBaseType() } /** @@ -957,7 +962,7 @@ class DeleteExpr extends Expr, @delete_expr { /** * Gets the destructor to be called to destroy the object, if any. */ - Destructor getDestructor() { result = getDestructorCall().getTarget() } + Destructor getDestructor() { result = this.getDestructorCall().getTarget() } /** * Gets the `operator delete` that deallocates storage. Does not hold @@ -1020,7 +1025,12 @@ class DeleteArrayExpr extends Expr, @delete_array_expr { */ Type getDeletedElementType() { result = - getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() + this.getExpr() + .getFullyConverted() + .getType() + .stripTopLevelSpecifiers() + .(PointerType) + .getBaseType() } /** @@ -1034,7 +1044,7 @@ class DeleteArrayExpr extends Expr, @delete_array_expr { /** * Gets the destructor to be called to destroy each element in the array, if any. */ - Destructor getDestructor() { result = getDestructorCall().getTarget() } + Destructor getDestructor() { result = this.getDestructorCall().getTarget() } /** * Gets the `operator delete[]` that deallocates storage. @@ -1101,7 +1111,7 @@ class StmtExpr extends Expr, @expr_stmt { * x = ({ dosomething(); a+b; }); * ``` */ - Expr getResultExpr() { result = getStmtResultExpr(getStmt()) } + Expr getResultExpr() { result = getStmtResultExpr(this.getStmt()) } } /** Get the result expression of a statement. (Helper function for StmtExpr.) */ @@ -1230,20 +1240,20 @@ class FoldExpr extends Expr, @foldexpr { predicate isRightFold() { fold(underlyingElement(this), _, false) } /** Holds if this is a unary fold expression. */ - predicate isUnaryFold() { getNumChild() = 1 } + predicate isUnaryFold() { this.getNumChild() = 1 } /** Holds if this is a binary fold expression. */ - predicate isBinaryFold() { getNumChild() = 2 } + predicate isBinaryFold() { this.getNumChild() = 2 } /** * Gets the child expression containing the unexpanded parameter pack. */ Expr getPackExpr() { this.isUnaryFold() and - result = getChild(0) + result = this.getChild(0) or this.isBinaryFold() and - if this.isRightFold() then result = getChild(0) else result = getChild(1) + if this.isRightFold() then result = this.getChild(0) else result = this.getChild(1) } /** @@ -1251,7 +1261,7 @@ class FoldExpr extends Expr, @foldexpr { */ Expr getInitExpr() { this.isBinaryFold() and - if this.isRightFold() then result = getChild(1) else result = getChild(0) + if this.isRightFold() then result = this.getChild(1) else result = this.getChild(0) } } diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Lambda.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Lambda.qll index 8a51001f4d5..c885831c444 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Lambda.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Lambda.qll @@ -24,7 +24,7 @@ class LambdaExpression extends Expr, @lambdaexpr { /** * Gets an implicitly or explicitly captured value of this lambda expression. */ - LambdaCapture getACapture() { result = getCapture(_) } + LambdaCapture getACapture() { result = this.getCapture(_) } /** * Gets the nth implicitly or explicitly captured value of this lambda expression. @@ -58,13 +58,13 @@ class LambdaExpression extends Expr, @lambdaexpr { * - The return type. * - The statements comprising the lambda body. */ - Operator getLambdaFunction() { result = getType().(Closure).getLambdaFunction() } + Operator getLambdaFunction() { result = this.getType().(Closure).getLambdaFunction() } /** * Gets the initializer that initializes the captured variables in the closure, if any. * A lambda that does not capture any variables will not have an initializer. */ - ClassAggregateLiteral getInitializer() { result = getChild(0) } + ClassAggregateLiteral getInitializer() { result = this.getChild(0) } } /** @@ -103,7 +103,7 @@ class Closure extends Class { * ``` */ class LambdaCapture extends Locatable, @lambdacapture { - override string toString() { result = getField().getName() } + override string toString() { result = this.getField().getName() } override string getAPrimaryQlClass() { result = "LambdaCapture" } diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll index 31790f85bfb..18ca03740ac 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll @@ -60,12 +60,12 @@ class TextLiteral extends Literal { /** Gets a hex escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */ string getAHexEscapeSequence(int occurrence, int offset) { - result = getValueText().regexpFind("(?<!\\\\)\\\\x[0-9a-fA-F]+", occurrence, offset) + result = this.getValueText().regexpFind("(?<!\\\\)\\\\x[0-9a-fA-F]+", occurrence, offset) } /** Gets an octal escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */ string getAnOctalEscapeSequence(int occurrence, int offset) { - result = getValueText().regexpFind("(?<!\\\\)\\\\[0-7]{1,3}", occurrence, offset) + result = this.getValueText().regexpFind("(?<!\\\\)\\\\[0-7]{1,3}", occurrence, offset) } /** @@ -75,27 +75,27 @@ class TextLiteral extends Literal { string getANonStandardEscapeSequence(int occurrence, int offset) { // Find all single character escape sequences (ignoring the start of octal escape sequences), // together with anything starting like a hex escape sequence but not followed by a hex digit. - result = getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and + result = this.getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and // From these, exclude all standard escape sequences. - not result = getAStandardEscapeSequence(_, _) + not result = this.getAStandardEscapeSequence(_, _) } /** Gets a simple escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */ string getASimpleEscapeSequence(int occurrence, int offset) { - result = getValueText().regexpFind("\\\\['\"?\\\\abfnrtv]", occurrence, offset) + result = this.getValueText().regexpFind("\\\\['\"?\\\\abfnrtv]", occurrence, offset) } /** Gets a standard escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */ string getAStandardEscapeSequence(int occurrence, int offset) { - result = getASimpleEscapeSequence(occurrence, offset) or - result = getAnOctalEscapeSequence(occurrence, offset) or - result = getAHexEscapeSequence(occurrence, offset) + result = this.getASimpleEscapeSequence(occurrence, offset) or + result = this.getAnOctalEscapeSequence(occurrence, offset) or + result = this.getAHexEscapeSequence(occurrence, offset) } /** * Gets the length of the string literal (including null) before escape sequences added by the extractor. */ - int getOriginalLength() { result = getValue().length() + 1 } + int getOriginalLength() { result = this.getValue().length() + 1 } } /** @@ -216,7 +216,7 @@ class ClassAggregateLiteral extends AggregateLiteral { ( // If the field has an explicit initializer expression, then the field is // initialized. - exists(getFieldExpr(field)) + exists(this.getFieldExpr(field)) or // If the type is not a union, all fields without initializers are value // initialized. @@ -224,7 +224,7 @@ class ClassAggregateLiteral extends AggregateLiteral { or // If the type is a union, and there are no explicit initializers, then // the first declared field is value initialized. - not exists(getAChild()) and + not exists(this.getAChild()) and field.getInitializationOrder() = 0 ) } @@ -239,8 +239,8 @@ class ClassAggregateLiteral extends AggregateLiteral { */ pragma[inline] predicate isValueInitialized(Field field) { - isInitialized(field) and - not exists(getFieldExpr(field)) + this.isInitialized(field) and + not exists(this.getFieldExpr(field)) } } @@ -285,7 +285,7 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral { bindingset[elementIndex] predicate isInitialized(int elementIndex) { elementIndex >= 0 and - elementIndex < getArraySize() + elementIndex < this.getArraySize() } /** @@ -298,8 +298,8 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral { */ bindingset[elementIndex] predicate isValueInitialized(int elementIndex) { - isInitialized(elementIndex) and - not exists(getElementExpr(elementIndex)) + this.isInitialized(elementIndex) and + not exists(this.getElementExpr(elementIndex)) } } diff --git a/cpp/ql/lib/semmle/code/cpp/internal/QualifiedName.qll b/cpp/ql/lib/semmle/code/cpp/internal/QualifiedName.qll index 692ce1fee19..7cf0c647142 100644 --- a/cpp/ql/lib/semmle/code/cpp/internal/QualifiedName.qll +++ b/cpp/ql/lib/semmle/code/cpp/internal/QualifiedName.qll @@ -173,7 +173,7 @@ class LocalVariable extends LocalScopeVariable, @localvariable { } class VariableDeclarationEntry extends @var_decl { string toString() { result = "QualifiedName DeclarationEntry" } - Variable getDeclaration() { result = getVariable() } + Variable getDeclaration() { result = this.getVariable() } /** * Gets the variable which is being declared or defined. 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 4ca06c93362..c3b2fc44f14 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 @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 9e7a95e010d..bdcaa856daa 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -110,7 +110,7 @@ class Node extends TIRDataFlowNode { /** * Gets an upper bound on the type of this node. */ - IRType getTypeBound() { result = getType() } + IRType getTypeBound() { result = this.getType() } /** Gets the location of this element. */ Location getLocation() { none() } // overridden by subclasses @@ -831,7 +831,7 @@ class FieldContent extends Content, TFieldContent { FieldContent() { this = TFieldContent(c, startBit, endBit) } // Ensure that there's just 1 result for `toString`. - override string toString() { result = min(Field f | f = getAField() | f.toString()) } + override string toString() { result = min(Field f | f = this.getAField() | f.toString()) } predicate hasOffset(Class cl, int start, int end) { cl = c and start = startBit and end = endBit } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index a9f408bf161..3f0f4f10ee3 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -55,7 +55,7 @@ abstract class TranslatedExpr extends TranslatedElement { abstract predicate producesExprResult(); final CppType getResultType() { - if isResultGLValue() + if this.isResultGLValue() then result = getTypeForGLValue(expr.getType()) else result = getTypeForPRValue(expr.getType()) } @@ -128,9 +128,9 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, TTranslatedConditionValue { TranslatedConditionValue() { this = TTranslatedConditionValue(expr) } - override TranslatedElement getChild(int id) { id = 0 and result = getCondition() } + override TranslatedElement getChild(int id) { id = 0 and result = this.getCondition() } - override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getCondition().getFirstInstruction() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { ( @@ -146,46 +146,46 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, tag = ConditionValueFalseConstantTag() ) and opcode instanceof Opcode::Constant and - resultType = getResultType() + resultType = this.getResultType() or ( tag = ConditionValueTrueStoreTag() or tag = ConditionValueFalseStoreTag() ) and opcode instanceof Opcode::Store and - resultType = getResultType() + resultType = this.getResultType() or tag = ConditionValueResultLoadTag() and opcode instanceof Opcode::Load and - resultType = getResultType() + resultType = this.getResultType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( tag = ConditionValueTrueTempAddressTag() and - result = getInstruction(ConditionValueTrueConstantTag()) + result = this.getInstruction(ConditionValueTrueConstantTag()) or tag = ConditionValueTrueConstantTag() and - result = getInstruction(ConditionValueTrueStoreTag()) + result = this.getInstruction(ConditionValueTrueStoreTag()) or tag = ConditionValueTrueStoreTag() and - result = getInstruction(ConditionValueResultTempAddressTag()) + result = this.getInstruction(ConditionValueResultTempAddressTag()) or tag = ConditionValueFalseTempAddressTag() and - result = getInstruction(ConditionValueFalseConstantTag()) + result = this.getInstruction(ConditionValueFalseConstantTag()) or tag = ConditionValueFalseConstantTag() and - result = getInstruction(ConditionValueFalseStoreTag()) + result = this.getInstruction(ConditionValueFalseStoreTag()) or tag = ConditionValueFalseStoreTag() and - result = getInstruction(ConditionValueResultTempAddressTag()) + result = this.getInstruction(ConditionValueResultTempAddressTag()) or tag = ConditionValueResultTempAddressTag() and - result = getInstruction(ConditionValueResultLoadTag()) + result = this.getInstruction(ConditionValueResultLoadTag()) or tag = ConditionValueResultLoadTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) ) } @@ -193,25 +193,25 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, tag = ConditionValueTrueStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueTrueTempAddressTag()) + result = this.getInstruction(ConditionValueTrueTempAddressTag()) or operandTag instanceof StoreValueOperandTag and - result = getInstruction(ConditionValueTrueConstantTag()) + result = this.getInstruction(ConditionValueTrueConstantTag()) ) or tag = ConditionValueFalseStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueFalseTempAddressTag()) + result = this.getInstruction(ConditionValueFalseTempAddressTag()) or operandTag instanceof StoreValueOperandTag and - result = getInstruction(ConditionValueFalseConstantTag()) + result = this.getInstruction(ConditionValueFalseConstantTag()) ) or tag = ConditionValueResultLoadTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueResultTempAddressTag()) + result = this.getInstruction(ConditionValueResultTempAddressTag()) ) } @@ -226,7 +226,7 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, tag = ConditionValueFalseTempAddressTag() or tag = ConditionValueResultTempAddressTag() ) and - result = getTempVariable(ConditionValueTempVar()) + result = this.getTempVariable(ConditionValueTempVar()) } override string getInstructionConstantValue(InstructionTag tag) { @@ -235,18 +235,18 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, tag = ConditionValueFalseConstantTag() and result = "0" } - override Instruction getResult() { result = getInstruction(ConditionValueResultLoadTag()) } + override Instruction getResult() { result = this.getInstruction(ConditionValueResultLoadTag()) } override Instruction getChildSuccessor(TranslatedElement child) { none() } override Instruction getChildTrueSuccessor(TranslatedCondition child) { - child = getCondition() and - result = getInstruction(ConditionValueTrueTempAddressTag()) + child = this.getCondition() and + result = this.getInstruction(ConditionValueTrueTempAddressTag()) } override Instruction getChildFalseSuccessor(TranslatedCondition child) { - child = getCondition() and - result = getInstruction(ConditionValueFalseTempAddressTag()) + child = this.getCondition() and + result = this.getInstruction(ConditionValueFalseTempAddressTag()) } private TranslatedCondition getCondition() { result = getTranslatedCondition(expr) } @@ -260,9 +260,11 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, * temporary variable. */ abstract class TranslatedValueCategoryAdjustment extends TranslatedExpr { - final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + final override Instruction getFirstInstruction() { + result = this.getOperand().getFirstInstruction() + } - final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() } final override predicate producesExprResult() { // A temp object always produces the result of the expression. @@ -284,28 +286,28 @@ class TranslatedLoad extends TranslatedValueCategoryAdjustment, TTranslatedLoad override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = LoadTag() and opcode instanceof Opcode::Load and - resultType = getResultType() + resultType = this.getResultType() } override predicate isResultGLValue() { none() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = LoadTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { - child = getOperand() and result = getInstruction(LoadTag()) + child = this.getOperand() and result = this.getInstruction(LoadTag()) } - override Instruction getResult() { result = getInstruction(LoadTag()) } + override Instruction getResult() { result = this.getInstruction(LoadTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = LoadTag() and ( operandTag instanceof AddressOperandTag and - result = getOperand().getResult() + result = this.getOperand().getResult() ) } } @@ -337,28 +339,28 @@ class TranslatedSyntheticTemporaryObject extends TranslatedValueCategoryAdjustme override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = InitializerVariableAddressTag() and - result = getInstruction(InitializerStoreTag()) and + result = this.getInstruction(InitializerStoreTag()) and kind instanceof GotoEdge or tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { - child = getOperand() and result = getInstruction(InitializerVariableAddressTag()) + child = this.getOperand() and result = this.getInstruction(InitializerVariableAddressTag()) } - override Instruction getResult() { result = getInstruction(InitializerVariableAddressTag()) } + override Instruction getResult() { result = this.getInstruction(InitializerVariableAddressTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = InitializerStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) or operandTag instanceof StoreValueOperandTag and - result = getOperand().getResult() + result = this.getOperand().getResult() ) } @@ -383,32 +385,32 @@ class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy { override string toString() { result = "Result of " + expr.toString() } - override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getOperand().getFirstInstruction() } - override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = ResultCopyTag() and opcode instanceof Opcode::CopyValue and - resultType = getOperand().getResultType() + resultType = this.getOperand().getResultType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = ResultCopyTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { - child = getOperand() and result = getInstruction(ResultCopyTag()) + child = this.getOperand() and result = this.getInstruction(ResultCopyTag()) } - override Instruction getResult() { result = getInstruction(ResultCopyTag()) } + override Instruction getResult() { result = this.getInstruction(ResultCopyTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = ResultCopyTag() and operandTag instanceof UnaryOperandTag and - result = getOperand().getResult() + result = this.getOperand().getResult() } final override predicate producesExprResult() { any() } @@ -419,23 +421,25 @@ class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy { class TranslatedCommaExpr extends TranslatedNonConstantExpr { override CommaExpr expr; - override Instruction getFirstInstruction() { result = getLeftOperand().getFirstInstruction() } - - override TranslatedElement getChild(int id) { - id = 0 and result = getLeftOperand() - or - id = 1 and result = getRightOperand() + override Instruction getFirstInstruction() { + result = this.getLeftOperand().getFirstInstruction() } - override Instruction getResult() { result = getRightOperand().getResult() } + override TranslatedElement getChild(int id) { + id = 0 and result = this.getLeftOperand() + or + id = 1 and result = this.getRightOperand() + } + + override Instruction getResult() { result = this.getRightOperand().getResult() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { - child = getLeftOperand() and - result = getRightOperand().getFirstInstruction() + child = this.getLeftOperand() and + result = this.getRightOperand().getFirstInstruction() or - child = getRightOperand() and result = getParent().getChildSuccessor(this) + child = this.getRightOperand() and result = this.getParent().getChildSuccessor(this) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -462,7 +466,7 @@ private int getElementSize(Type type) { abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { override CrementOperation expr; - final override TranslatedElement getChild(int id) { id = 0 and result = getLoadedOperand() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getLoadedOperand() } final override string getInstructionConstantValue(InstructionTag tag) { tag = CrementConstantTag() and @@ -493,10 +497,10 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = CrementConstantTag() and opcode instanceof Opcode::Constant and - resultType = getConstantType() + resultType = this.getConstantType() or tag = CrementOpTag() and - opcode = getOpcode() and + opcode = this.getOpcode() and resultType = getTypeForPRValue(expr.getType()) or tag = CrementStoreTag() and @@ -508,49 +512,49 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { tag = CrementOpTag() and ( operandTag instanceof LeftOperandTag and - result = getLoadedOperand().getResult() + result = this.getLoadedOperand().getResult() or operandTag instanceof RightOperandTag and - result = getInstruction(CrementConstantTag()) + result = this.getInstruction(CrementConstantTag()) ) or tag = CrementStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getUnloadedOperand().getResult() + result = this.getUnloadedOperand().getResult() or operandTag instanceof StoreValueOperandTag and - result = getInstruction(CrementOpTag()) + result = this.getInstruction(CrementOpTag()) ) } final override Instruction getFirstInstruction() { - result = getLoadedOperand().getFirstInstruction() + result = this.getLoadedOperand().getFirstInstruction() } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( tag = CrementConstantTag() and - result = getInstruction(CrementOpTag()) + result = this.getInstruction(CrementOpTag()) or tag = CrementOpTag() and - result = getInstruction(CrementStoreTag()) + result = this.getInstruction(CrementStoreTag()) or tag = CrementStoreTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) ) } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getLoadedOperand() and result = getInstruction(CrementConstantTag()) + child = this.getLoadedOperand() and result = this.getInstruction(CrementConstantTag()) } final override int getInstructionElementSize(InstructionTag tag) { tag = CrementOpTag() and ( - getOpcode() instanceof Opcode::PointerAdd or - getOpcode() instanceof Opcode::PointerSub + this.getOpcode() instanceof Opcode::PointerAdd or + this.getOpcode() instanceof Opcode::PointerSub ) and result = getElementSize(expr.getType()) } @@ -567,7 +571,7 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { /** * Gets the address to which the result of this crement will be stored. */ - final TranslatedExpr getUnloadedOperand() { result = getLoadedOperand().getOperand() } + final TranslatedExpr getUnloadedOperand() { result = this.getLoadedOperand().getOperand() } final Opcode getOpcode() { exists(Type resultType | @@ -601,18 +605,18 @@ class TranslatedPrefixCrementOperation extends TranslatedCrementOperation { // new value assigned to the operand. If this is C++, then the result is // an lvalue, but that lvalue is being loaded as part of this expression. // EDG doesn't mark this as a load. - result = getInstruction(CrementOpTag()) + result = this.getInstruction(CrementOpTag()) else // This is C++, where the result is an lvalue for the operand, and that // lvalue is not being loaded as part of this expression. - result = getUnloadedOperand().getResult() + result = this.getUnloadedOperand().getResult() } } class TranslatedPostfixCrementOperation extends TranslatedCrementOperation { override PostfixCrementOperation expr; - override Instruction getResult() { result = getLoadedOperand().getResult() } + override Instruction getResult() { result = this.getLoadedOperand().getResult() } } /** @@ -624,30 +628,30 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr { override ArrayExpr expr; final override Instruction getFirstInstruction() { - result = getBaseOperand().getFirstInstruction() + result = this.getBaseOperand().getFirstInstruction() } final override TranslatedElement getChild(int id) { - id = 0 and result = getBaseOperand() + id = 0 and result = this.getBaseOperand() or - id = 1 and result = getOffsetOperand() + id = 1 and result = this.getOffsetOperand() } 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) { - child = getBaseOperand() and - result = getOffsetOperand().getFirstInstruction() + child = this.getBaseOperand() and + result = this.getOffsetOperand().getFirstInstruction() or - child = getOffsetOperand() and - result = getInstruction(OnlyInstructionTag()) + child = this.getOffsetOperand() and + result = this.getInstruction(OnlyInstructionTag()) } - override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and @@ -659,10 +663,10 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr { tag = OnlyInstructionTag() and ( operandTag instanceof LeftOperandTag and - result = getBaseOperand().getResult() + result = this.getBaseOperand().getResult() or operandTag instanceof RightOperandTag and - result = getOffsetOperand().getResult() + result = this.getOffsetOperand().getResult() ) } @@ -681,21 +685,23 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr { } abstract class TranslatedTransparentExpr extends TranslatedNonConstantExpr { - final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + final override Instruction getFirstInstruction() { + result = this.getOperand().getFirstInstruction() + } - final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getOperand() and result = getParent().getChildSuccessor(this) + child = this.getOperand() and result = this.getParent().getChildSuccessor(this) } final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { none() } - final override Instruction getResult() { result = getOperand().getResult() } + final override Instruction getResult() { result = this.getOperand().getResult() } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { none() @@ -749,21 +755,23 @@ class TranslatedThisExpr extends TranslatedNonConstantExpr { or tag = ThisLoadTag() and opcode instanceof Opcode::Load and - resultType = getResultType() + resultType = this.getResultType() } - final override Instruction getResult() { result = getInstruction(ThisLoadTag()) } + final override Instruction getResult() { result = this.getInstruction(ThisLoadTag()) } - final override Instruction getFirstInstruction() { result = getInstruction(ThisAddressTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(ThisAddressTag()) + } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and tag = ThisAddressTag() and - result = getInstruction(ThisLoadTag()) + result = this.getInstruction(ThisLoadTag()) or kind instanceof GotoEdge and tag = ThisLoadTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } final override Instruction getChildSuccessor(TranslatedElement child) { none() } @@ -771,7 +779,7 @@ class TranslatedThisExpr extends TranslatedNonConstantExpr { final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = ThisLoadTag() and operandTag instanceof AddressOperandTag and - result = getInstruction(ThisAddressTag()) + result = this.getInstruction(ThisAddressTag()) } override IRVariable getInstructionVariable(InstructionTag tag) { @@ -784,23 +792,23 @@ abstract class TranslatedVariableAccess extends TranslatedNonConstantExpr { override VariableAccess expr; final override TranslatedElement getChild(int id) { - id = 0 and result = getQualifier() // Might not exist + id = 0 and result = this.getQualifier() // Might not exist } final TranslatedExpr getQualifier() { result = getTranslatedExpr(expr.getQualifier().getFullyConverted()) } - override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getQualifier() and result = getInstruction(OnlyInstructionTag()) + child = this.getQualifier() and result = this.getInstruction(OnlyInstructionTag()) } } @@ -808,9 +816,9 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess { TranslatedNonFieldVariableAccess() { not expr instanceof FieldAccess } override Instruction getFirstInstruction() { - if exists(getQualifier()) - then result = getQualifier().getFirstInstruction() - else result = getInstruction(OnlyInstructionTag()) + if exists(this.getQualifier()) + then result = this.getQualifier().getFirstInstruction() + else result = this.getInstruction(OnlyInstructionTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { @@ -832,12 +840,12 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess { class TranslatedFieldAccess extends TranslatedVariableAccess { override FieldAccess expr; - override Instruction getFirstInstruction() { result = getQualifier().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getQualifier().getFirstInstruction() } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and - result = getQualifier().getResult() + result = this.getQualifier().getResult() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -857,20 +865,20 @@ class TranslatedFunctionAccess extends TranslatedNonConstantExpr { override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) } - override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } final 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 predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and opcode instanceof Opcode::FunctionAddress and - resultType = getResultType() + resultType = this.getResultType() } override Function getInstructionFunction(InstructionTag tag) { @@ -902,11 +910,13 @@ abstract class TranslatedConstantExpr extends TranslatedCoreExpr, TTranslatedVal isIRConstant(expr) } - final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(OnlyInstructionTag()) + } final override TranslatedElement getChild(int id) { none() } - final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { none() @@ -914,13 +924,13 @@ abstract class TranslatedConstantExpr extends TranslatedCoreExpr, TTranslatedVal final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and - opcode = getOpcode() and - resultType = getResultType() + opcode = this.getOpcode() and + resultType = this.getResultType() } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } @@ -962,12 +972,12 @@ abstract class TranslatedSingleInstructionExpr extends TranslatedNonConstantExpr abstract Opcode getOpcode(); final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { - opcode = getOpcode() and + opcode = this.getOpcode() and tag = OnlyInstructionTag() and - resultType = getResultType() + resultType = this.getResultType() } - final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } } class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr { @@ -978,23 +988,25 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr { expr instanceof UnaryMinusExpr } - final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + final override Instruction getFirstInstruction() { + result = this.getOperand().getFirstInstruction() + } - final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getOperand() and result = getInstruction(OnlyInstructionTag()) + child = this.getOperand() and result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and - result = getOperand().getResult() and + result = this.getOperand().getResult() and operandTag instanceof UnaryOperandTag } @@ -1016,9 +1028,9 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr { abstract class TranslatedConversion extends TranslatedNonConstantExpr { override Conversion expr; - override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getOperand().getFirstInstruction() } - final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() } final TranslatedExpr getOperand() { result = getTranslatedExpr(expr.(Conversion).getExpr()) } } @@ -1030,26 +1042,26 @@ abstract class TranslatedConversion extends TranslatedNonConstantExpr { abstract class TranslatedSingleInstructionConversion extends TranslatedConversion { 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) { - child = getOperand() and result = getInstruction(OnlyInstructionTag()) + child = this.getOperand() and result = this.getInstruction(OnlyInstructionTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and - opcode = getOpcode() and - resultType = getResultType() + opcode = this.getOpcode() and + resultType = this.getResultType() } - override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and - result = getOperand().getResult() + result = this.getOperand().getResult() } /** @@ -1133,37 +1145,37 @@ class TranslatedBoolConversion extends TranslatedConversion { kind instanceof GotoEdge and ( tag = BoolConversionConstantTag() and - result = getInstruction(BoolConversionCompareTag()) + result = this.getInstruction(BoolConversionCompareTag()) or tag = BoolConversionCompareTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) ) } override Instruction getChildSuccessor(TranslatedElement child) { - child = getOperand() and result = getInstruction(BoolConversionConstantTag()) + child = this.getOperand() and result = this.getInstruction(BoolConversionConstantTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = BoolConversionConstantTag() and opcode instanceof Opcode::Constant and - resultType = getOperand().getResultType() + resultType = this.getOperand().getResultType() or tag = BoolConversionCompareTag() and opcode instanceof Opcode::CompareNE and resultType = getBoolType() } - override Instruction getResult() { result = getInstruction(BoolConversionCompareTag()) } + override Instruction getResult() { result = this.getInstruction(BoolConversionCompareTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = BoolConversionCompareTag() and ( operandTag instanceof LeftOperandTag and - result = getOperand().getResult() + result = this.getOperand().getResult() or operandTag instanceof RightOperandTag and - result = getInstruction(BoolConversionConstantTag()) + result = this.getInstruction(BoolConversionConstantTag()) ) } @@ -1250,44 +1262,46 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { expr instanceof ComparisonOperation } - override Instruction getFirstInstruction() { result = getLeftOperand().getFirstInstruction() } + override Instruction getFirstInstruction() { + result = this.getLeftOperand().getFirstInstruction() + } final override TranslatedElement getChild(int id) { - id = 0 and result = getLeftOperand() + id = 0 and result = this.getLeftOperand() or - id = 1 and result = getRightOperand() + id = 1 and result = this.getRightOperand() } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and - if swapOperandsOnOp() + if this.swapOperandsOnOp() then ( operandTag instanceof RightOperandTag and - result = getLeftOperand().getResult() + result = this.getLeftOperand().getResult() or operandTag instanceof LeftOperandTag and - result = getRightOperand().getResult() + result = this.getRightOperand().getResult() ) else ( operandTag instanceof LeftOperandTag and - result = getLeftOperand().getResult() + result = this.getLeftOperand().getResult() or operandTag instanceof RightOperandTag and - result = getRightOperand().getResult() + result = this.getRightOperand().getResult() ) } 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) { - child = getLeftOperand() and - result = getRightOperand().getFirstInstruction() + child = this.getLeftOperand() and + result = this.getRightOperand().getFirstInstruction() or - child = getRightOperand() and - result = getInstruction(OnlyInstructionTag()) + child = this.getRightOperand() and + result = this.getInstruction(OnlyInstructionTag()) } override Opcode getOpcode() { @@ -1299,18 +1313,20 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { override int getInstructionElementSize(InstructionTag tag) { tag = OnlyInstructionTag() and exists(Opcode opcode | - opcode = getOpcode() and + opcode = this.getOpcode() and ( opcode instanceof Opcode::PointerAdd or opcode instanceof Opcode::PointerSub or opcode instanceof Opcode::PointerDiff ) and - result = getElementSize(getPointerOperand().getExpr().getType()) + result = getElementSize(this.getPointerOperand().getExpr().getType()) ) } private TranslatedExpr getPointerOperand() { - if swapOperandsOnOp() then result = getRightOperand() else result = getLeftOperand() + if this.swapOperandsOnOp() + then result = this.getRightOperand() + else result = this.getLeftOperand() } private predicate swapOperandsOnOp() { @@ -1337,14 +1353,14 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr { override AssignExpr expr; final override TranslatedElement getChild(int id) { - id = 0 and result = getLeftOperand() + id = 0 and result = this.getLeftOperand() or - id = 1 and result = getRightOperand() + id = 1 and result = this.getRightOperand() } final override Instruction getFirstInstruction() { // Evaluation is right-to-left - result = getRightOperand().getFirstInstruction() + result = this.getRightOperand().getFirstInstruction() } final override Instruction getResult() { @@ -1354,11 +1370,11 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr { // value assigned to the left operand. If this is C++, then the result is // an lvalue, but that lvalue is being loaded as part of this expression. // EDG doesn't mark this as a load. - result = getRightOperand().getResult() + result = this.getRightOperand().getResult() else // This is C++, where the result is an lvalue for the left operand, // and that lvalue is not being loaded as part of this expression. - result = getLeftOperand().getResult() + result = this.getLeftOperand().getResult() } abstract Instruction getStoredValue(); @@ -1373,17 +1389,17 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = AssignmentStoreTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { // Operands are evaluated right-to-left. - child = getRightOperand() and - result = getLeftOperand().getFirstInstruction() + child = this.getRightOperand() and + result = this.getLeftOperand().getFirstInstruction() or - child = getLeftOperand() and - result = getInstruction(AssignmentStoreTag()) + child = this.getLeftOperand() and + result = this.getInstruction(AssignmentStoreTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -1396,10 +1412,10 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr { tag = AssignmentStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getLeftOperand().getResult() + result = this.getLeftOperand().getResult() or operandTag instanceof StoreValueOperandTag and - result = getRightOperand().getResult() + result = this.getRightOperand().getResult() ) } } @@ -1408,14 +1424,14 @@ class TranslatedAssignOperation extends TranslatedNonConstantExpr { override AssignOperation expr; final override TranslatedElement getChild(int id) { - id = 0 and result = getLoadedLeftOperand() + id = 0 and result = this.getLoadedLeftOperand() or - id = 1 and result = getRightOperand() + id = 1 and result = this.getRightOperand() } final override Instruction getFirstInstruction() { // Evaluation is right-to-left - result = getRightOperand().getFirstInstruction() + result = this.getRightOperand().getFirstInstruction() } final override Instruction getResult() { @@ -1425,14 +1441,16 @@ class TranslatedAssignOperation extends TranslatedNonConstantExpr { // value assigned to the left operand. If this is C++, then the result is // an lvalue, but that lvalue is being loaded as part of this expression. // EDG doesn't mark this as a load. - result = getStoredValue() + result = this.getStoredValue() else // This is C++, where the result is an lvalue for the left operand, // and that lvalue is not being loaded as part of this expression. - result = getUnloadedLeftOperand().getResult() + result = this.getUnloadedLeftOperand().getResult() } - final TranslatedExpr getUnloadedLeftOperand() { result = getLoadedLeftOperand().getOperand() } + final TranslatedExpr getUnloadedLeftOperand() { + result = this.getLoadedLeftOperand().getOperand() + } /** * Gets the `TranslatedLoad` on the `e` in this `e += ...` which is the @@ -1454,38 +1472,38 @@ class TranslatedAssignOperation extends TranslatedNonConstantExpr { kind instanceof GotoEdge and ( tag = AssignOperationConvertLeftTag() and - result = getInstruction(AssignOperationOpTag()) + result = this.getInstruction(AssignOperationOpTag()) or ( tag = AssignOperationOpTag() and - if leftOperandNeedsConversion() - then result = getInstruction(AssignOperationConvertResultTag()) - else result = getInstruction(AssignmentStoreTag()) + if this.leftOperandNeedsConversion() + then result = this.getInstruction(AssignOperationConvertResultTag()) + else result = this.getInstruction(AssignmentStoreTag()) ) or tag = AssignOperationConvertResultTag() and - result = getInstruction(AssignmentStoreTag()) + result = this.getInstruction(AssignmentStoreTag()) or tag = AssignmentStoreTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) ) } override Instruction getChildSuccessor(TranslatedElement child) { // Operands are evaluated right-to-left. - child = getRightOperand() and - result = getLoadedLeftOperand().getFirstInstruction() + child = this.getRightOperand() and + result = this.getLoadedLeftOperand().getFirstInstruction() or - child = getLoadedLeftOperand() and - if leftOperandNeedsConversion() - then result = getInstruction(AssignOperationConvertLeftTag()) - else result = getInstruction(AssignOperationOpTag()) + child = this.getLoadedLeftOperand() and + if this.leftOperandNeedsConversion() + then result = this.getInstruction(AssignOperationConvertLeftTag()) + else result = this.getInstruction(AssignOperationOpTag()) } private Instruction getStoredValue() { - if leftOperandNeedsConversion() - then result = getInstruction(AssignOperationConvertResultTag()) - else result = getInstruction(AssignOperationOpTag()) + if this.leftOperandNeedsConversion() + then result = this.getInstruction(AssignOperationConvertResultTag()) + else result = this.getInstruction(AssignOperationOpTag()) } private Type getConvertedLeftOperandType() { @@ -1502,15 +1520,15 @@ class TranslatedAssignOperation extends TranslatedNonConstantExpr { // anyway. If we really want to model this case perfectly, we'll need the // extractor to tell us what the promoted type of the left operand would // be. - result = getLoadedLeftOperand().getExpr().getType() + result = this.getLoadedLeftOperand().getExpr().getType() else // The right operand has already been converted to the type of the op. - result = getRightOperand().getExpr().getType() + result = this.getRightOperand().getExpr().getType() } private predicate leftOperandNeedsConversion() { - getConvertedLeftOperandType().getUnspecifiedType() != - getLoadedLeftOperand().getExpr().getUnspecifiedType() + this.getConvertedLeftOperandType().getUnspecifiedType() != + this.getLoadedLeftOperand().getExpr().getUnspecifiedType() } private Opcode getOpcode() { @@ -1541,64 +1559,64 @@ class TranslatedAssignOperation extends TranslatedNonConstantExpr { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = AssignOperationOpTag() and - opcode = getOpcode() and - resultType = getTypeForPRValue(getConvertedLeftOperandType()) + opcode = this.getOpcode() and + resultType = getTypeForPRValue(this.getConvertedLeftOperandType()) or tag = AssignmentStoreTag() and opcode instanceof Opcode::Store and resultType = getTypeForPRValue(expr.getType()) // Always a prvalue or - leftOperandNeedsConversion() and + this.leftOperandNeedsConversion() and opcode instanceof Opcode::Convert and ( tag = AssignOperationConvertLeftTag() and - resultType = getTypeForPRValue(getConvertedLeftOperandType()) + resultType = getTypeForPRValue(this.getConvertedLeftOperandType()) or tag = AssignOperationConvertResultTag() and - resultType = getTypeForPRValue(getLoadedLeftOperand().getExpr().getType()) + resultType = getTypeForPRValue(this.getLoadedLeftOperand().getExpr().getType()) ) } override int getInstructionElementSize(InstructionTag tag) { tag = AssignOperationOpTag() and exists(Opcode opcode | - opcode = getOpcode() and + opcode = this.getOpcode() and (opcode instanceof Opcode::PointerAdd or opcode instanceof Opcode::PointerSub) ) and result = getElementSize(expr.getType()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { - leftOperandNeedsConversion() and + this.leftOperandNeedsConversion() and tag = AssignOperationConvertLeftTag() and operandTag instanceof UnaryOperandTag and - result = getLoadedLeftOperand().getResult() + result = this.getLoadedLeftOperand().getResult() or tag = AssignOperationOpTag() and ( ( operandTag instanceof LeftOperandTag and - if leftOperandNeedsConversion() - then result = getInstruction(AssignOperationConvertLeftTag()) - else result = getLoadedLeftOperand().getResult() + if this.leftOperandNeedsConversion() + then result = this.getInstruction(AssignOperationConvertLeftTag()) + else result = this.getLoadedLeftOperand().getResult() ) or operandTag instanceof RightOperandTag and - result = getRightOperand().getResult() + result = this.getRightOperand().getResult() ) or - leftOperandNeedsConversion() and + this.leftOperandNeedsConversion() and tag = AssignOperationConvertResultTag() and operandTag instanceof UnaryOperandTag and - result = getInstruction(AssignOperationOpTag()) + result = this.getInstruction(AssignOperationOpTag()) or tag = AssignmentStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getUnloadedLeftOperand().getResult() + result = this.getUnloadedLeftOperand().getResult() or operandTag instanceof StoreValueOperandTag and - result = getStoredValue() + result = this.getStoredValue() ) } } @@ -1619,7 +1637,7 @@ abstract class TranslatedAllocationSize extends TranslatedExpr, TTranslatedAlloc final override predicate producesExprResult() { none() } - final override Instruction getResult() { result = getInstruction(AllocationSizeTag()) } + final override Instruction getResult() { result = this.getInstruction(AllocationSizeTag()) } } TranslatedAllocationSize getTranslatedAllocationSize(NewOrNewArrayExpr newExpr) { @@ -1636,7 +1654,9 @@ TranslatedAllocationSize getTranslatedAllocationSize(NewOrNewArrayExpr newExpr) class TranslatedConstantAllocationSize extends TranslatedAllocationSize { TranslatedConstantAllocationSize() { not exists(expr.(NewArrayExpr).getExtent()) } - final override Instruction getFirstInstruction() { result = getInstruction(AllocationSizeTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(AllocationSizeTag()) + } final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = AllocationSizeTag() and @@ -1647,7 +1667,7 @@ class TranslatedConstantAllocationSize extends TranslatedAllocationSize { final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = AllocationSizeTag() and kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } final override TranslatedElement getChild(int id) { none() } @@ -1672,7 +1692,9 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize { TranslatedNonConstantAllocationSize() { exists(expr.getExtent()) } - final override Instruction getFirstInstruction() { result = getExtent().getFirstInstruction() } + final override Instruction getFirstInstruction() { + result = this.getExtent().getFirstInstruction() + } final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { resultType = getTypeForPRValue(expr.getAllocator().getParameter(0).getType()) and @@ -1690,21 +1712,21 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize { kind instanceof GotoEdge and ( tag = AllocationExtentConvertTag() and - result = getInstruction(AllocationElementSizeTag()) + result = this.getInstruction(AllocationElementSizeTag()) or tag = AllocationElementSizeTag() and - result = getInstruction(AllocationSizeTag()) + result = this.getInstruction(AllocationSizeTag()) or tag = AllocationSizeTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) ) } - final override TranslatedElement getChild(int id) { id = 0 and result = getExtent() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getExtent() } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getExtent() and - result = getInstruction(AllocationExtentConvertTag()) + child = this.getExtent() and + result = this.getInstruction(AllocationExtentConvertTag()) } final override string getInstructionConstantValue(InstructionTag tag) { @@ -1715,14 +1737,16 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize { final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = AllocationSizeTag() and ( - operandTag instanceof LeftOperandTag and result = getInstruction(AllocationExtentConvertTag()) + operandTag instanceof LeftOperandTag and + result = this.getInstruction(AllocationExtentConvertTag()) or - operandTag instanceof RightOperandTag and result = getInstruction(AllocationElementSizeTag()) + operandTag instanceof RightOperandTag and + result = this.getInstruction(AllocationElementSizeTag()) ) or tag = AllocationExtentConvertTag() and operandTag instanceof UnaryOperandTag and - result = getExtent().getResult() + result = this.getExtent().getResult() } private TranslatedExpr getExtent() { @@ -1806,7 +1830,7 @@ abstract class StructorCallContext extends TranslatedElement { class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, StructorCallContext { override DestructorFieldDestruction expr; - final override TranslatedElement getChild(int id) { id = 0 and result = getDestructorCall() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getDestructorCall() } final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and @@ -1817,17 +1841,19 @@ class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, St final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and - result = getDestructorCall().getFirstInstruction() + result = this.getDestructorCall().getFirstInstruction() } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getDestructorCall() and - result = getParent().getChildSuccessor(this) + child = this.getDestructorCall() and + result = this.getParent().getChildSuccessor(this) } final override Instruction getResult() { none() } - final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(OnlyInstructionTag()) + } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and @@ -1840,7 +1866,7 @@ class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, St result = expr.getTarget() } - final override Instruction getReceiver() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getReceiver() { result = this.getInstruction(OnlyInstructionTag()) } private TranslatedExpr getDestructorCall() { result = getTranslatedExpr(expr.getExpr()) } } @@ -1859,12 +1885,12 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr { // the condition directly to the appropriate then/else block via // `getChild[True|False]Successor()`. // The binary flavor will override this predicate to add the `ConditionalBranch`. - not resultIsVoid() and + not this.resultIsVoid() and ( ( - not thenIsVoid() and tag = ConditionValueTrueTempAddressTag() + not this.thenIsVoid() and tag = ConditionValueTrueTempAddressTag() or - not elseIsVoid() and tag = ConditionValueFalseTempAddressTag() + not this.elseIsVoid() and tag = ConditionValueFalseTempAddressTag() or tag = ConditionValueResultTempAddressTag() ) and @@ -1876,106 +1902,106 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr { ) or ( - not thenIsVoid() and tag = ConditionValueTrueStoreTag() + not this.thenIsVoid() and tag = ConditionValueTrueStoreTag() or - not elseIsVoid() and tag = ConditionValueFalseStoreTag() + not this.elseIsVoid() and tag = ConditionValueFalseStoreTag() ) and opcode instanceof Opcode::Store and - resultType = getResultType() + resultType = this.getResultType() or tag = ConditionValueResultLoadTag() and opcode instanceof Opcode::Load and - resultType = getResultType() + resultType = this.getResultType() ) } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - not resultIsVoid() and + not this.resultIsVoid() and kind instanceof GotoEdge and ( - not thenIsVoid() and + not this.thenIsVoid() and ( tag = ConditionValueTrueTempAddressTag() and - result = getInstruction(ConditionValueTrueStoreTag()) + result = this.getInstruction(ConditionValueTrueStoreTag()) or tag = ConditionValueTrueStoreTag() and - result = getInstruction(ConditionValueResultTempAddressTag()) + result = this.getInstruction(ConditionValueResultTempAddressTag()) ) or - not elseIsVoid() and + not this.elseIsVoid() and ( tag = ConditionValueFalseTempAddressTag() and - result = getInstruction(ConditionValueFalseStoreTag()) + result = this.getInstruction(ConditionValueFalseStoreTag()) or tag = ConditionValueFalseStoreTag() and - result = getInstruction(ConditionValueResultTempAddressTag()) + result = this.getInstruction(ConditionValueResultTempAddressTag()) ) or tag = ConditionValueResultTempAddressTag() and - result = getInstruction(ConditionValueResultLoadTag()) + result = this.getInstruction(ConditionValueResultLoadTag()) or tag = ConditionValueResultLoadTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) ) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { - not resultIsVoid() and + not this.resultIsVoid() and ( - not thenIsVoid() and + not this.thenIsVoid() and tag = ConditionValueTrueStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueTrueTempAddressTag()) + result = this.getInstruction(ConditionValueTrueTempAddressTag()) or operandTag instanceof StoreValueOperandTag and - result = getThen().getResult() + result = this.getThen().getResult() ) or - not elseIsVoid() and + not this.elseIsVoid() and tag = ConditionValueFalseStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueFalseTempAddressTag()) + result = this.getInstruction(ConditionValueFalseTempAddressTag()) or operandTag instanceof StoreValueOperandTag and - result = getElse().getResult() + result = this.getElse().getResult() ) or tag = ConditionValueResultLoadTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueResultTempAddressTag()) + result = this.getInstruction(ConditionValueResultTempAddressTag()) ) ) } final override predicate hasTempVariable(TempVariableTag tag, CppType type) { - not resultIsVoid() and + not this.resultIsVoid() and tag = ConditionValueTempVar() and - type = getResultType() + type = this.getResultType() } final override IRVariable getInstructionVariable(InstructionTag tag) { - not resultIsVoid() and + not this.resultIsVoid() and ( tag = ConditionValueTrueTempAddressTag() or tag = ConditionValueFalseTempAddressTag() or tag = ConditionValueResultTempAddressTag() ) and - result = getTempVariable(ConditionValueTempVar()) + result = this.getTempVariable(ConditionValueTempVar()) } final override Instruction getResult() { - not resultIsVoid() and - result = getInstruction(ConditionValueResultLoadTag()) + not this.resultIsVoid() and + result = this.getInstruction(ConditionValueResultLoadTag()) } override Instruction getChildSuccessor(TranslatedElement child) { - child = getElse() and - if elseIsVoid() - then result = getParent().getChildSuccessor(this) - else result = getInstruction(ConditionValueFalseTempAddressTag()) + child = this.getElse() and + if this.elseIsVoid() + then result = this.getParent().getChildSuccessor(this) + else result = this.getInstruction(ConditionValueFalseTempAddressTag()) } /** @@ -1990,7 +2016,7 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr { final TranslatedExpr getElse() { result = getTranslatedExpr(expr.getElse().getFullyConverted()) } final predicate thenIsVoid() { - getThen().getResultType().getIRType() instanceof IRVoidType + this.getThen().getResultType().getIRType() instanceof IRVoidType or // A `ThrowExpr.getType()` incorrectly returns the type of exception being // thrown, rather than `void`. Handle that case here. @@ -1998,14 +2024,14 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr { } private predicate elseIsVoid() { - getElse().getResultType().getIRType() instanceof IRVoidType + this.getElse().getResultType().getIRType() instanceof IRVoidType or // A `ThrowExpr.getType()` incorrectly returns the type of exception being // thrown, rather than `void`. Handle that case here. expr.getElse() instanceof ThrowExpr } - private predicate resultIsVoid() { getResultType().getIRType() instanceof IRVoidType } + private predicate resultIsVoid() { this.getResultType().getIRType() instanceof IRVoidType } } /** @@ -2017,34 +2043,34 @@ class TranslatedTernaryConditionalExpr extends TranslatedConditionalExpr, Condit TranslatedTernaryConditionalExpr() { not expr.isTwoOperand() } final override TranslatedElement getChild(int id) { - id = 0 and result = getCondition() + id = 0 and result = this.getCondition() or - id = 1 and result = getThen() + id = 1 and result = this.getThen() or - id = 2 and result = getElse() + id = 2 and result = this.getElse() } - override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getCondition().getFirstInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { result = TranslatedConditionalExpr.super.getChildSuccessor(child) or ( - child = getThen() and - if thenIsVoid() - then result = getParent().getChildSuccessor(this) - else result = getInstruction(ConditionValueTrueTempAddressTag()) + child = this.getThen() and + if this.thenIsVoid() + then result = this.getParent().getChildSuccessor(this) + else result = this.getInstruction(ConditionValueTrueTempAddressTag()) ) } 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 - result = getElse().getFirstInstruction() + child = this.getCondition() and + result = this.getElse().getFirstInstruction() } private TranslatedCondition getCondition() { @@ -2069,12 +2095,12 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr { final override TranslatedElement getChild(int id) { // We only truly have two children, because our "condition" and "then" are the same as far as // the extractor is concerned. - id = 0 and result = getCondition() + id = 0 and result = this.getCondition() or - id = 1 and result = getElse() + id = 1 and result = this.getElse() } - override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getCondition().getFirstInstruction() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { super.hasInstruction(opcode, tag, resultType) @@ -2091,10 +2117,10 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr { tag = ValueConditionConditionalBranchTag() and ( kind instanceof TrueEdge and - result = getInstruction(ConditionValueTrueTempAddressTag()) + result = this.getInstruction(ConditionValueTrueTempAddressTag()) or kind instanceof FalseEdge and - result = getElse().getFirstInstruction() + result = this.getElse().getFirstInstruction() ) } @@ -2103,13 +2129,14 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr { or tag = ValueConditionConditionalBranchTag() and operandTag instanceof ConditionOperandTag and - result = getCondition().getResult() + result = this.getCondition().getResult() } override Instruction getChildSuccessor(TranslatedElement child) { result = super.getChildSuccessor(child) or - child = getCondition() and result = getInstruction(ValueConditionConditionalBranchTag()) + child = this.getCondition() and + result = this.getInstruction(ValueConditionConditionalBranchTag()) } private TranslatedExpr getCondition() { @@ -2154,10 +2181,10 @@ class TranslatedTemporaryObjectExpr extends TranslatedNonConstantExpr, } final override Instruction getInitializationSuccessor() { - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } - final override Instruction getResult() { result = getTargetAddress() } + final override Instruction getResult() { result = this.getTargetAddress() } } /** @@ -2168,14 +2195,14 @@ abstract class TranslatedThrowExpr extends TranslatedNonConstantExpr { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = ThrowTag() and - opcode = getThrowOpcode() and + opcode = this.getThrowOpcode() and resultType = getVoidType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = ThrowTag() and kind instanceof ExceptionEdge and - result = getParent().getExceptionSuccessorInstruction() + result = this.getParent().getExceptionSuccessorInstruction() } override Instruction getResult() { none() } @@ -2202,11 +2229,13 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, TranslatedVariableIn result = TranslatedVariableInitialization.super.getInstructionSuccessor(tag, kind) } - final override Instruction getInitializationSuccessor() { result = getInstruction(ThrowTag()) } + final override Instruction getInitializationSuccessor() { + result = this.getInstruction(ThrowTag()) + } final override predicate hasTempVariable(TempVariableTag tag, CppType type) { tag = ThrowTempVar() and - type = getTypeForPRValue(getExceptionType()) + type = getTypeForPRValue(this.getExceptionType()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { @@ -2215,7 +2244,7 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, TranslatedVariableIn tag = ThrowTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) ) } @@ -2224,10 +2253,10 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, TranslatedVariableIn ) { tag = ThrowTag() and operandTag instanceof LoadOperandTag and - result = getTypeForPRValue(getExceptionType()) + result = getTypeForPRValue(this.getExceptionType()) } - override Type getTargetType() { result = getExceptionType() } + override Type getTargetType() { result = this.getExceptionType() } final override TranslatedInitialization getInitialization() { result = getTranslatedInitialization(expr.getExpr().getFullyConverted()) @@ -2248,7 +2277,7 @@ class TranslatedReThrowExpr extends TranslatedThrowExpr { override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { result = getInstruction(ThrowTag()) } + override Instruction getFirstInstruction() { result = this.getInstruction(ThrowTag()) } override Instruction getChildSuccessor(TranslatedElement child) { none() } @@ -2271,12 +2300,12 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr { not expr instanceof BuiltInVarArgCopy } - final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getFirstInstruction() { - if exists(getChild(0)) - then result = getChild(0).getFirstInstruction() - else result = getInstruction(OnlyInstructionTag()) + if exists(this.getChild(0)) + then result = this.getChild(0).getFirstInstruction() + else result = this.getInstruction(OnlyInstructionTag()) } final override TranslatedElement getChild(int id) { @@ -2286,31 +2315,31 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr { final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } final override Instruction getChildSuccessor(TranslatedElement child) { exists(int id | - child = getChild(id) and + child = this.getChild(id) and ( - result = getChild(id + 1).getFirstInstruction() + result = this.getChild(id + 1).getFirstInstruction() or - not exists(getChild(id + 1)) and result = getInstruction(OnlyInstructionTag()) + not exists(this.getChild(id + 1)) and result = this.getInstruction(OnlyInstructionTag()) ) ) } final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and - opcode = getOpcode() and - resultType = getResultType() + opcode = this.getOpcode() and + resultType = this.getResultType() } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and exists(int index | operandTag = positionalArgumentOperand(index) and - result = getChild(index).(TranslatedExpr).getResult() + result = this.getChild(index).(TranslatedExpr).getResult() ) } @@ -2391,12 +2420,12 @@ class TranslatedVarArgsStart extends TranslatedNonConstantExpr { } final override Instruction getFirstInstruction() { - result = getInstruction(VarArgsStartEllipsisAddressTag()) + result = this.getInstruction(VarArgsStartEllipsisAddressTag()) } final override Instruction getResult() { none() } - final override TranslatedElement getChild(int id) { id = 0 and result = getVAList() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getVAList() } private TranslatedExpr getVAList() { result = getTranslatedExpr(expr.getVAList().getFullyConverted()) @@ -2405,37 +2434,37 @@ class TranslatedVarArgsStart extends TranslatedNonConstantExpr { final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = VarArgsStartEllipsisAddressTag() and kind instanceof GotoEdge and - result = getInstruction(VarArgsStartTag()) + result = this.getInstruction(VarArgsStartTag()) or tag = VarArgsStartTag() and kind instanceof GotoEdge and - result = getVAList().getFirstInstruction() + result = this.getVAList().getFirstInstruction() or tag = VarArgsVAListStoreTag() and kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getVAList() and - result = getInstruction(VarArgsVAListStoreTag()) + child = this.getVAList() and + result = this.getInstruction(VarArgsVAListStoreTag()) } final override IRVariable getInstructionVariable(InstructionTag tag) { tag = VarArgsStartEllipsisAddressTag() and - result = getEnclosingFunction().getEllipsisVariable() + result = this.getEnclosingFunction().getEllipsisVariable() } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = VarArgsStartTag() and operandTag instanceof UnaryOperandTag and - result = getInstruction(VarArgsStartEllipsisAddressTag()) + result = this.getInstruction(VarArgsStartEllipsisAddressTag()) or tag = VarArgsVAListStoreTag() and ( - operandTag instanceof AddressOperandTag and result = getVAList().getResult() + operandTag instanceof AddressOperandTag and result = this.getVAList().getResult() or - operandTag instanceof StoreValueOperandTag and result = getInstruction(VarArgsStartTag()) + operandTag instanceof StoreValueOperandTag and result = this.getInstruction(VarArgsStartTag()) ) } } @@ -2453,7 +2482,7 @@ class TranslatedVarArg extends TranslatedNonConstantExpr { or tag = VarArgsArgAddressTag() and opcode instanceof Opcode::VarArg and - resultType = getResultType() + resultType = this.getResultType() or tag = VarArgsMoveNextTag() and opcode instanceof Opcode::NextVarArg and @@ -2464,11 +2493,13 @@ class TranslatedVarArg extends TranslatedNonConstantExpr { resultType = getTypeForPRValue(getVAListType(expr.getVAList().getFullyConverted())) } - final override Instruction getFirstInstruction() { result = getVAList().getFirstInstruction() } + final override Instruction getFirstInstruction() { + result = this.getVAList().getFirstInstruction() + } - final override Instruction getResult() { result = getInstruction(VarArgsArgAddressTag()) } + final override Instruction getResult() { result = this.getInstruction(VarArgsArgAddressTag()) } - final override TranslatedElement getChild(int id) { id = 0 and result = getVAList() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getVAList() } private TranslatedExpr getVAList() { result = getTranslatedExpr(expr.getVAList().getFullyConverted()) @@ -2477,46 +2508,47 @@ class TranslatedVarArg extends TranslatedNonConstantExpr { final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = VarArgsVAListLoadTag() and kind instanceof GotoEdge and - result = getInstruction(VarArgsArgAddressTag()) + result = this.getInstruction(VarArgsArgAddressTag()) or tag = VarArgsArgAddressTag() and kind instanceof GotoEdge and - result = getInstruction(VarArgsMoveNextTag()) + result = this.getInstruction(VarArgsMoveNextTag()) or tag = VarArgsMoveNextTag() and kind instanceof GotoEdge and - result = getInstruction(VarArgsVAListStoreTag()) + result = this.getInstruction(VarArgsVAListStoreTag()) or tag = VarArgsVAListStoreTag() and kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getVAList() and - result = getInstruction(VarArgsVAListLoadTag()) + child = this.getVAList() and + result = this.getInstruction(VarArgsVAListLoadTag()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = VarArgsVAListLoadTag() and ( operandTag instanceof AddressOperandTag and - result = getVAList().getResult() + result = this.getVAList().getResult() ) or tag = VarArgsArgAddressTag() and operandTag instanceof UnaryOperandTag and - result = getInstruction(VarArgsVAListLoadTag()) + result = this.getInstruction(VarArgsVAListLoadTag()) or tag = VarArgsMoveNextTag() and operandTag instanceof UnaryOperandTag and - result = getInstruction(VarArgsVAListLoadTag()) + result = this.getInstruction(VarArgsVAListLoadTag()) or tag = VarArgsVAListStoreTag() and ( - operandTag instanceof AddressOperandTag and result = getVAList().getResult() + operandTag instanceof AddressOperandTag and result = this.getVAList().getResult() or - operandTag instanceof StoreValueOperandTag and result = getInstruction(VarArgsMoveNextTag()) + operandTag instanceof StoreValueOperandTag and + result = this.getInstruction(VarArgsMoveNextTag()) ) } } @@ -2533,11 +2565,13 @@ class TranslatedVarArgsEnd extends TranslatedNonConstantExpr { resultType = getVoidType() } - final override Instruction getFirstInstruction() { result = getVAList().getFirstInstruction() } + final override Instruction getFirstInstruction() { + result = this.getVAList().getFirstInstruction() + } final override Instruction getResult() { none() } - final override TranslatedElement getChild(int id) { id = 0 and result = getVAList() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getVAList() } private TranslatedExpr getVAList() { result = getTranslatedExpr(expr.getVAList().getFullyConverted()) @@ -2546,18 +2580,18 @@ class TranslatedVarArgsEnd extends TranslatedNonConstantExpr { final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getVAList() and - result = getInstruction(OnlyInstructionTag()) + child = this.getVAList() and + result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and - result = getVAList().getResult() + result = this.getVAList().getResult() } } @@ -2578,15 +2612,15 @@ class TranslatedVarArgCopy extends TranslatedNonConstantExpr { } final override Instruction getFirstInstruction() { - result = getSourceVAList().getFirstInstruction() + result = this.getSourceVAList().getFirstInstruction() } - final override Instruction getResult() { result = getInstruction(VarArgsVAListStoreTag()) } + final override Instruction getResult() { result = this.getInstruction(VarArgsVAListStoreTag()) } final override TranslatedElement getChild(int id) { - id = 0 and result = getDestinationVAList() + id = 0 and result = this.getDestinationVAList() or - id = 1 and result = getSourceVAList() + id = 1 and result = this.getSourceVAList() } private TranslatedExpr getDestinationVAList() { @@ -2600,33 +2634,34 @@ class TranslatedVarArgCopy extends TranslatedNonConstantExpr { final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = VarArgsVAListLoadTag() and kind instanceof GotoEdge and - result = getDestinationVAList().getFirstInstruction() + result = this.getDestinationVAList().getFirstInstruction() or tag = VarArgsVAListStoreTag() and kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getSourceVAList() and - result = getInstruction(VarArgsVAListLoadTag()) + child = this.getSourceVAList() and + result = this.getInstruction(VarArgsVAListLoadTag()) or - child = getDestinationVAList() and - result = getInstruction(VarArgsVAListStoreTag()) + child = this.getDestinationVAList() and + result = this.getInstruction(VarArgsVAListStoreTag()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = VarArgsVAListLoadTag() and ( operandTag instanceof AddressOperandTag and - result = getSourceVAList().getResult() + result = this.getSourceVAList().getResult() ) or tag = VarArgsVAListStoreTag() and ( - operandTag instanceof AddressOperandTag and result = getDestinationVAList().getResult() + operandTag instanceof AddressOperandTag and result = this.getDestinationVAList().getResult() or - operandTag instanceof StoreValueOperandTag and result = getInstruction(VarArgsVAListLoadTag()) + operandTag instanceof StoreValueOperandTag and + result = this.getInstruction(VarArgsVAListLoadTag()) ) } } @@ -2638,44 +2673,46 @@ abstract class TranslatedNewOrNewArrayExpr extends TranslatedNonConstantExpr, In override NewOrNewArrayExpr expr; final override TranslatedElement getChild(int id) { - id = 0 and result = getAllocatorCall() + id = 0 and result = this.getAllocatorCall() or - id = 1 and result = getInitialization() + id = 1 and result = this.getInitialization() } final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and opcode instanceof Opcode::Convert and - resultType = getResultType() + resultType = this.getResultType() } final override Instruction getFirstInstruction() { - result = getAllocatorCall().getFirstInstruction() + result = this.getAllocatorCall().getFirstInstruction() } - final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and tag = OnlyInstructionTag() and - if exists(getInitialization()) - then result = getInitialization().getFirstInstruction() - else result = getParent().getChildSuccessor(this) + if exists(this.getInitialization()) + then result = this.getInitialization().getFirstInstruction() + else result = this.getParent().getChildSuccessor(this) } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getAllocatorCall() and result = getInstruction(OnlyInstructionTag()) + child = this.getAllocatorCall() and result = this.getInstruction(OnlyInstructionTag()) or - child = getInitialization() and result = getParent().getChildSuccessor(this) + child = this.getInitialization() and result = this.getParent().getChildSuccessor(this) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and - result = getAllocatorCall().getResult() + result = this.getAllocatorCall().getResult() } - final override Instruction getTargetAddress() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getTargetAddress() { + result = this.getInstruction(OnlyInstructionTag()) + } private TranslatedAllocatorCall getAllocatorCall() { result = getTranslatedAllocatorCall(expr) } @@ -2718,18 +2755,20 @@ class TranslatedNewArrayExpr extends TranslatedNewOrNewArrayExpr { class TranslatedDeleteArrayExprPlaceHolder extends TranslatedSingleInstructionExpr { override DeleteArrayExpr expr; - final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + final override Instruction getFirstInstruction() { + result = this.getOperand().getFirstInstruction() + } - final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getOperand() and result = getInstruction(OnlyInstructionTag()) + child = this.getOperand() and result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { @@ -2752,18 +2791,20 @@ class TranslatedDeleteArrayExprPlaceHolder extends TranslatedSingleInstructionEx class TranslatedDeleteExprPlaceHolder extends TranslatedSingleInstructionExpr { override DeleteExpr expr; - final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + final override Instruction getFirstInstruction() { + result = this.getOperand().getFirstInstruction() + } - final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getOperand() and result = getInstruction(OnlyInstructionTag()) + child = this.getOperand() and result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { @@ -2788,23 +2829,23 @@ class TranslatedDeleteExprPlaceHolder extends TranslatedSingleInstructionExpr { class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr { override ConditionDeclExpr expr; - final override Instruction getFirstInstruction() { result = getDecl().getFirstInstruction() } + final override Instruction getFirstInstruction() { result = this.getDecl().getFirstInstruction() } final override TranslatedElement getChild(int id) { - id = 0 and result = getDecl() + id = 0 and result = this.getDecl() or - id = 1 and result = getConditionExpr() + id = 1 and result = this.getConditionExpr() } - override Instruction getResult() { result = getConditionExpr().getResult() } + override Instruction getResult() { result = this.getConditionExpr().getResult() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { - child = getDecl() and - result = getConditionExpr().getFirstInstruction() + child = this.getDecl() and + result = this.getConditionExpr().getFirstInstruction() or - child = getConditionExpr() and result = getParent().getChildSuccessor(this) + child = this.getConditionExpr() and result = this.getParent().getChildSuccessor(this) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -2826,34 +2867,34 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont override LambdaExpression expr; final override Instruction getFirstInstruction() { - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) } - final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() } - override Instruction getResult() { result = getInstruction(LoadTag()) } + override Instruction getResult() { result = this.getInstruction(LoadTag()) } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = InitializerVariableAddressTag() and kind instanceof GotoEdge and - result = getInstruction(InitializerStoreTag()) + result = this.getInstruction(InitializerStoreTag()) or tag = InitializerStoreTag() and kind instanceof GotoEdge and ( - result = getInitialization().getFirstInstruction() + result = this.getInitialization().getFirstInstruction() or - not hasInitializer() and result = getInstruction(LoadTag()) + not this.hasInitializer() and result = this.getInstruction(LoadTag()) ) or tag = LoadTag() and kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and - result = getInstruction(LoadTag()) + child = this.getInitialization() and + result = this.getInstruction(LoadTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -2873,12 +2914,12 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = InitializerStoreTag() and operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) or tag = LoadTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) ) } @@ -2887,7 +2928,7 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont tag = InitializerVariableAddressTag() or tag = InitializerStoreTag() ) and - result = getTempVariable(LambdaTempVar()) + result = this.getTempVariable(LambdaTempVar()) } override predicate hasTempVariable(TempVariableTag tag, CppType type) { @@ -2896,12 +2937,12 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont } final override Instruction getTargetAddress() { - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) } final override Type getTargetType() { result = expr.getType() } - private predicate hasInitializer() { exists(getInitialization()) } + private predicate hasInitializer() { exists(this.getInitialization()) } private TranslatedInitialization getInitialization() { result = getTranslatedInitialization(expr.getChild(0).getFullyConverted()) @@ -2915,28 +2956,28 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont class TranslatedStmtExpr extends TranslatedNonConstantExpr { override StmtExpr expr; - final override Instruction getFirstInstruction() { result = getStmt().getFirstInstruction() } + final override Instruction getFirstInstruction() { result = this.getStmt().getFirstInstruction() } - final override TranslatedElement getChild(int id) { id = 0 and result = getStmt() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getStmt() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag instanceof OnlyInstructionTag and kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } override Instruction getChildSuccessor(TranslatedElement child) { - child = getStmt() and - result = getInstruction(OnlyInstructionTag()) + child = this.getStmt() and + result = this.getInstruction(OnlyInstructionTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { opcode instanceof Opcode::CopyValue and tag instanceof OnlyInstructionTag and - resultType = getResultType() + resultType = this.getResultType() } - override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag instanceof OnlyInstructionTag and @@ -2950,13 +2991,15 @@ class TranslatedStmtExpr extends TranslatedNonConstantExpr { class TranslatedErrorExpr extends TranslatedSingleInstructionExpr { override ErrorExpr expr; - final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(OnlyInstructionTag()) + } final override TranslatedElement getChild(int id) { none() } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } @@ -3034,13 +3077,15 @@ class TranslatedAssumeExpr extends TranslatedSingleInstructionExpr { final override Opcode getOpcode() { result instanceof Opcode::NoOp } - final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(OnlyInstructionTag()) + } final override TranslatedElement getChild(int id) { none() } final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } diff --git a/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll b/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll index 33a256ce3e5..496e3f4511d 100644 --- a/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll +++ b/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll @@ -366,7 +366,7 @@ class MetricClass extends Class { 1 + count(string s | exists(Operation op | op = this.getAnEnclosedExpression() and s = op.getOperator()) - ) + count(string s | s = getAUsedHalsteadN1Operator()) + ) + count(string s | s = this.getAUsedHalsteadN1Operator()) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/metrics/MetricFile.qll b/cpp/ql/lib/semmle/code/cpp/metrics/MetricFile.qll index f12d1011865..b3838ce4a5a 100644 --- a/cpp/ql/lib/semmle/code/cpp/metrics/MetricFile.qll +++ b/cpp/ql/lib/semmle/code/cpp/metrics/MetricFile.qll @@ -134,7 +134,7 @@ class MetricFile extends File { result = // avoid 0 values 1 + count(string s | exists(Operation op | op.getFile() = this and s = op.getOperator())) + - count(string s | s = getAUsedHalsteadN1Operator()) + count(string s | s = this.getAUsedHalsteadN1Operator()) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/metrics/MetricFunction.qll b/cpp/ql/lib/semmle/code/cpp/metrics/MetricFunction.qll index 45036cfddf3..960e06c8375 100644 --- a/cpp/ql/lib/semmle/code/cpp/metrics/MetricFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/metrics/MetricFunction.qll @@ -41,7 +41,7 @@ class MetricFunction extends Function { * `&&`, and `||`) plus one. */ int getCyclomaticComplexity() { - result = 1 + cyclomaticComplexityBranches(getBlock()) and + result = 1 + cyclomaticComplexityBranches(this.getBlock()) and not this.isMultiplyDefined() } @@ -295,7 +295,7 @@ class MetricFunction extends Function { int getNestingDepth() { result = max(Stmt s, int aDepth | s.getEnclosingFunction() = this and nestingDepth(s, aDepth) | aDepth) and - not isMultiplyDefined() + not this.isMultiplyDefined() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll index b91eff2b3d9..1da6e3b0b3b 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll @@ -15,10 +15,10 @@ private class MallocAllocationFunction extends AllocationFunction { MallocAllocationFunction() { // --- C library allocation - hasGlobalOrStdOrBslName("malloc") and // malloc(size) + this.hasGlobalOrStdOrBslName("malloc") and // malloc(size) sizeArg = 0 or - hasGlobalName([ + this.hasGlobalName([ // --- Windows Memory Management for Windows Drivers "MmAllocateContiguousMemory", // MmAllocateContiguousMemory(size, maxaddress) "MmAllocateContiguousNodeMemory", // MmAllocateContiguousNodeMemory(size, minaddress, maxaddress, bound, flag, prefer) @@ -39,7 +39,7 @@ private class MallocAllocationFunction extends AllocationFunction { ]) and sizeArg = 0 or - hasGlobalName([ + this.hasGlobalName([ // --- Windows Memory Management for Windows Drivers "ExAllocatePool", // ExAllocatePool(type, size) "ExAllocatePoolWithTag", // ExAllocatePool(type, size, tag) @@ -56,10 +56,10 @@ private class MallocAllocationFunction extends AllocationFunction { ]) and sizeArg = 1 or - hasGlobalName("HeapAlloc") and // HeapAlloc(heap, flags, size) + this.hasGlobalName("HeapAlloc") and // HeapAlloc(heap, flags, size) sizeArg = 2 or - hasGlobalName([ + this.hasGlobalName([ // --- Windows Memory Management for Windows Drivers "MmAllocatePagesForMdl", // MmAllocatePagesForMdl(minaddress, maxaddress, skip, size) "MmAllocatePagesForMdlEx", // MmAllocatePagesForMdlEx(minaddress, maxaddress, skip, size, type, flags) @@ -79,7 +79,7 @@ private class AllocaAllocationFunction extends AllocationFunction { int sizeArg; AllocaAllocationFunction() { - hasGlobalName([ + this.hasGlobalName([ // --- stack allocation "alloca", // // alloca(size) "__builtin_alloca", // __builtin_alloca(size) @@ -104,7 +104,7 @@ private class CallocAllocationFunction extends AllocationFunction { CallocAllocationFunction() { // --- C library allocation - hasGlobalOrStdOrBslName("calloc") and // calloc(num, size) + this.hasGlobalOrStdOrBslName("calloc") and // calloc(num, size) sizeArg = 1 and multArg = 0 } @@ -124,11 +124,11 @@ private class ReallocAllocationFunction extends AllocationFunction { ReallocAllocationFunction() { // --- C library allocation - hasGlobalOrStdOrBslName("realloc") and // realloc(ptr, size) + this.hasGlobalOrStdOrBslName("realloc") and // realloc(ptr, size) sizeArg = 1 and reallocArg = 0 or - hasGlobalName([ + this.hasGlobalName([ // --- Windows Global / Local legacy allocation "LocalReAlloc", // LocalReAlloc(ptr, size, flags) "GlobalReAlloc", // GlobalReAlloc(ptr, size, flags) @@ -140,7 +140,7 @@ private class ReallocAllocationFunction extends AllocationFunction { sizeArg = 1 and reallocArg = 0 or - hasGlobalName("HeapReAlloc") and // HeapReAlloc(heap, flags, ptr, size) + this.hasGlobalName("HeapReAlloc") and // HeapReAlloc(heap, flags, ptr, size) sizeArg = 3 and reallocArg = 2 } @@ -156,7 +156,7 @@ private class ReallocAllocationFunction extends AllocationFunction { */ private class SizelessAllocationFunction extends AllocationFunction { SizelessAllocationFunction() { - hasGlobalName([ + this.hasGlobalName([ // --- Windows Memory Management for Windows Drivers "ExAllocateFromLookasideListEx", // ExAllocateFromLookasideListEx(list) "ExAllocateFromPagedLookasideList", // ExAllocateFromPagedLookasideList(list) @@ -209,18 +209,18 @@ private class CallAllocationExpr extends AllocationExpr, FunctionCall { AllocationFunction target; CallAllocationExpr() { - target = getTarget() and + target = this.getTarget() and // realloc(ptr, 0) only frees the pointer not ( exists(target.getReallocPtrArg()) and - getArgument(target.getSizeArg()).getValue().toInt() = 0 + this.getArgument(target.getSizeArg()).getValue().toInt() = 0 ) and // these are modelled directly (and more accurately), avoid duplication not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this) } override Expr getSizeExpr() { - exists(Expr sizeExpr | sizeExpr = getArgument(target.getSizeArg()) | + exists(Expr sizeExpr | sizeExpr = this.getArgument(target.getSizeArg()) | if exists(target.getSizeMult()) then result = sizeExpr else @@ -233,16 +233,18 @@ private class CallAllocationExpr extends AllocationExpr, FunctionCall { override int getSizeMult() { // malloc with multiplier argument that is a constant - result = getArgument(target.getSizeMult()).getValue().toInt() + result = this.getArgument(target.getSizeMult()).getValue().toInt() or // malloc with no multiplier argument not exists(target.getSizeMult()) and - deconstructSizeExpr(getArgument(target.getSizeArg()), _, result) + deconstructSizeExpr(this.getArgument(target.getSizeArg()), _, result) } - override int getSizeBytes() { result = getSizeExpr().getValue().toInt() * getSizeMult() } + override int getSizeBytes() { + result = this.getSizeExpr().getValue().toInt() * this.getSizeMult() + } - override Expr getReallocPtr() { result = getArgument(target.getReallocPtrArg()) } + override Expr getReallocPtr() { result = this.getArgument(target.getReallocPtrArg()) } override Type getAllocatedElementType() { result = @@ -259,11 +261,11 @@ private class CallAllocationExpr extends AllocationExpr, FunctionCall { private class NewAllocationExpr extends AllocationExpr, NewExpr { NewAllocationExpr() { this instanceof NewExpr } - override int getSizeBytes() { result = getAllocatedType().getSize() } + override int getSizeBytes() { result = this.getAllocatedType().getSize() } - override Type getAllocatedElementType() { result = getAllocatedType() } + override Type getAllocatedElementType() { result = this.getAllocatedType() } - override predicate requiresDealloc() { not exists(getPlacementPointer()) } + override predicate requiresDealloc() { not exists(this.getPlacementPointer()) } } /** @@ -274,18 +276,18 @@ private class NewArrayAllocationExpr extends AllocationExpr, NewArrayExpr { override Expr getSizeExpr() { // new array expr with variable size - result = getExtent() + result = this.getExtent() } override int getSizeMult() { // new array expr with variable size - exists(getExtent()) and - result = getAllocatedElementType().getSize() + exists(this.getExtent()) and + result = this.getAllocatedElementType().getSize() } override Type getAllocatedElementType() { result = NewArrayExpr.super.getAllocatedElementType() } - override int getSizeBytes() { result = getAllocatedType().getSize() } + override int getSizeBytes() { result = this.getAllocatedType().getSize() } - override predicate requiresDealloc() { not exists(getPlacementPointer()) } + override predicate requiresDealloc() { not exists(this.getPlacementPointer()) } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll index e2015406346..67950b6e135 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.models.interfaces.FlowSource */ private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction, RemoteFlowSourceFunction { - GetDelimFunction() { hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) } + GetDelimFunction() { this.hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) } override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) { i.isParameter(3) and o.isParameterDeref(0) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll index 08222c2cd6a..407c11834e5 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll @@ -19,7 +19,7 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio // gets(str) // fgets(str, num, stream) // fgetws(wstr, num, stream) - hasGlobalOrStdOrBslName(["gets", "fgets", "fgetws"]) + this.hasGlobalOrStdOrBslName(["gets", "fgets", "fgetws"]) } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { @@ -54,13 +54,13 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio } override predicate hasArrayWithVariableSize(int bufParam, int countParam) { - not hasName("gets") and + not this.hasName("gets") and bufParam = 0 and countParam = 1 } override predicate hasArrayWithUnknownSize(int bufParam) { - hasName("gets") and + this.hasName("gets") and bufParam = 0 } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll index b7d8aed60fa..a8d0e94f43c 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll @@ -44,27 +44,27 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect */ int getParamSize() { if this.hasGlobalName("memccpy") then result = 3 else result = 2 } - override predicate hasArrayInput(int bufParam) { bufParam = getParamSrc() } + override predicate hasArrayInput(int bufParam) { bufParam = this.getParamSrc() } - override predicate hasArrayOutput(int bufParam) { bufParam = getParamDest() } + override predicate hasArrayOutput(int bufParam) { bufParam = this.getParamDest() } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { - input.isParameterDeref(getParamSrc()) and - output.isParameterDeref(getParamDest()) + input.isParameterDeref(this.getParamSrc()) and + output.isParameterDeref(this.getParamDest()) or - input.isParameterDeref(getParamSrc()) and + input.isParameterDeref(this.getParamSrc()) and output.isReturnValueDeref() or - input.isParameter(getParamDest()) and + input.isParameter(this.getParamDest()) and output.isReturnValue() } override predicate hasArrayWithVariableSize(int bufParam, int countParam) { ( - bufParam = getParamDest() or - bufParam = getParamSrc() + bufParam = this.getParamDest() or + bufParam = this.getParamSrc() ) and - countParam = getParamSize() + countParam = this.getParamSize() } override predicate hasOnlySpecificReadSideEffects() { any() } @@ -72,37 +72,37 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { - i = getParamDest() and + i = this.getParamDest() and buffer = true and // memccpy only writes until a given character `c` is found (if this.hasGlobalName("memccpy") then mustWrite = false else mustWrite = true) } override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { - i = getParamSrc() and buffer = true + i = this.getParamSrc() and buffer = true } override ParameterIndex getParameterSizeIndex(ParameterIndex i) { - result = getParamSize() and + result = this.getParamSize() and ( - i = getParamDest() or - i = getParamSrc() + i = this.getParamDest() or + i = this.getParamSrc() ) } override predicate parameterNeverEscapes(int index) { - index = getParamSrc() + index = this.getParamSrc() or - this.hasGlobalName("bcopy") and index = getParamDest() + this.hasGlobalName("bcopy") and index = this.getParamDest() } override predicate parameterEscapesOnlyViaReturn(int index) { - not this.hasGlobalName("bcopy") and index = getParamDest() + not this.hasGlobalName("bcopy") and index = this.getParamDest() } override predicate parameterIsAlwaysReturned(int index) { not this.hasGlobalName(["bcopy", mempcpy(), "memccpy"]) and - index = getParamDest() + index = this.getParamDest() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll index d646be0363d..11ef853a0bc 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll @@ -31,17 +31,17 @@ private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct override predicate hasArrayWithVariableSize(int bufParam, int countParam) { bufParam = 0 and - (if hasGlobalName(bzero()) then countParam = 1 else countParam = 2) + (if this.hasGlobalName(bzero()) then countParam = 1 else countParam = 2) } - override predicate parameterNeverEscapes(int index) { hasGlobalName(bzero()) and index = 0 } + override predicate parameterNeverEscapes(int index) { this.hasGlobalName(bzero()) and index = 0 } override predicate parameterEscapesOnlyViaReturn(int index) { - not hasGlobalName(bzero()) and index = 0 + not this.hasGlobalName(bzero()) and index = 0 } override predicate parameterIsAlwaysReturned(int index) { - not hasGlobalName(bzero()) and index = 0 + not this.hasGlobalName(bzero()) and index = 0 } override predicate hasOnlySpecificReadSideEffects() { any() } @@ -54,7 +54,7 @@ private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 0 and - if hasGlobalName(bzero()) then result = 1 else result = 2 + if this.hasGlobalName(bzero()) then result = 1 else result = 2 } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Pure.qll index d728a66463d..4efab29cabf 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Pure.qll @@ -10,49 +10,49 @@ import semmle.code.cpp.models.interfaces.SideEffect private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureStrFunction() { - hasGlobalOrStdOrBslName([ + this.hasGlobalOrStdOrBslName([ atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr", "strspn", strtol(), strrev(), strcmp(), strlwr(), strupr() ]) } override predicate hasArrayInput(int bufParam) { - getParameter(bufParam).getUnspecifiedType() instanceof PointerType + this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType } override predicate hasArrayWithNullTerminator(int bufParam) { - getParameter(bufParam).getUnspecifiedType() instanceof PointerType + this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists(ParameterIndex i | ( input.isParameter(i) and - exists(getParameter(i)) + exists(this.getParameter(i)) or input.isParameterDeref(i) and - getParameter(i).getUnspecifiedType() instanceof PointerType + this.getParameter(i).getUnspecifiedType() instanceof PointerType ) and // Functions that end with _l also take a locale argument (always as the last argument), // and we don't want taint from those arguments. - (not this.getName().matches("%\\_l") or exists(getParameter(i + 1))) + (not this.getName().matches("%\\_l") or exists(this.getParameter(i + 1))) ) and ( output.isReturnValueDeref() and - getUnspecifiedType() instanceof PointerType + this.getUnspecifiedType() instanceof PointerType or output.isReturnValue() ) } override predicate parameterNeverEscapes(int i) { - getParameter(i).getUnspecifiedType() instanceof PointerType and - not parameterEscapesOnlyViaReturn(i) + this.getParameter(i).getUnspecifiedType() instanceof PointerType and + not this.parameterEscapesOnlyViaReturn(i) } override predicate parameterEscapesOnlyViaReturn(int i) { i = 0 and - getUnspecifiedType() instanceof PointerType + this.getUnspecifiedType() instanceof PointerType } override predicate parameterIsAlwaysReturned(int i) { none() } @@ -62,7 +62,7 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { - getParameter(i).getUnspecifiedType() instanceof PointerType and + this.getParameter(i).getUnspecifiedType() instanceof PointerType and buffer = true } } @@ -97,21 +97,21 @@ private string strcmp() { */ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction { StrLenFunction() { - hasGlobalOrStdOrBslName(["strlen", "strnlen", "wcslen"]) + this.hasGlobalOrStdOrBslName(["strlen", "strnlen", "wcslen"]) or - hasGlobalName(["_mbslen", "_mbslen_l", "_mbstrlen", "_mbstrlen_l"]) + this.hasGlobalName(["_mbslen", "_mbslen_l", "_mbstrlen", "_mbstrlen_l"]) } override predicate hasArrayInput(int bufParam) { - getParameter(bufParam).getUnspecifiedType() instanceof PointerType + this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType } override predicate hasArrayWithNullTerminator(int bufParam) { - getParameter(bufParam).getUnspecifiedType() instanceof PointerType + this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType } override predicate parameterNeverEscapes(int i) { - getParameter(i).getUnspecifiedType() instanceof PointerType + this.getParameter(i).getUnspecifiedType() instanceof PointerType } override predicate parameterEscapesOnlyViaReturn(int i) { none() } @@ -123,7 +123,7 @@ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFun override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { - getParameter(i).getUnspecifiedType() instanceof PointerType and + this.getParameter(i).getUnspecifiedType() instanceof PointerType and buffer = true } } @@ -133,12 +133,12 @@ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFun * side-effect free. Excludes functions modeled by `PureStrFunction` and `PureMemFunction`. */ private class PureFunction extends TaintFunction, SideEffectFunction { - PureFunction() { hasGlobalOrStdOrBslName(["abs", "labs"]) } + PureFunction() { this.hasGlobalOrStdOrBslName(["abs", "labs"]) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists(ParameterIndex i | input.isParameter(i) and - exists(getParameter(i)) + exists(this.getParameter(i)) ) and output.isReturnValue() } @@ -155,44 +155,44 @@ private class PureFunction extends TaintFunction, SideEffectFunction { private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureMemFunction() { - hasGlobalOrStdOrBslName([ + this.hasGlobalOrStdOrBslName([ "memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem" ]) or this.hasGlobalName("memfrob") } override predicate hasArrayInput(int bufParam) { - getParameter(bufParam).getUnspecifiedType() instanceof PointerType + this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists(ParameterIndex i | ( input.isParameter(i) and - exists(getParameter(i)) + exists(this.getParameter(i)) or input.isParameterDeref(i) and - getParameter(i).getUnspecifiedType() instanceof PointerType + this.getParameter(i).getUnspecifiedType() instanceof PointerType ) and // `memfrob` should not have taint from the size argument. (not this.hasGlobalName("memfrob") or i = 0) ) and ( output.isReturnValueDeref() and - getUnspecifiedType() instanceof PointerType + this.getUnspecifiedType() instanceof PointerType or output.isReturnValue() ) } override predicate parameterNeverEscapes(int i) { - getParameter(i).getUnspecifiedType() instanceof PointerType and - not parameterEscapesOnlyViaReturn(i) + this.getParameter(i).getUnspecifiedType() instanceof PointerType and + not this.parameterEscapesOnlyViaReturn(i) } override predicate parameterEscapesOnlyViaReturn(int i) { i = 0 and - getUnspecifiedType() instanceof PointerType + this.getUnspecifiedType() instanceof PointerType } override predicate parameterIsAlwaysReturned(int i) { none() } @@ -202,7 +202,7 @@ private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunctio override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { - getParameter(i).getUnspecifiedType() instanceof PointerType and + this.getParameter(i).getUnspecifiedType() instanceof PointerType and buffer = true } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/SmartPointer.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/SmartPointer.qll index e249a164061..389ce6c5ab0 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/SmartPointer.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/SmartPointer.qll @@ -72,9 +72,9 @@ private class MakeUniqueOrShared extends TaintFunction { // since these just take a size argument, which we don't want to propagate taint through. not this.isArray() and ( - input.isParameter([0 .. getNumberOfParameters() - 1]) + input.isParameter([0 .. this.getNumberOfParameters() - 1]) or - input.isParameterDeref([0 .. getNumberOfParameters() - 1]) + input.isParameterDeref([0 .. this.getNumberOfParameters() - 1]) ) and output.isReturnValue() } @@ -116,14 +116,14 @@ private class SmartPtrSetterFunction extends MemberFunction, AliasFunction, Side or // When taking ownership of a smart pointer via an rvalue reference, always overwrite the input // smart pointer. - getPointerInput().isParameterDeref(i) and + this.getPointerInput().isParameterDeref(i) and this.getParameter(i).getUnspecifiedType() instanceof RValueReferenceType and buffer = false and mustWrite = true } override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { - getPointerInput().isParameterDeref(i) and + this.getPointerInput().isParameterDeref(i) and buffer = false or not this instanceof Constructor and @@ -136,7 +136,7 @@ private class SmartPtrSetterFunction extends MemberFunction, AliasFunction, Side override predicate parameterEscapesOnlyViaReturn(int index) { none() } override predicate hasAddressFlow(FunctionInput input, FunctionOutput output) { - input = getPointerInput() and + input = this.getPointerInput() and output.isQualifierObject() or // Assignment operator always returns a reference to `*this`. diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Sscanf.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Sscanf.qll index b6120abf05a..42166ae9baa 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Sscanf.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Sscanf.qll @@ -23,15 +23,15 @@ private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, S bufParam = this.(ScanfFunction).getInputParameterIndex() } - override predicate hasArrayInput(int bufParam) { hasArrayWithNullTerminator(bufParam) } + override predicate hasArrayInput(int bufParam) { this.hasArrayWithNullTerminator(bufParam) } private int getLengthParameterIndex() { result = this.(Snscanf).getInputLengthParameterIndex() } private int getLocaleParameterIndex() { this.getName().matches("%\\_l") and ( - if exists(getLengthParameterIndex()) - then result = getLengthParameterIndex() + 2 + if exists(this.getLengthParameterIndex()) + then result = this.getLengthParameterIndex() + 2 else result = 2 ) } @@ -40,11 +40,11 @@ private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, S override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref(this.(ScanfFunction).getInputParameterIndex()) and - output.isParameterDeref(any(int i | i >= getArgsStartPosition())) + output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) } override predicate parameterNeverEscapes(int index) { - index = [0 .. max(getACallToThisFunction().getNumberOfArguments())] + index = [0 .. max(this.getACallToThisFunction().getNumberOfArguments())] } override predicate parameterEscapesOnlyViaReturn(int index) { none() } @@ -56,7 +56,7 @@ private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, S override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { - i >= getArgsStartPosition() and + i >= this.getArgsStartPosition() and buffer = true and mustWrite = true } @@ -66,7 +66,7 @@ private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, S i = [ this.(ScanfFunction).getInputParameterIndex(), - this.(ScanfFunction).getFormatParameterIndex(), getLocaleParameterIndex() + this.(ScanfFunction).getFormatParameterIndex(), this.getLocaleParameterIndex() ] } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdContainer.qll index 367db1613fc..c93a5ad147b 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdContainer.qll @@ -61,20 +61,20 @@ private class StdSequenceContainerConstructor extends Constructor, TaintFunction * value type of the container. */ int getAValueTypeParameterIndex() { - getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = - getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>` + this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = + this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>` } /** * Gets the index of a parameter to this function that is an iterator. */ - int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator } + int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // taint flow from any parameter of the value type to the returned object ( - input.isParameterDeref(getAValueTypeParameterIndex()) or - input.isParameter(getAnIteratorParameterIndex()) + input.isParameterDeref(this.getAValueTypeParameterIndex()) or + input.isParameter(this.getAnIteratorParameterIndex()) ) and ( output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object @@ -158,21 +158,21 @@ private class StdSequenceContainerInsert extends TaintFunction { * value type of the container. */ int getAValueTypeParameterIndex() { - getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = - getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>` + this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = + this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>` } /** * Gets the index of a parameter to this function that is an iterator. */ - int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator } + int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to container itself (qualifier) and return value ( input.isQualifierObject() or - input.isParameterDeref(getAValueTypeParameterIndex()) or - input.isParameter(getAnIteratorParameterIndex()) + input.isParameterDeref(this.getAValueTypeParameterIndex()) or + input.isParameter(this.getAnIteratorParameterIndex()) ) and ( output.isQualifierObject() or @@ -197,20 +197,20 @@ private class StdSequenceContainerAssign extends TaintFunction { * value type of the container. */ int getAValueTypeParameterIndex() { - getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = - getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>` + this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = + this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>` } /** * Gets the index of a parameter to this function that is an iterator. */ - int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator } + int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to container itself (qualifier) ( - input.isParameterDeref(getAValueTypeParameterIndex()) or - input.isParameter(getAnIteratorParameterIndex()) + input.isParameterDeref(this.getAValueTypeParameterIndex()) or + input.isParameter(this.getAnIteratorParameterIndex()) ) and output.isQualifierObject() } @@ -246,7 +246,7 @@ class StdVectorEmplace extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter except the position iterator to qualifier and return value // (here we assume taint flow from any constructor parameter to the constructed object) - input.isParameterDeref([1 .. getNumberOfParameters() - 1]) and + input.isParameterDeref([1 .. this.getNumberOfParameters() - 1]) and ( output.isQualifierObject() or output.isReturnValue() @@ -263,7 +263,7 @@ class StdVectorEmplaceBack extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter to qualifier // (here we assume taint flow from any constructor parameter to the constructed object) - input.isParameterDeref([0 .. getNumberOfParameters() - 1]) and + input.isParameterDeref([0 .. this.getNumberOfParameters() - 1]) and output.isQualifierObject() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMap.qll index aecd98981e8..9dc220e79af 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMap.qll @@ -22,12 +22,12 @@ private class StdMapConstructor extends Constructor, TaintFunction { * Gets the index of a parameter to this function that is an iterator. */ int getAnIteratorParameterIndex() { - getParameter(result).getUnspecifiedType() instanceof Iterator + this.getParameter(result).getUnspecifiedType() instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // taint flow from any parameter of an iterator type to the qualifier - input.isParameterDeref(getAnIteratorParameterIndex()) and + input.isParameterDeref(this.getAnIteratorParameterIndex()) and ( output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object or @@ -47,7 +47,7 @@ private class StdMapInsert extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from last parameter to qualifier and return value // (where the return value is a pair, this should really flow just to the first part of it) - input.isParameterDeref(getNumberOfParameters() - 1) and + input.isParameterDeref(this.getNumberOfParameters() - 1) and ( output.isQualifierObject() or output.isReturnValue() @@ -66,7 +66,7 @@ private class StdMapEmplace extends TaintFunction { // construct a pair, or a pair to be copied / moved) to the qualifier and // return value. // (where the return value is a pair, this should really flow just to the first part of it) - input.isParameterDeref(getNumberOfParameters() - 1) and + input.isParameterDeref(this.getNumberOfParameters() - 1) and ( output.isQualifierObject() or output.isReturnValue() @@ -87,9 +87,9 @@ private class StdMapTryEmplace extends TaintFunction { // flow from any parameter apart from the key to qualifier and return value // (here we assume taint flow from any constructor parameter to the constructed object) // (where the return value is a pair, this should really flow just to the first part of it) - exists(int arg | arg = [1 .. getNumberOfParameters() - 1] | + exists(int arg | arg = [1 .. this.getNumberOfParameters() - 1] | ( - not getUnspecifiedType() instanceof Iterator or + not this.getUnspecifiedType() instanceof Iterator or arg != 1 ) and input.isParameterDeref(arg) @@ -154,7 +154,7 @@ private class StdMapErase extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to iterator return value - getType().getUnderlyingType() instanceof Iterator and + this.getType().getUnderlyingType() instanceof Iterator and input.isQualifierObject() and output.isReturnValue() } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdPair.qll index 755f6a48520..c6fabcac314 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdPair.qll @@ -51,13 +51,13 @@ private class StdPairConstructor extends Constructor, TaintFunction { * either value type of the pair. */ int getAValueTypeParameterIndex() { - getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = - getDeclaringType().getTemplateArgument(_).(Type).getUnspecifiedType() // i.e. the `T1` or `T2` of this `std::pair<T1, T2>` + this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = + this.getDeclaringType().getTemplateArgument(_).(Type).getUnspecifiedType() // i.e. the `T1` or `T2` of this `std::pair<T1, T2>` } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // taint flow from second parameter of a value type to the qualifier - getAValueTypeParameterIndex() = 1 and + this.getAValueTypeParameterIndex() = 1 and input.isParameterDeref(1) and ( output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdSet.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdSet.qll index d2e9892abcb..3e26d80c136 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdSet.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdSet.qll @@ -22,12 +22,12 @@ private class StdSetConstructor extends Constructor, TaintFunction { * Gets the index of a parameter to this function that is an iterator. */ int getAnIteratorParameterIndex() { - getParameter(result).getUnspecifiedType() instanceof Iterator + this.getParameter(result).getUnspecifiedType() instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // taint flow from any parameter of an iterator type to the qualifier - input.isParameterDeref(getAnIteratorParameterIndex()) and + input.isParameterDeref(this.getAnIteratorParameterIndex()) and ( output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object or @@ -45,7 +45,7 @@ private class StdSetInsert extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from last parameter to qualifier and return value // (where the return value is a pair, this should really flow just to the first part of it) - input.isParameterDeref(getNumberOfParameters() - 1) and + input.isParameterDeref(this.getNumberOfParameters() - 1) and ( output.isQualifierObject() or output.isReturnValue() @@ -63,7 +63,7 @@ private class StdSetEmplace extends TaintFunction { // flow from any parameter to qualifier and return value // (here we assume taint flow from any constructor parameter to the constructed object) // (where the return value is a pair, this should really flow just to the first part of it) - input.isParameterDeref([0 .. getNumberOfParameters() - 1]) and + input.isParameterDeref([0 .. this.getNumberOfParameters() - 1]) and ( output.isQualifierObject() or output.isReturnValue() @@ -107,7 +107,7 @@ private class StdSetErase extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to iterator return value - getType().getUnderlyingType() instanceof Iterator and + this.getType().getUnderlyingType() instanceof Iterator and input.isQualifierObject() and output.isReturnValue() } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdString.qll index 73a0f6edf26..ae190688b70 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdString.qll @@ -31,31 +31,31 @@ private class StdStringConstructor extends Constructor, TaintFunction { * character). */ int getAStringParameterIndex() { - exists(Type paramType | paramType = getParameter(result).getUnspecifiedType() | + exists(Type paramType | paramType = this.getParameter(result).getUnspecifiedType() | // e.g. `std::basic_string::CharT *` paramType instanceof PointerType or // e.g. `std::basic_string &`, avoiding `const Allocator&` paramType instanceof ReferenceType and not paramType.(ReferenceType).getBaseType() = - getDeclaringType().getTemplateArgument(2).(Type).getUnspecifiedType() + this.getDeclaringType().getTemplateArgument(2).(Type).getUnspecifiedType() or // i.e. `std::basic_string::CharT` - getParameter(result).getUnspecifiedType() = - getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() + this.getParameter(result).getUnspecifiedType() = + this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() ) } /** * Gets the index of a parameter to this function that is an iterator. */ - int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator } + int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // taint flow from any parameter of the value type to the returned object ( - input.isParameterDeref(getAStringParameterIndex()) or - input.isParameter(getAnIteratorParameterIndex()) + input.isParameterDeref(this.getAStringParameterIndex()) or + input.isParameter(this.getAnIteratorParameterIndex()) ) and ( output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object @@ -156,23 +156,23 @@ private class StdStringAppend extends TaintFunction { * character). */ int getAStringParameterIndex() { - getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *` - getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &` - getParameter(result).getUnspecifiedType() = - getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT` + this.getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *` + this.getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &` + this.getParameter(result).getUnspecifiedType() = + this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT` } /** * Gets the index of a parameter to this function that is an iterator. */ - int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator } + int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string and parameter to string (qualifier) and return value ( input.isQualifierObject() or - input.isParameterDeref(getAStringParameterIndex()) or - input.isParameter(getAnIteratorParameterIndex()) + input.isParameterDeref(this.getAStringParameterIndex()) or + input.isParameter(this.getAnIteratorParameterIndex()) ) and ( output.isQualifierObject() or @@ -197,22 +197,22 @@ private class StdStringAssign extends TaintFunction { * character). */ int getAStringParameterIndex() { - getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *` - getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &` - getParameter(result).getUnspecifiedType() = - getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT` + this.getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *` + this.getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &` + this.getParameter(result).getUnspecifiedType() = + this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT` } /** * Gets the index of a parameter to this function that is an iterator. */ - int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator } + int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to string itself (qualifier) and return value ( - input.isParameterDeref(getAStringParameterIndex()) or - input.isParameter(getAnIteratorParameterIndex()) + input.isParameterDeref(this.getAStringParameterIndex()) or + input.isParameter(this.getAnIteratorParameterIndex()) ) and ( output.isQualifierObject() or @@ -574,12 +574,12 @@ private class StdStringStreamConstructor extends Constructor, TaintFunction { * Gets the index of a parameter to this function that is a string. */ int getAStringParameterIndex() { - getParameter(result).getType() instanceof ReferenceType // `const std::basic_string &` + this.getParameter(result).getType() instanceof ReferenceType // `const std::basic_string &` } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // taint flow from any parameter of string type to the returned object - input.isParameterDeref(getAStringParameterIndex()) and + input.isParameterDeref(this.getAStringParameterIndex()) and ( output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object or diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll index ee9af547582..1a65e7b6ca4 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll @@ -32,7 +32,7 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid /** * Gets the index of the parameter that is the size of the copy (in characters). */ - int getParamSize() { exists(getParameter(2)) and result = 2 } + int getParamSize() { exists(this.getParameter(2)) and result = 2 } /** * Gets the index of the parameter that is the source of the copy. @@ -50,11 +50,11 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - getName() = ["strncat", "wcsncat", "_mbsncat", "_mbsncat_l"] and + this.getName() = ["strncat", "wcsncat", "_mbsncat", "_mbsncat_l"] and input.isParameter(2) and output.isParameterDeref(0) or - getName() = ["_mbsncat_l", "_mbsnbcat_l"] and + this.getName() = ["_mbsncat_l", "_mbsnbcat_l"] and input.isParameter(3) and output.isParameterDeref(0) or diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll index 432fbf999ef..10b160dee47 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll @@ -45,22 +45,22 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid ) and // exclude the 2-parameter template versions // that find the size of a fixed size destination buffer. - getNumberOfParameters() = 3 + this.getNumberOfParameters() = 3 } /** * Holds if this is one of the `strcpy_s` variants. */ - private predicate isSVariant() { getName().matches("%\\_s") } + private predicate isSVariant() { this.getName().matches("%\\_s") } /** * Gets the index of the parameter that is the maximum size of the copy (in characters). */ int getParamSize() { - if isSVariant() + if this.isSVariant() then result = 1 else ( - getName().matches(["%ncpy%", "%nbcpy%", "%xfrm%"]) and + this.getName().matches(["%ncpy%", "%nbcpy%", "%xfrm%"]) and result = 2 ) } @@ -68,49 +68,49 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid /** * Gets the index of the parameter that is the source of the copy. */ - int getParamSrc() { if isSVariant() then result = 2 else result = 1 } + int getParamSrc() { if this.isSVariant() then result = 2 else result = 1 } /** * Gets the index of the parameter that is the destination of the copy. */ int getParamDest() { result = 0 } - override predicate hasArrayInput(int bufParam) { bufParam = getParamSrc() } + override predicate hasArrayInput(int bufParam) { bufParam = this.getParamSrc() } - override predicate hasArrayOutput(int bufParam) { bufParam = getParamDest() } + override predicate hasArrayOutput(int bufParam) { bufParam = this.getParamDest() } - override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = getParamSrc() } + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = this.getParamSrc() } override predicate hasArrayWithVariableSize(int bufParam, int countParam) { - bufParam = getParamDest() and - countParam = getParamSize() + bufParam = this.getParamDest() and + countParam = this.getParamSize() } override predicate hasArrayWithUnknownSize(int bufParam) { - not exists(getParamSize()) and - bufParam = getParamDest() + not exists(this.getParamSize()) and + bufParam = this.getParamDest() } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { - not exists(getParamSize()) and - input.isParameterDeref(getParamSrc()) and - output.isParameterDeref(getParamDest()) + not exists(this.getParamSize()) and + input.isParameterDeref(this.getParamSrc()) and + output.isParameterDeref(this.getParamDest()) or - not exists(getParamSize()) and - input.isParameterDeref(getParamSrc()) and + not exists(this.getParamSize()) and + input.isParameterDeref(this.getParamSrc()) and output.isReturnValueDeref() or - input.isParameter(getParamDest()) and + input.isParameter(this.getParamDest()) and output.isReturnValue() } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // these may do only a partial copy of the input buffer to the output // buffer - exists(getParamSize()) and - input.isParameter(getParamSrc()) and + exists(this.getParamSize()) and + input.isParameter(this.getParamSrc()) and ( - output.isParameterDeref(getParamDest()) or + output.isParameterDeref(this.getParamDest()) or output.isReturnValueDeref() ) } @@ -120,18 +120,18 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { - i = getParamDest() and + i = this.getParamDest() and buffer = true and mustWrite = false } override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { - i = getParamSrc() and + i = this.getParamSrc() and buffer = true } override ParameterIndex getParameterSizeIndex(ParameterIndex i) { - i = getParamDest() and - result = getParamSize() + i = this.getParamDest() and + result = this.getParamSize() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcrement.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcrement.qll index 4c335c8581e..8f6c17aae54 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcrement.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcrement.qll @@ -29,10 +29,10 @@ private class Strcrement extends ArrayFunction, TaintFunction, SideEffectFunctio this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType } - override predicate hasArrayInput(int bufParam) { hasArrayWithNullTerminator(bufParam) } + override predicate hasArrayInput(int bufParam) { this.hasArrayWithNullTerminator(bufParam) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - exists(int index | hasArrayInput(index) | + exists(int index | this.hasArrayInput(index) | input.isParameter(index) and output.isReturnValue() or input.isParameterDeref(index) and output.isReturnValueDeref() @@ -44,6 +44,6 @@ private class Strcrement extends ArrayFunction, TaintFunction, SideEffectFunctio override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { - hasArrayInput(i) and buffer = true + this.hasArrayInput(i) and buffer = true } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Swap.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Swap.qll index b79f7afe5d9..446e659fac5 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Swap.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Swap.qll @@ -31,7 +31,7 @@ private class MemberSwap extends TaintFunction, MemberFunction, AliasFunction { this.hasName("swap") and this.getNumberOfParameters() = 1 and this.getParameter(0).getType().(ReferenceType).getBaseType().getUnspecifiedType() = - getDeclaringType() + this.getDeclaringType() } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll index 4ab55ee5b3f..5e899be68d4 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll @@ -44,7 +44,7 @@ class FunctionInput extends TFunctionInput { * Holds if this is the input value of the parameter with index `index`. * DEPRECATED: Use `isParameter(index)` instead. */ - deprecated final predicate isInParameter(ParameterIndex index) { isParameter(index) } + deprecated final predicate isInParameter(ParameterIndex index) { this.isParameter(index) } /** * Holds if this is the input value pointed to by a pointer parameter to a function, or the input @@ -70,7 +70,9 @@ class FunctionInput extends TFunctionInput { * `index`. * DEPRECATED: Use `isParameterDeref(index)` instead. */ - deprecated final predicate isInParameterPointer(ParameterIndex index) { isParameterDeref(index) } + deprecated final predicate isInParameterPointer(ParameterIndex index) { + this.isParameterDeref(index) + } /** * Holds if this is the input value pointed to by the `this` pointer of an instance member @@ -92,7 +94,7 @@ class FunctionInput extends TFunctionInput { * function. * DEPRECATED: Use `isQualifierObject()` instead. */ - deprecated final predicate isInQualifier() { isQualifierObject() } + deprecated final predicate isInQualifier() { this.isQualifierObject() } /** * Holds if this is the input value of the `this` pointer of an instance member function. @@ -314,7 +316,9 @@ class FunctionOutput extends TFunctionOutput { * index `index`. * DEPRECATED: Use `isParameterDeref(index)` instead. */ - deprecated final predicate isOutParameterPointer(ParameterIndex index) { isParameterDeref(index) } + deprecated final predicate isOutParameterPointer(ParameterIndex index) { + this.isParameterDeref(index) + } /** * Holds if this is the output value pointed to by the `this` pointer of an instance member @@ -336,7 +340,7 @@ class FunctionOutput extends TFunctionOutput { * function. * DEPRECATED: Use `isQualifierObject()` instead. */ - deprecated final predicate isOutQualifier() { isQualifierObject() } + deprecated final predicate isOutQualifier() { this.isQualifierObject() } /** * Holds if this is the value returned by a function. @@ -361,7 +365,7 @@ class FunctionOutput extends TFunctionOutput { * Holds if this is the value returned by a function. * DEPRECATED: Use `isReturnValue()` instead. */ - deprecated final predicate isOutReturnValue() { isReturnValue() } + deprecated final predicate isOutReturnValue() { this.isReturnValue() } /** * Holds if this is the output value pointed to by the return value of a function, if the function @@ -389,7 +393,7 @@ class FunctionOutput extends TFunctionOutput { * function returns a reference. * DEPRECATED: Use `isReturnValueDeref()` instead. */ - deprecated final predicate isOutReturnPointer() { isReturnValueDeref() } + deprecated final predicate isOutReturnPointer() { this.isReturnValueDeref() } /** * Holds if `i >= 0` and `isParameterDeref(i)` holds for this is the value, or diff --git a/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll b/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll index 7446569451d..e9bde69cfda 100644 --- a/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll +++ b/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll @@ -72,7 +72,7 @@ abstract class Architecture extends string { or t instanceof CharType and result = 8 or - t instanceof WideCharType and result = wideCharSize() + t instanceof WideCharType and result = this.wideCharSize() or t instanceof Char8Type and result = 8 or @@ -84,22 +84,22 @@ abstract class Architecture extends string { or t instanceof IntType and result = 32 or - t instanceof LongType and result = longSize() + t instanceof LongType and result = this.longSize() or - t instanceof LongLongType and result = longLongSize() + t instanceof LongLongType and result = this.longLongSize() or - result = enumBitSize(t.(Enum)) + result = this.enumBitSize(t.(Enum)) or - result = integralBitSize(t.(SpecifiedType).getBaseType()) + result = this.integralBitSize(t.(SpecifiedType).getBaseType()) or - result = integralBitSize(t.(TypedefType).getBaseType()) + result = this.integralBitSize(t.(TypedefType).getBaseType()) } /** * Gets the bit size of enum type `e`. */ int enumBitSize(Enum e) { - result = integralBitSize(e.getExplicitUnderlyingType()) + result = this.integralBitSize(e.getExplicitUnderlyingType()) or not exists(e.getExplicitUnderlyingType()) and result = 32 } @@ -108,7 +108,7 @@ abstract class Architecture extends string { * Gets the alignment of enum type `e`. */ int enumAlignment(Enum e) { - result = alignment(e.getExplicitUnderlyingType()) + result = this.alignment(e.getExplicitUnderlyingType()) or not exists(e.getExplicitUnderlyingType()) and result = 32 } @@ -120,26 +120,26 @@ abstract class Architecture extends string { */ cached int bitSize(Type t) { - result = integralBitSize(t) + result = this.integralBitSize(t) or t instanceof FloatType and result = 32 or t instanceof DoubleType and result = 64 or - t instanceof LongDoubleType and result = longDoubleSize() + t instanceof LongDoubleType and result = this.longDoubleSize() or - t instanceof PointerType and result = pointerSize() + t instanceof PointerType and result = this.pointerSize() or - t instanceof ReferenceType and result = pointerSize() + t instanceof ReferenceType and result = this.pointerSize() or - t instanceof FunctionPointerType and result = pointerSize() + t instanceof FunctionPointerType and result = this.pointerSize() or - result = bitSize(t.(SpecifiedType).getBaseType()) + result = this.bitSize(t.(SpecifiedType).getBaseType()) or - result = bitSize(t.(TypedefType).getBaseType()) + result = this.bitSize(t.(TypedefType).getBaseType()) or exists(ArrayType array | array = t | - result = array.getArraySize() * paddedSize(array.getBaseType()) + result = array.getArraySize() * this.paddedSize(array.getBaseType()) ) or result = t.(PaddedType).typeBitSize(this) @@ -155,7 +155,7 @@ abstract class Architecture extends string { or t instanceof CharType and result = 8 or - t instanceof WideCharType and result = wideCharSize() + t instanceof WideCharType and result = this.wideCharSize() or t instanceof Char8Type and result = 8 or @@ -169,27 +169,27 @@ abstract class Architecture extends string { or t instanceof FloatType and result = 32 or - t instanceof DoubleType and result = doubleAlign() + t instanceof DoubleType and result = this.doubleAlign() or - t instanceof LongType and result = longSize() + t instanceof LongType and result = this.longSize() or - t instanceof LongDoubleType and result = longDoubleAlign() + t instanceof LongDoubleType and result = this.longDoubleAlign() or - t instanceof LongLongType and result = longLongAlign() + t instanceof LongLongType and result = this.longLongAlign() or - t instanceof PointerType and result = pointerSize() + t instanceof PointerType and result = this.pointerSize() or - t instanceof FunctionPointerType and result = pointerSize() + t instanceof FunctionPointerType and result = this.pointerSize() or - t instanceof ReferenceType and result = pointerSize() + t instanceof ReferenceType and result = this.pointerSize() or - result = enumAlignment(t.(Enum)) + result = this.enumAlignment(t.(Enum)) or - result = alignment(t.(SpecifiedType).getBaseType()) + result = this.alignment(t.(SpecifiedType).getBaseType()) or - result = alignment(t.(TypedefType).getBaseType()) + result = this.alignment(t.(TypedefType).getBaseType()) or - result = alignment(t.(ArrayType).getBaseType()) + result = this.alignment(t.(ArrayType).getBaseType()) or result = t.(PaddedType).typeAlignment(this) } @@ -203,7 +203,7 @@ abstract class Architecture extends string { exists(Type realType | realType = stripSpecifiers(t) | if realType instanceof PaddedType then result = realType.(PaddedType).paddedSize(this) - else result = bitSize(realType) + else result = this.bitSize(realType) ) } @@ -429,7 +429,7 @@ class PaddedType extends Class { * Gets the number of bits wasted by padding at the end of this * struct. */ - int trailingPadding(Architecture arch) { result = paddedSize(arch) - arch.bitSize(this) } + int trailingPadding(Architecture arch) { result = this.paddedSize(arch) - arch.bitSize(this) } /** * Gets the number of bits wasted in this struct definition; that is. @@ -440,7 +440,7 @@ class PaddedType extends Class { * laid out one after another, and hence there is no padding between * them. */ - int wastedSpace(Architecture arch) { result = arch.paddedSize(this) - dataSize(arch) } + int wastedSpace(Architecture arch) { result = arch.paddedSize(this) - this.dataSize(arch) } /** * Gets the total size of all fields declared in this class, not including any @@ -448,8 +448,8 @@ class PaddedType extends Class { */ private int fieldDataSize(Architecture arch) { if this instanceof Union - then result = max(Field f | f = this.getAMember() | fieldSize(f, arch)) - else result = sum(Field f | f = this.getAMember() | fieldSize(f, arch)) + then result = max(Field f | f = this.getAMember() | this.fieldSize(f, arch)) + else result = sum(Field f | f = this.getAMember() | this.fieldSize(f, arch)) } /** @@ -472,7 +472,7 @@ class PaddedType extends Class { * reorganizing member structs' field layouts. */ int optimalSize(Architecture arch) { - result = alignUp(dataSize(arch), arch.alignment(this)).maximum(8) + result = alignUp(this.dataSize(arch), arch.alignment(this)).maximum(8) } /** @@ -490,11 +490,11 @@ class PaddedType extends Class { // but that uses a recursive aggregate, which isn't supported in // QL. We therefore use this slightly more complex implementation // instead. - result = biggestFieldSizeUpTo(lastFieldIndex(), arch) + result = this.biggestFieldSizeUpTo(this.lastFieldIndex(), arch) else // If we're not a union type, the size is the padded // sum of field sizes, padded. - result = fieldEnd(lastFieldIndex(), arch) + result = this.fieldEnd(this.lastFieldIndex(), arch) } /** @@ -522,8 +522,8 @@ class PaddedType extends Class { if index = 0 then result = 0 else - exists(Field f, int fSize | index = fieldIndex(f) and fSize = fieldSize(f, arch) | - result = fSize.maximum(biggestFieldSizeUpTo(index - 1, arch)) + exists(Field f, int fSize | index = this.fieldIndex(f) and fSize = this.fieldSize(f, arch) | + result = fSize.maximum(this.biggestFieldSizeUpTo(index - 1, arch)) ) } @@ -536,8 +536,10 @@ class PaddedType extends Class { if index = 0 then result = 1 // Minimum possible alignment else - exists(Field f, int fAlign | index = fieldIndex(f) and fAlign = arch.alignment(f.getType()) | - result = fAlign.maximum(biggestAlignmentUpTo(index - 1, arch)) + exists(Field f, int fAlign | + index = this.fieldIndex(f) and fAlign = arch.alignment(f.getType()) + | + result = fAlign.maximum(this.biggestAlignmentUpTo(index - 1, arch)) ) } @@ -545,17 +547,18 @@ class PaddedType extends Class { * Gets the 1-based index for each field. */ int fieldIndex(Field f) { - memberIndex(f) = rank[result](Field field, int index | memberIndex(field) = index | index) + this.memberIndex(f) = + rank[result](Field field, int index | this.memberIndex(field) = index | index) } - private int memberIndex(Field f) { result = min(int i | getCanonicalMember(i) = f) } + private int memberIndex(Field f) { result = min(int i | this.getCanonicalMember(i) = f) } /** * Gets the 1-based index for the last field. */ int lastFieldIndex() { - if exists(lastField()) - then result = fieldIndex(lastField()) + if exists(this.lastField()) + then result = this.fieldIndex(this.lastField()) else // Field indices are 1-based, so return 0 to represent the lack of fields. result = 0 @@ -566,25 +569,27 @@ class PaddedType extends Class { * `arch`. */ int fieldSize(Field f, Architecture arch) { - exists(fieldIndex(f)) and + exists(this.fieldIndex(f)) and if f instanceof BitField then result = f.(BitField).getNumBits() else result = arch.paddedSize(f.getType()) } /** Gets the last field of this type. */ - Field lastField() { fieldIndex(result) = max(Field other | | fieldIndex(other)) } + Field lastField() { this.fieldIndex(result) = max(Field other | | this.fieldIndex(other)) } /** * Gets the offset, in bits, of the end of the class' last base class * subobject, or zero if the class has no base classes. */ int baseClassEnd(Architecture arch) { - if exists(getABaseClass()) then result = arch.baseClassSize(getADerivation()) else result = 0 + if exists(this.getABaseClass()) + then result = arch.baseClassSize(this.getADerivation()) + else result = 0 } /** Gets the bitfield at field index `index`, if that field is a bitfield. */ - private BitField bitFieldAt(int index) { fieldIndex(result) = index } + private BitField bitFieldAt(int index) { this.fieldIndex(result) = index } /** * Gets the 0-based offset, in bits, of the first free bit after @@ -596,13 +601,13 @@ class PaddedType extends Class { then // Base case: No fields seen yet, so return the offset of the end of the // base class subojects. - result = baseClassEnd(arch) + result = this.baseClassEnd(arch) else - exists(Field f | index = fieldIndex(f) | - exists(int fSize | fSize = fieldSize(f, arch) | + exists(Field f | index = this.fieldIndex(f) | + exists(int fSize | fSize = this.fieldSize(f, arch) | // Recursive case: Take previous field's end point, pad and add // this field's size - exists(int firstFree | firstFree = fieldEnd(index - 1, arch) | + exists(int firstFree | firstFree = this.fieldEnd(index - 1, arch) | if f instanceof BitField then // Bitfield packing: @@ -629,9 +634,11 @@ class PaddedType extends Class { // No additional restrictions, so just pack it in with no padding. result = firstFree + fSize ) else ( - if exists(bitFieldAt(index - 1)) + if exists(this.bitFieldAt(index - 1)) then - exists(BitField previousBitField | previousBitField = bitFieldAt(index - 1) | + exists(BitField previousBitField | + previousBitField = this.bitFieldAt(index - 1) + | // Previous field was a bitfield. if nextSizeofBoundary >= (firstFree + fSize) and diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll index bc66d9b2dd0..5aebf07f2f1 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll @@ -88,7 +88,7 @@ class RangeSsaDefinition extends ControlFlowNodeBase { ControlFlowNode getDefinition() { result = this } /** Gets the basic block containing this definition. */ - BasicBlock getBasicBlock() { result.contains(getDefinition()) } + BasicBlock getBasicBlock() { result.contains(this.getDefinition()) } /** Whether this definition is a phi node for variable `v`. */ predicate isPhiNode(StackVariable v) { exists(RangeSSA x | x.phi_node(v, this.(BasicBlock))) } diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 289187d4301..0be94ed4e62 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -127,17 +127,22 @@ private string getValue(Expr e) { private class UnsignedBitwiseAndExpr extends BitwiseAndExpr { UnsignedBitwiseAndExpr() { ( - getLeftOperand().getFullyConverted().getType().getUnderlyingType().(IntegralType).isUnsigned() or - getValue(getLeftOperand().getFullyConverted()).toInt() >= 0 - ) and - ( - getRightOperand() + this.getLeftOperand() .getFullyConverted() .getType() .getUnderlyingType() .(IntegralType) .isUnsigned() or - getValue(getRightOperand().getFullyConverted()).toInt() >= 0 + getValue(this.getLeftOperand().getFullyConverted()).toInt() >= 0 + ) and + ( + this.getRightOperand() + .getFullyConverted() + .getType() + .getUnderlyingType() + .(IntegralType) + .isUnsigned() or + getValue(this.getRightOperand().getFullyConverted()).toInt() >= 0 ) } } diff --git a/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll b/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll index e5d892eb4cd..61845654721 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll @@ -77,21 +77,21 @@ abstract class BufferWrite extends Expr { * much smaller (8 bytes) than their true maximum length. This can be * helpful in determining the cause of a buffer overflow issue. */ - int getMaxDataLimited() { result = getMaxData() } + int getMaxDataLimited() { result = this.getMaxData() } /** * Gets the size of a single character of the type this * operation works with, in bytes. */ int getCharSize() { - result = getBufferType().(PointerType).getBaseType().getSize() or - result = getBufferType().(ArrayType).getBaseType().getSize() + result = this.getBufferType().(PointerType).getBaseType().getSize() or + result = this.getBufferType().(ArrayType).getBaseType().getSize() } /** * Gets a description of this buffer write. */ - string getBWDesc() { result = toString() } + string getBWDesc() { result = this.toString() } } /** @@ -109,7 +109,7 @@ abstract class BufferWriteCall extends BufferWrite, FunctionCall { } class StrCopyBW extends BufferWriteCall { StrcpyFunction f; - StrCopyBW() { getTarget() = f.(TopLevelFunction) } + StrCopyBW() { this.getTarget() = f.(TopLevelFunction) } /** * Gets the index of the parameter that is the maximum size of the copy (in characters). @@ -122,21 +122,22 @@ class StrCopyBW extends BufferWriteCall { int getParamSrc() { result = f.getParamSrc() } override Type getBufferType() { - result = this.getTarget().getParameter(getParamSrc()).getUnspecifiedType() + result = this.getTarget().getParameter(this.getParamSrc()).getUnspecifiedType() } - override Expr getASource() { result = getArgument(getParamSrc()) } + override Expr getASource() { result = this.getArgument(this.getParamSrc()) } - override Expr getDest() { result = getArgument(f.getParamDest()) } + override Expr getDest() { result = this.getArgument(f.getParamDest()) } - override predicate hasExplicitLimit() { exists(getParamSize()) } + override predicate hasExplicitLimit() { exists(this.getParamSize()) } override int getExplicitLimit() { - result = getArgument(getParamSize()).getValue().toInt() * getCharSize() + result = this.getArgument(this.getParamSize()).getValue().toInt() * this.getCharSize() } override int getMaxData() { - result = getArgument(getParamSrc()).(AnalysedString).getMaxLength() * getCharSize() + result = + this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize() } } @@ -146,7 +147,7 @@ class StrCopyBW extends BufferWriteCall { class StrCatBW extends BufferWriteCall { StrcatFunction f; - StrCatBW() { getTarget() = f.(TopLevelFunction) } + StrCatBW() { this.getTarget() = f.(TopLevelFunction) } /** * Gets the index of the parameter that is the maximum size of the copy (in characters). @@ -159,21 +160,22 @@ class StrCatBW extends BufferWriteCall { int getParamSrc() { result = f.getParamSrc() } override Type getBufferType() { - result = this.getTarget().getParameter(getParamSrc()).getUnspecifiedType() + result = this.getTarget().getParameter(this.getParamSrc()).getUnspecifiedType() } - override Expr getASource() { result = getArgument(getParamSrc()) } + override Expr getASource() { result = this.getArgument(this.getParamSrc()) } - override Expr getDest() { result = getArgument(f.getParamDest()) } + override Expr getDest() { result = this.getArgument(f.getParamDest()) } - override predicate hasExplicitLimit() { exists(getParamSize()) } + override predicate hasExplicitLimit() { exists(this.getParamSize()) } override int getExplicitLimit() { - result = getArgument(getParamSize()).getValue().toInt() * getCharSize() + result = this.getArgument(this.getParamSize()).getValue().toInt() * this.getCharSize() } override int getMaxData() { - result = getArgument(getParamSrc()).(AnalysedString).getMaxLength() * getCharSize() + result = + this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize() } } @@ -184,7 +186,7 @@ class SprintfBW extends BufferWriteCall { FormattingFunction f; SprintfBW() { - exists(string name | f = getTarget().(TopLevelFunction) and name = f.getName() | + exists(string name | f = this.getTarget().(TopLevelFunction) and name = f.getName() | /* * C sprintf variants: */ @@ -229,19 +231,19 @@ class SprintfBW extends BufferWriteCall { result = this.(FormattingFunctionCall).getFormatArgument(_) } - override Expr getDest() { result = getArgument(f.getOutputParameterIndex(false)) } + override Expr getDest() { result = this.getArgument(f.getOutputParameterIndex(false)) } override int getMaxData() { exists(FormatLiteral fl | fl = this.(FormattingFunctionCall).getFormat() and - result = fl.getMaxConvertedLength() * getCharSize() + result = fl.getMaxConvertedLength() * this.getCharSize() ) } override int getMaxDataLimited() { exists(FormatLiteral fl | fl = this.(FormattingFunctionCall).getFormat() and - result = fl.getMaxConvertedLengthLimited() * getCharSize() + result = fl.getMaxConvertedLengthLimited() * this.getCharSize() ) } } @@ -251,7 +253,7 @@ class SprintfBW extends BufferWriteCall { */ class SnprintfBW extends BufferWriteCall { SnprintfBW() { - exists(TopLevelFunction fn, string name | fn = getTarget() and name = fn.getName() | + exists(TopLevelFunction fn, string name | fn = this.getTarget() and name = fn.getName() | /* * C snprintf variants: */ @@ -326,25 +328,25 @@ class SnprintfBW extends BufferWriteCall { result = this.(FormattingFunctionCall).getFormatArgument(_) } - override Expr getDest() { result = getArgument(0) } + override Expr getDest() { result = this.getArgument(0) } - override predicate hasExplicitLimit() { exists(getParamSize()) } + override predicate hasExplicitLimit() { exists(this.getParamSize()) } override int getExplicitLimit() { - result = getArgument(getParamSize()).getValue().toInt() * getCharSize() + result = this.getArgument(this.getParamSize()).getValue().toInt() * this.getCharSize() } override int getMaxData() { exists(FormatLiteral fl | fl = this.(FormattingFunctionCall).getFormat() and - result = fl.getMaxConvertedLength() * getCharSize() + result = fl.getMaxConvertedLength() * this.getCharSize() ) } override int getMaxDataLimited() { exists(FormatLiteral fl | fl = this.(FormattingFunctionCall).getFormat() and - result = fl.getMaxConvertedLengthLimited() * getCharSize() + result = fl.getMaxConvertedLengthLimited() * this.getCharSize() ) } } @@ -354,7 +356,7 @@ class SnprintfBW extends BufferWriteCall { */ class GetsBW extends BufferWriteCall { GetsBW() { - getTarget().(TopLevelFunction).getName() = + this.getTarget().(TopLevelFunction).getName() = [ "gets", // gets(dst) "fgets", // fgets(dst, max_amount, src_stream) @@ -365,24 +367,24 @@ class GetsBW extends BufferWriteCall { /** * Gets the index of the parameter that is the maximum number of characters to be read. */ - int getParamSize() { exists(getArgument(1)) and result = 1 } + int getParamSize() { exists(this.getArgument(1)) and result = 1 } override Type getBufferType() { result = this.getTarget().getParameter(0).getUnspecifiedType() } override Expr getASource() { - if exists(getArgument(2)) - then result = getArgument(2) + if exists(this.getArgument(2)) + then result = this.getArgument(2) else // the source is input inside the 'gets' call itself result = this } - override Expr getDest() { result = getArgument(0) } + override Expr getDest() { result = this.getArgument(0) } - override predicate hasExplicitLimit() { exists(getParamSize()) } + override predicate hasExplicitLimit() { exists(this.getParamSize()) } override int getExplicitLimit() { - result = getArgument(getParamSize()).getValue().toInt() * getCharSize() + result = this.getArgument(this.getParamSize()).getValue().toInt() * this.getCharSize() } } @@ -438,7 +440,7 @@ class ScanfBW extends BufferWrite { exists(ScanfFunctionCall fc, ScanfFormatLiteral fl, int arg | this = fc.getArgument(arg) and fl = fc.getFormat() and - result = (fl.getMaxConvertedLength(arg - getParamArgs()) + 1) * getCharSize() // +1 is for the terminating null + result = (fl.getMaxConvertedLength(arg - this.getParamArgs()) + 1) * this.getCharSize() // +1 is for the terminating null ) } @@ -463,14 +465,14 @@ private int path_max() { class RealpathBW extends BufferWriteCall { RealpathBW() { exists(path_max()) and // Ignore realpath() calls if PATH_MAX cannot be determined - getTarget().hasGlobalName("realpath") // realpath(path, resolved_path); + this.getTarget().hasGlobalName("realpath") // realpath(path, resolved_path); } override Type getBufferType() { result = this.getTarget().getParameter(0).getUnspecifiedType() } - override Expr getDest() { result = getArgument(1) } + override Expr getDest() { result = this.getArgument(1) } - override Expr getASource() { result = getArgument(0) } + override Expr getASource() { result = this.getArgument(0) } override int getMaxData() { result = path_max() and diff --git a/cpp/ql/lib/semmle/code/cpp/security/FileWrite.qll b/cpp/ql/lib/semmle/code/cpp/security/FileWrite.qll index 7c3d893b471..36f8b58d812 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/FileWrite.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/FileWrite.qll @@ -52,9 +52,9 @@ class BasicOStreamClass extends Type { */ class BasicOStreamCall extends FunctionCall { BasicOStreamCall() { - if getTarget() instanceof MemberFunction - then getQualifier().getType() instanceof BasicOStreamClass - else getArgument(0).getType() instanceof BasicOStreamClass + if this.getTarget() instanceof MemberFunction + then this.getQualifier().getType() instanceof BasicOStreamClass + else this.getArgument(0).getType() instanceof BasicOStreamClass } } @@ -77,10 +77,10 @@ abstract class ChainedOutputCall extends BasicOStreamCall { */ Expr getEndDest() { // recurse into the destination - result = getDest().(ChainedOutputCall).getEndDest() + result = this.getDest().(ChainedOutputCall).getEndDest() or // or return something other than a ChainedOutputCall - result = getDest() and + result = this.getDest() and not result instanceof ChainedOutputCall } } @@ -89,18 +89,18 @@ abstract class ChainedOutputCall extends BasicOStreamCall { * A call to `operator<<` on an output stream. */ class OperatorLShiftCall extends ChainedOutputCall { - OperatorLShiftCall() { getTarget().(Operator).hasName("operator<<") } + OperatorLShiftCall() { this.getTarget().(Operator).hasName("operator<<") } override Expr getSource() { - if getTarget() instanceof MemberFunction - then result = getArgument(0) - else result = getArgument(1) + if this.getTarget() instanceof MemberFunction + then result = this.getArgument(0) + else result = this.getArgument(1) } override Expr getDest() { - if getTarget() instanceof MemberFunction - then result = getQualifier() - else result = getArgument(0) + if this.getTarget() instanceof MemberFunction + then result = this.getQualifier() + else result = this.getArgument(0) } } @@ -108,22 +108,22 @@ class OperatorLShiftCall extends ChainedOutputCall { * A call to 'put'. */ class PutFunctionCall extends ChainedOutputCall { - PutFunctionCall() { getTarget().(MemberFunction).hasName("put") } + PutFunctionCall() { this.getTarget().(MemberFunction).hasName("put") } - override Expr getSource() { result = getArgument(0) } + override Expr getSource() { result = this.getArgument(0) } - override Expr getDest() { result = getQualifier() } + override Expr getDest() { result = this.getQualifier() } } /** * A call to 'write'. */ class WriteFunctionCall extends ChainedOutputCall { - WriteFunctionCall() { getTarget().(MemberFunction).hasName("write") } + WriteFunctionCall() { this.getTarget().(MemberFunction).hasName("write") } - override Expr getSource() { result = getArgument(0) } + override Expr getSource() { result = this.getArgument(0) } - override Expr getDest() { result = getQualifier() } + override Expr getDest() { result = this.getQualifier() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll b/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll index b080651951f..d2c90a38075 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll @@ -24,7 +24,7 @@ private class RemoteReturnSource extends RemoteFlowSource { RemoteReturnSource() { exists(RemoteFlowSourceFunction func, CallInstruction instr, FunctionOutput output | - asInstruction() = instr and + this.asInstruction() = instr and instr.getStaticCallTarget() = func and func.hasRemoteFlowSource(output, sourceType) and ( @@ -43,7 +43,7 @@ private class RemoteParameterSource extends RemoteFlowSource { RemoteParameterSource() { exists(RemoteFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output | - asInstruction() = instr and + this.asInstruction() = instr and instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and func.hasRemoteFlowSource(output, sourceType) and output.isParameterDerefOrQualifierObject(instr.getIndex()) @@ -58,7 +58,7 @@ private class LocalReturnSource extends LocalFlowSource { LocalReturnSource() { exists(LocalFlowSourceFunction func, CallInstruction instr, FunctionOutput output | - asInstruction() = instr and + this.asInstruction() = instr and instr.getStaticCallTarget() = func and func.hasLocalFlowSource(output, sourceType) and ( @@ -77,7 +77,7 @@ private class LocalParameterSource extends LocalFlowSource { LocalParameterSource() { exists(LocalFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output | - asInstruction() = instr and + this.asInstruction() = instr and instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and func.hasLocalFlowSource(output, sourceType) and output.isParameterDerefOrQualifierObject(instr.getIndex()) diff --git a/cpp/ql/lib/semmle/code/cpp/security/FunctionWithWrappers.qll b/cpp/ql/lib/semmle/code/cpp/security/FunctionWithWrappers.qll index 654e9d92451..b7a7a95a427 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/FunctionWithWrappers.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/FunctionWithWrappers.qll @@ -77,7 +77,7 @@ abstract class FunctionWithWrappers extends Function { ) { // base case func = this and - interestingArg(paramIndex) and + this.interestingArg(paramIndex) and callChain = toCause(func, paramIndex) and depth = 0 or @@ -101,7 +101,7 @@ abstract class FunctionWithWrappers extends Function { private predicate wrapperFunctionAnyDepth(Function func, int paramIndex, string cause) { // base case func = this and - interestingArg(paramIndex) and + this.interestingArg(paramIndex) and cause = toCause(func, paramIndex) or // recursive step @@ -147,7 +147,7 @@ abstract class FunctionWithWrappers extends Function { ) or not this.wrapperFunctionLimitedDepth(func, paramIndex, _, _) and - cause = wrapperFunctionAnyDepthUnique(func, paramIndex) + cause = this.wrapperFunctionAnyDepthUnique(func, paramIndex) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/security/Security.qll b/cpp/ql/lib/semmle/code/cpp/security/Security.qll index da808592b3e..7a73144f5fa 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/Security.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/Security.qll @@ -78,7 +78,7 @@ class SecurityOptions extends string { functionCall.getTarget().getName() = fname and ( fname = ["fgets", "gets"] or - userInputReturn(fname) + this.userInputReturn(fname) ) ) or diff --git a/cpp/ql/lib/semmle/code/cpp/security/SensitiveExprs.qll b/cpp/ql/lib/semmle/code/cpp/security/SensitiveExprs.qll index 22e0ee71b66..04efeebcb18 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/SensitiveExprs.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/SensitiveExprs.qll @@ -29,7 +29,7 @@ private predicate suspicious(string s) { */ class SensitiveVariable extends Variable { SensitiveVariable() { - suspicious(getName().toLowerCase()) and + suspicious(this.getName().toLowerCase()) and not this.getUnspecifiedType() instanceof IntegralType } } @@ -39,7 +39,7 @@ class SensitiveVariable extends Variable { */ class SensitiveFunction extends Function { SensitiveFunction() { - suspicious(getName().toLowerCase()) and + suspicious(this.getName().toLowerCase()) and not this.getUnspecifiedType() instanceof IntegralType } } diff --git a/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll index e113d5e5745..c9d6b6613d8 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -113,7 +113,7 @@ module BoostorgAsio { result.getName() = "tls_server" ) or - result = getASslv23ProtocolConstant() + result = this.getASslv23ProtocolConstant() } /** diff --git a/cpp/ql/lib/semmle/code/cpp/stmts/Block.qll b/cpp/ql/lib/semmle/code/cpp/stmts/Block.qll index 3bebc660456..5fe8798cebb 100644 --- a/cpp/ql/lib/semmle/code/cpp/stmts/Block.qll +++ b/cpp/ql/lib/semmle/code/cpp/stmts/Block.qll @@ -76,9 +76,9 @@ class BlockStmt extends Stmt, @stmt_block { * the result is the expression statement `a = b`. */ Stmt getLastStmtIn() { - if getLastStmt() instanceof BlockStmt - then result = getLastStmt().(BlockStmt).getLastStmtIn() - else result = getLastStmt() + if this.getLastStmt() instanceof BlockStmt + then result = this.getLastStmt().(BlockStmt).getLastStmtIn() + else result = this.getLastStmt() } /** diff --git a/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll b/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll index ed1fb4fbb50..af68daf025c 100644 --- a/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll @@ -27,10 +27,10 @@ class Stmt extends StmtParent, @stmt { */ BlockStmt getEnclosingBlock() { if - getParentStmt() instanceof BlockStmt and - not getParentStmt().(BlockStmt).getLocation() instanceof UnknownLocation - then result = getParentStmt() - else result = getParentStmt().getEnclosingBlock() + this.getParentStmt() instanceof BlockStmt and + not this.getParentStmt().(BlockStmt).getLocation() instanceof UnknownLocation + then result = this.getParentStmt() + else result = this.getParentStmt().getEnclosingBlock() } /** Gets a child of this statement. */ @@ -438,7 +438,7 @@ class WhileStmt extends Loop, @stmt_while { * while(1) { ...; if(b) break; ...; } * ``` */ - predicate conditionAlwaysTrue() { conditionAlwaysTrue(getCondition()) } + predicate conditionAlwaysTrue() { conditionAlwaysTrue(this.getCondition()) } /** * Holds if the loop condition is provably `false`. @@ -448,7 +448,7 @@ class WhileStmt extends Loop, @stmt_while { * while(0) { ...; } * ``` */ - predicate conditionAlwaysFalse() { conditionAlwaysFalse(getCondition()) } + predicate conditionAlwaysFalse() { conditionAlwaysFalse(this.getCondition()) } /** * Holds if the loop condition is provably `true` upon entry, @@ -857,7 +857,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for { * ``` * the result is `int x`. */ - LocalVariable getVariable() { result = getChild(4).(DeclStmt).getADeclaration() } + LocalVariable getVariable() { result = this.getChild(4).(DeclStmt).getADeclaration() } /** * Gets the expression giving the range to iterate over. @@ -868,10 +868,10 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for { * ``` * the result is `xs`. */ - Expr getRange() { result = getRangeVariable().getInitializer().getExpr() } + Expr getRange() { result = this.getRangeVariable().getInitializer().getExpr() } /** Gets the compiler-generated `__range` variable after desugaring. */ - LocalVariable getRangeVariable() { result = getChild(0).(DeclStmt).getADeclaration() } + LocalVariable getRangeVariable() { result = this.getChild(0).(DeclStmt).getADeclaration() } /** * Gets the compiler-generated `__begin != __end` which is the @@ -891,10 +891,10 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for { DeclStmt getBeginEndDeclaration() { result = this.getChild(1) } /** Gets the compiler-generated `__begin` variable after desugaring. */ - LocalVariable getBeginVariable() { result = getBeginEndDeclaration().getDeclaration(0) } + LocalVariable getBeginVariable() { result = this.getBeginEndDeclaration().getDeclaration(0) } /** Gets the compiler-generated `__end` variable after desugaring. */ - LocalVariable getEndVariable() { result = getBeginEndDeclaration().getDeclaration(1) } + LocalVariable getEndVariable() { result = this.getBeginEndDeclaration().getDeclaration(1) } /** * Gets the compiler-generated `++__begin` which is the update @@ -905,7 +905,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for { Expr getUpdate() { result = this.getChild(3) } /** Gets the compiler-generated `__begin` variable after desugaring. */ - LocalVariable getAnIterationVariable() { result = getBeginVariable() } + LocalVariable getAnIterationVariable() { result = this.getBeginVariable() } } /** @@ -1067,7 +1067,7 @@ class ForStmt extends Loop, @stmt_for { * for(x = 0; 1; ++x) { sum += x; } * ``` */ - predicate conditionAlwaysTrue() { conditionAlwaysTrue(getCondition()) } + predicate conditionAlwaysTrue() { conditionAlwaysTrue(this.getCondition()) } /** * Holds if the loop condition is provably `false`. @@ -1077,7 +1077,7 @@ class ForStmt extends Loop, @stmt_for { * for(x = 0; 0; ++x) { sum += x; } * ``` */ - predicate conditionAlwaysFalse() { conditionAlwaysFalse(getCondition()) } + predicate conditionAlwaysFalse() { conditionAlwaysFalse(this.getCondition()) } /** * Holds if the loop condition is provably `true` upon entry, @@ -1723,10 +1723,10 @@ class Handler extends Stmt, @stmt_handler { /** * Gets the block containing the implementation of this handler. */ - CatchBlock getBlock() { result = getChild(0) } + CatchBlock getBlock() { result = this.getChild(0) } /** Gets the 'try' statement corresponding to this 'catch block'. */ - TryStmt getTryStmt() { result = getParent() } + TryStmt getTryStmt() { result = this.getParent() } /** * Gets the parameter introduced by this 'catch block', if any. @@ -1734,7 +1734,7 @@ class Handler extends Stmt, @stmt_handler { * For example, `catch(std::exception& e)` introduces a * parameter `e`, whereas `catch(...)` does not introduce a parameter. */ - Parameter getParameter() { result = getBlock().getParameter() } + Parameter getParameter() { result = this.getBlock().getParameter() } override predicate mayBeImpure() { none() } @@ -1921,15 +1921,15 @@ class MicrosoftTryStmt extends Stmt, @stmt_microsoft_try { * This is a Microsoft C/C++ extension. */ class MicrosoftTryExceptStmt extends MicrosoftTryStmt { - MicrosoftTryExceptStmt() { getChild(1) instanceof Expr } + MicrosoftTryExceptStmt() { this.getChild(1) instanceof Expr } override string toString() { result = "__try { ... } __except( ... ) { ... }" } /** Gets the expression guarding the `__except` statement. */ - Expr getCondition() { result = getChild(1) } + Expr getCondition() { result = this.getChild(1) } /** Gets the `__except` statement (usually a `BlockStmt`). */ - Stmt getExcept() { result = getChild(2) } + Stmt getExcept() { result = this.getChild(2) } override string getAPrimaryQlClass() { result = "MicrosoftTryExceptStmt" } } @@ -1948,12 +1948,12 @@ class MicrosoftTryExceptStmt extends MicrosoftTryStmt { * This is a Microsoft C/C++ extension. */ class MicrosoftTryFinallyStmt extends MicrosoftTryStmt { - MicrosoftTryFinallyStmt() { not getChild(1) instanceof Expr } + MicrosoftTryFinallyStmt() { not this.getChild(1) instanceof Expr } override string toString() { result = "__try { ... } __finally { ... }" } /** Gets the `__finally` statement (usually a `BlockStmt`). */ - Stmt getFinally() { result = getChild(1) } + Stmt getFinally() { result = this.getChild(1) } override string getAPrimaryQlClass() { result = "MicrosoftTryFinallyStmt" } } diff --git a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql index 5f11a9e0830..d2c69ba5fff 100644 --- a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql +++ b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql @@ -68,12 +68,12 @@ class VariableDeclarationLine extends TVariableDeclarationInfo { /** * Gets the start column of the first `VariableDeclarationEntry` on this line. */ - int getStartColumn() { result = min(getAVDE().getLocation().getStartColumn()) } + int getStartColumn() { result = min(this.getAVDE().getLocation().getStartColumn()) } /** * Gets the end column of the last `VariableDeclarationEntry` on this line. */ - int getEndColumn() { result = max(getAVDE().getLocation().getEndColumn()) } + int getEndColumn() { result = max(this.getAVDE().getLocation().getEndColumn()) } /** * Gets the rank of this `VariableDeclarationLine` in its file and class @@ -89,14 +89,14 @@ class VariableDeclarationLine extends TVariableDeclarationInfo { */ VariableDeclarationLine getNext() { result = TVariableDeclarationLine(c, f, _) and - result.getRank() = getRank() + 1 + result.getRank() = this.getRank() + 1 } /** * Gets the `VariableDeclarationLine` following this one, if it is nearby. */ VariableDeclarationLine getProximateNext() { - result = getNext() and + result = this.getNext() and result.getLine() <= this.getLine() + 3 } @@ -114,14 +114,14 @@ class VariableDeclarationGroup extends VariableDeclarationLine { // there is no `VariableDeclarationLine` within three lines previously not any(VariableDeclarationLine prev).getProximateNext() = this and // `end` is the last transitively proximate line - end = getProximateNext*() and + end = this.getProximateNext*() and not exists(end.getProximateNext()) } predicate hasLocationInfo(string path, int startline, int startcol, int endline, int endcol) { path = f.getAbsolutePath() and - startline = getLine() and - startcol = getStartColumn() and + startline = this.getLine() and + startcol = this.getStartColumn() and endline = end.getLine() and endcol = end.getEndColumn() } @@ -132,18 +132,18 @@ class VariableDeclarationGroup extends VariableDeclarationLine { int getCount() { result = count(VariableDeclarationLine l | - l = getProximateNext*() + l = this.getProximateNext*() | l.getAVDE().getVariable().getName() ) } override string toString() { - getCount() = 1 and - result = "declaration of " + getAVDE().getVariable().getName() + this.getCount() = 1 and + result = "declaration of " + this.getAVDE().getVariable().getName() or - getCount() > 1 and - result = "group of " + getCount() + " fields here" + this.getCount() > 1 and + result = "group of " + this.getCount() + " fields here" } } diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll b/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll index 0b60a3b9877..543c516e4bf 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll @@ -50,7 +50,7 @@ class SemaphoreTake extends LockOperation { result.(SemaphoreGive).getLocked() = this.getLocked() } - override string say() { result = "semaphore take of " + getLocked().getName() } + override string say() { result = "semaphore take of " + this.getLocked().getName() } } class SemaphoreGive extends UnlockOperation { @@ -76,13 +76,13 @@ class LockingPrimitive extends FunctionCall, LockOperation { this.getTarget().getName().replaceAll("Lock", "Unlock") } - override string say() { result = "call to " + getLocked().getName() } + override string say() { result = "call to " + this.getLocked().getName() } } class UnlockingPrimitive extends FunctionCall, UnlockOperation { UnlockingPrimitive() { this.getTarget().getName() = ["taskUnlock", "intUnlock", "taskRtpUnlock"] } - Function getLocked() { result = getMatchingLock().getLocked() } + Function getLocked() { result = this.getMatchingLock().getLocked() } override LockOperation getMatchingLock() { this = result.getMatchingUnlock() } } diff --git a/cpp/ql/src/external/CodeDuplication.qll b/cpp/ql/src/external/CodeDuplication.qll index 1550ca697a3..2656378bf62 100644 --- a/cpp/ql/src/external/CodeDuplication.qll +++ b/cpp/ql/src/external/CodeDuplication.qll @@ -38,10 +38,10 @@ class Copy extends @duplication_or_similarity { int sourceStartColumn() { tokens(this, 0, _, result, _, _) } /** Gets the line on which the last token in this block ends. */ - int sourceEndLine() { tokens(this, lastToken(), _, _, result, _) } + int sourceEndLine() { tokens(this, this.lastToken(), _, _, result, _) } /** Gets the column on which the last token in this block ends. */ - int sourceEndColumn() { tokens(this, lastToken(), _, _, _, result) } + int sourceEndColumn() { tokens(this, this.lastToken(), _, _, _, result) } /** Gets the number of lines containing at least (part of) one token in this block. */ int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() } @@ -66,11 +66,11 @@ class Copy extends @duplication_or_similarity { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - sourceFile().getAbsolutePath() = filepath and - startline = sourceStartLine() and - startcolumn = sourceStartColumn() and - endline = sourceEndLine() and - endcolumn = sourceEndColumn() + this.sourceFile().getAbsolutePath() = filepath and + startline = this.sourceStartLine() and + startcolumn = this.sourceStartColumn() and + endline = this.sourceEndLine() and + endcolumn = this.sourceEndColumn() } /** Gets a textual representation of this element. */ @@ -79,13 +79,15 @@ class Copy extends @duplication_or_similarity { /** A block of duplicated code. */ class DuplicateBlock extends Copy, @duplication { - override string toString() { result = "Duplicate code: " + sourceLines() + " duplicated lines." } + override string toString() { + result = "Duplicate code: " + this.sourceLines() + " duplicated lines." + } } /** A block of similar code. */ class SimilarBlock extends Copy, @similarity { override string toString() { - result = "Similar code: " + sourceLines() + " almost duplicated lines." + result = "Similar code: " + this.sourceLines() + " almost duplicated lines." } } diff --git a/cpp/ql/src/external/MetricFilter.qll b/cpp/ql/src/external/MetricFilter.qll index 58e8bf154e9..0315cd23c8d 100644 --- a/cpp/ql/src/external/MetricFilter.qll +++ b/cpp/ql/src/external/MetricFilter.qll @@ -67,7 +67,7 @@ class MetricResult extends int { /** Gets the URL corresponding to the location of this query result. */ string getURL() { result = - "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" + - getEndLine() + ":" + getEndColumn() + "file://" + this.getFile().getAbsolutePath() + ":" + this.getStartLine() + ":" + + this.getStartColumn() + ":" + this.getEndLine() + ":" + this.getEndColumn() } } From f38dade578d703a8868062fcff0578505535d77a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 15 Oct 2021 17:39:12 +0100 Subject: [PATCH 298/361] C++: Disable the two null termination queries enabled by 6794. --- .../src/Likely Bugs/Memory Management/ImproperNullTermination.ql | 1 - .../src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql | 1 - 2 files changed, 2 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql index 5c92b0a3db7..ed378dce60a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql @@ -5,7 +5,6 @@ * @kind problem * @id cpp/improper-null-termination * @problem.severity warning - * @precision medium * @security-severity 7.8 * @tags security * external/cwe/cwe-170 diff --git a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql index 31ce1037b27..b2844c319ba 100644 --- a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql @@ -5,7 +5,6 @@ * @kind problem * @id cpp/user-controlled-null-termination-tainted * @problem.severity warning - * @precision medium * @security-severity 10.0 * @tags security * external/cwe/cwe-170 From 2d61519ec6dee02e3e6e3939a6a59e1b2a8b2e83 Mon Sep 17 00:00:00 2001 From: Calum Grant <42069085+calumgrant@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:01:56 +0100 Subject: [PATCH 299/361] Update docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst Co-authored-by: hubwriter <hubwriter@github.com> --- .../codeql/codeql-language-guides/basic-query-for-ruby-code.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst index a48933fc4cf..d30064c1ec9 100644 --- a/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst @@ -3,7 +3,7 @@ Basic query for Ruby code ========================= -Learn to write and run a simple CodeQL query using CodeQL. +Learn to write and run a simple CodeQL query. About the query --------------- From 579753b0fc27b623cead28e872d910cf83be411a Mon Sep 17 00:00:00 2001 From: Calum Grant <42069085+calumgrant@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:02:09 +0100 Subject: [PATCH 300/361] Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst Co-authored-by: hubwriter <hubwriter@github.com> --- docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index 146b4eb1d90..eab0e5bae15 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -41,7 +41,7 @@ The data flow library is imported using import codeql.ruby.DataFlow Data flow tracks the flow of data through the program, including through function calls (interprocedural data flow). -Data flow is particularly useful for security queries, where untrusted data flow to vulnerable parts of the program +Data flow is particularly useful for security queries, where untrusted data flows to vulnerable parts of the program to exploit it. Related to data flow, is the taint-tracking library, which finds how data can *influence* other values in a program, even when it is not copied exactly. From 86c5b5d94402c7dd91f9f773ee3509819969575e Mon Sep 17 00:00:00 2001 From: Calum Grant <42069085+calumgrant@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:02:20 +0100 Subject: [PATCH 301/361] Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst Co-authored-by: hubwriter <hubwriter@github.com> --- docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index eab0e5bae15..3d462b58cc4 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -68,7 +68,7 @@ To summarise, the main Ruby modules are: * - ``codeql.ruby.TaintTracking`` - The taint tracking library -The CodeQL examples are only excerpts and are not meant to represent complete queries. +The CodeQL examples in this article are only excerpts and are not meant to represent complete queries. Abstract syntax --------------- From 48077a5757896a2ac7d61ade70d88fa4dec0714d Mon Sep 17 00:00:00 2001 From: Calum Grant <42069085+calumgrant@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:02:32 +0100 Subject: [PATCH 302/361] Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst Co-authored-by: hubwriter <hubwriter@github.com> --- docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index 3d462b58cc4..7968c9973d8 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -74,7 +74,7 @@ Abstract syntax --------------- The abstract syntax tree (AST) represents the elements of the source code organised into a tree. The AST viewer -feature of Visual Studio Code shows the AST nodes, including the relevant CodeQL classes and predicates. +in Visual Studio Code shows the AST nodes, including the relevant CodeQL classes and predicates. All CodeQL AST classes inherit from the `AstNode` class, which provides the following member predicates to all AST classes: From bf5cc212e1084759933df76cdf9cb4087b6dd592 Mon Sep 17 00:00:00 2001 From: Calum Grant <42069085+calumgrant@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:02:40 +0100 Subject: [PATCH 303/361] Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst Co-authored-by: hubwriter <hubwriter@github.com> --- docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index 7968c9973d8..905be333ba1 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -115,7 +115,7 @@ namespaces (``Namespace``) and classes (``ClassDeclaration``). - A representation of a run-time `module` or `class` value. - `getADeclaration()` - Gets a declaration - - `getSuperClass()` - Gets the super class fo this module, if any. + - `getSuperClass()` - Gets the super class of this module, if any. - `getAPrependedModule()` - Gets a prepended module. - `getAnIncludedModule()` - Gets an included module. * - ``Namespace`` From 5265ed6b640ffe7a61a71654a7810602bb71409d Mon Sep 17 00:00:00 2001 From: Calum Grant <42069085+calumgrant@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:02:54 +0100 Subject: [PATCH 304/361] Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst Co-authored-by: hubwriter <hubwriter@github.com> --- docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index 905be333ba1..12989d4c13f 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -112,7 +112,7 @@ namespaces (``Namespace``) and classes (``ClassDeclaration``). * - CodeQL class - Description and selected predicates * - ``Module`` - - A representation of a run-time `module` or `class` value. + - A representation of a runtime `module` or `class` value. - `getADeclaration()` - Gets a declaration - `getSuperClass()` - Gets the super class of this module, if any. From 87adcc2e6b99e23f962bb80847a39a58c0427aeb Mon Sep 17 00:00:00 2001 From: Calum Grant <42069085+calumgrant@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:03:04 +0100 Subject: [PATCH 305/361] Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst Co-authored-by: hubwriter <hubwriter@github.com> --- docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index 12989d4c13f..296d8e36385 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -73,7 +73,7 @@ The CodeQL examples in this article are only excerpts and are not meant to repre Abstract syntax --------------- -The abstract syntax tree (AST) represents the elements of the source code organised into a tree. The AST viewer +The abstract syntax tree (AST) represents the elements of the source code organized into a tree. The AST viewer in Visual Studio Code shows the AST nodes, including the relevant CodeQL classes and predicates. All CodeQL AST classes inherit from the `AstNode` class, which provides the following member predicates From 42c5af3cdf31fa7140fe2de76912ff15039d2ebb Mon Sep 17 00:00:00 2001 From: Calum Grant <42069085+calumgrant@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:03:12 +0100 Subject: [PATCH 306/361] Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst Co-authored-by: hubwriter <hubwriter@github.com> --- docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index 296d8e36385..c6bb83d83c2 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -48,7 +48,7 @@ in a program, even when it is not copied exactly. The API graphs library is used to locate methods in libraries. This is particuarly useful when locating particular functions or parameters that could be used as a source or sink of data in a security query. -To summarise, the main Ruby modules are: +To summarize, the main Ruby modules are: .. list-table:: Main Ruby modules :header-rows: 1 From 5861fcf4434aee9c72f7d04b1e79dfd28b94be6c Mon Sep 17 00:00:00 2001 From: Calum Grant <calumgrant@github.com> Date: Fri, 15 Oct 2021 18:07:18 +0100 Subject: [PATCH 307/361] Address review comment --- docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index c6bb83d83c2..1119159314f 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -30,7 +30,7 @@ The control flow graph (CFG) is imported using import codeql.ruby.CFG -The CFG reasons about the control flow between statements and expressions, for example whether one expression can +The CFG models the control flow between statements and expressions, for example whether one expression can flow to another expression, or whether an expression "dominates" another one, meaning that all paths to an expression must flow through another expression first. From e485a169933ed5a9af557a886710c601bac2fd40 Mon Sep 17 00:00:00 2001 From: Ian Lynagh <igfoo@github.com> Date: Fri, 15 Oct 2021 18:39:42 +0100 Subject: [PATCH 308/361] Java: Don't use dbscheme tables in CloseType.qll --- java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll b/java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll index 46d88f86f41..b4bdc9283a0 100644 --- a/java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll +++ b/java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll @@ -228,8 +228,8 @@ private predicate closeCalled(Variable v) { ) or // The "close" call could happen indirectly inside a helper method of unknown name. - exists(int i | exprs(v.getAnAccess(), _, _, e, i) | - exists(Parameter p, int j | params(p, _, j, e.getMethod(), _) | + exists(int i | v.getAnAccess().isNthChildOf(e, i) | + exists(Parameter p, int j | p.getPosition() = j and p.getCallable() = e.getMethod() | closeCalled(p) and i = j or // The helper method could be iterating over a varargs parameter. From 0e01b91c7ead89d072749cd8077a094e4ed15923 Mon Sep 17 00:00:00 2001 From: Edoardo Pirovano <edoardo.pirovano@gmail.com> Date: Sat, 16 Oct 2021 08:57:26 +0100 Subject: [PATCH 309/361] Language reference: Fix when trailing commas are allowed --- docs/codeql/ql-language-reference/ql-language-specification.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 919a075e9aa..2ebcd3780ce 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -1333,7 +1333,7 @@ The values of a set literal expression are all the values of all the contained e Set literals are supported from release 2.1.0 of the CodeQL CLI, and release 1.24 of LGTM Enterprise. -Since release 2.6.3 of the CodeQL CLI, and release 1.28 of LGTM Enterprise, a trailing comma is allowed in a set literal. +Since release 2.7.0 of the CodeQL CLI, and release 1.28 of LGTM Enterprise, a trailing comma is allowed in a set literal. Disambiguation of expressions ----------------------------- From bf76d9cd8b33ef2e5c3e21a1065f4a8b11742896 Mon Sep 17 00:00:00 2001 From: jorgectf <jorgectf@protonmail.com> Date: Sat, 16 Oct 2021 10:45:25 +0200 Subject: [PATCH 310/361] Fix django test --- .../query-tests/Security/CWE-113/django_bad.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-113/django_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-113/django_bad.py index b97d9137f46..972b3344a50 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-113/django_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-113/django_bad.py @@ -1,15 +1,15 @@ import django.http -def django_setitem(request): - rfs_header = request.GET.get("rfs_header") +def django_setitem(): + rfs_header = django.http.request.GET.get("rfs_header") response = django.http.HttpResponse() response.__setitem__('HeaderName', rfs_header) return response -def django_response(request): - rfs_header = request.GET.get("rfs_header") +def django_response(): + rfs_header = django.http.request.GET.get("rfs_header") response = django.http.HttpResponse() response['HeaderName'] = rfs_header return response From 14c50e993ba44893eef2e38ae2da957c4b62a906 Mon Sep 17 00:00:00 2001 From: jorgectf <jorgectf@protonmail.com> Date: Sat, 16 Oct 2021 13:10:48 +0200 Subject: [PATCH 311/361] Add django `GET.get` RFS --- .../semmle/python/frameworks/Django.qll | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Django.qll b/python/ql/src/experimental/semmle/python/frameworks/Django.qll index c525b73b40e..27ec7f6bd75 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Django.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Django.qll @@ -8,16 +8,27 @@ private import semmle.python.frameworks.Django private import semmle.python.dataflow.new.DataFlow private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs +import semmle.python.dataflow.new.RemoteFlowSources private module PrivateDjango { - API::Node django() { result = API::moduleImport("django") } - private module django { - API::Node http() { result = django().getMember("http") } + API::Node http() { result = API::moduleImport("django").getMember("http") } module http { API::Node response() { result = http().getMember("response") } + API::Node request() { result = http().getMember("request") } + + module request { + module HttpRequest { + class DjangoGETParameter extends DataFlow::Node, RemoteFlowSource::Range { + DjangoGETParameter() { this = request().getMember("GET").getMember("get").getACall() } + + override string getSourceType() { result = "django.http.request.GET.get" } + } + } + } + module response { module HttpResponse { API::Node baseClassRef() { From 271e2e4c49135a3af01a358a62d49a5ccf91b550 Mon Sep 17 00:00:00 2001 From: jorgectf <jorgectf@protonmail.com> Date: Sat, 16 Oct 2021 13:12:33 +0200 Subject: [PATCH 312/361] Update `.expected` --- .../Security/CWE-113/HeaderInjection.expected | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected index 9e0eff704b6..48fc4dfab07 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected @@ -1,4 +1,6 @@ edges +| django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | +| django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | | flask_bad.py:9:18:9:24 | ControlFlowNode for request | flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | | flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | | flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | @@ -10,11 +12,14 @@ edges | flask_bad.py:27:18:27:43 | ControlFlowNode for Subscript | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | | flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute | | flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute | flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | -| flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | +| flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | | flask_bad.py:44:44:44:50 | ControlFlowNode for request | flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute | | flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute | flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | -| flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | nodes +| django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | +| django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | | flask_bad.py:9:18:9:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -30,14 +35,16 @@ nodes | flask_bad.py:35:18:35:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | | flask_bad.py:44:44:44:50 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +subpaths #select +| django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | This | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | user-provided value | +| django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | This | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | user-provided value | | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | flask_bad.py:9:18:9:24 | ControlFlowNode for request | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | This | flask_bad.py:9:18:9:24 | ControlFlowNode for request | user-provided value | | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | flask_bad.py:19:18:19:24 | ControlFlowNode for request | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | This | flask_bad.py:19:18:19:24 | ControlFlowNode for request | user-provided value | | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | flask_bad.py:27:18:27:24 | ControlFlowNode for request | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | This | flask_bad.py:27:18:27:24 | ControlFlowNode for request | user-provided value | -| flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | $@ HTTP header is constructed from a $@. | flask_bad.py:38:9:38:34 | ControlFlowNode for Dict | This | flask_bad.py:35:18:35:24 | ControlFlowNode for request | user-provided value | -| flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | flask_bad.py:44:44:44:50 | ControlFlowNode for request | flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | $@ HTTP header is constructed from a $@. | flask_bad.py:44:29:44:70 | ControlFlowNode for Dict | This | flask_bad.py:44:44:44:50 | ControlFlowNode for request | user-provided value | +| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | This | flask_bad.py:35:18:35:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | flask_bad.py:44:44:44:50 | ControlFlowNode for request | flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | $@ HTTP header is constructed from a $@. | flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | This | flask_bad.py:44:44:44:50 | ControlFlowNode for request | user-provided value | From 2871bdb206b744d4031f820ece916abf4cc39312 Mon Sep 17 00:00:00 2001 From: Surya Prakash Sahu <suryathe16@gmail.com> Date: Sun, 17 Oct 2021 18:04:20 +0530 Subject: [PATCH 313/361] Python SignatureOverriddenMethod: Rmv duplicate condition --- python/ql/src/Functions/SignatureOverriddenMethod.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/python/ql/src/Functions/SignatureOverriddenMethod.ql b/python/ql/src/Functions/SignatureOverriddenMethod.ql index e695f2385ea..85f1f0c2eb1 100644 --- a/python/ql/src/Functions/SignatureOverriddenMethod.ql +++ b/python/ql/src/Functions/SignatureOverriddenMethod.ql @@ -24,7 +24,6 @@ where not derived.getScope().isSpecialMethod() and derived.getName() != "__init__" and derived.isNormalMethod() and - not derived.getScope().isSpecialMethod() and // call to overrides distributed for efficiency ( derived.overrides(base) and derived.minParameters() > base.maxParameters() From 43b7bc52cadec8fcfbd81d66158e93fe23c0ab33 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 18 Oct 2021 00:26:19 +0200 Subject: [PATCH 314/361] Java: Add `MemberRefExpr.getReceiverType()` --- java/ql/lib/semmle/code/java/Expr.qll | 21 +++++++ .../MemberRefExpr/MemberRefExpr.expected | 14 +++++ .../MemberRefExpr/MemberRefExpr.ql | 10 +++ .../library-tests/MemberRefExpr/Test.java | 63 +++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 java/ql/test/library-tests/MemberRefExpr/MemberRefExpr.expected create mode 100644 java/ql/test/library-tests/MemberRefExpr/MemberRefExpr.ql create mode 100644 java/ql/test/library-tests/MemberRefExpr/Test.java diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index b83f5332756..44da63f8fdc 100755 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1225,6 +1225,27 @@ class MemberRefExpr extends FunctionalExpr, @memberref { */ override Method asMethod() { result = getAnonymousClass().getAMethod() } + /** + * Gets the receiver type whose member this expression refers to. The result might not be + * the type which actually declares the member (makes a difference for inherited non-overridden + * methods). + */ + RefType getReceiverType() { + exists(Stmt stmt, Expr resultExpr | + stmt = asMethod().getBody().(SingletonBlock).getStmt() and + ( + resultExpr = stmt.(ReturnStmt).getResult() + or + // Note: Currently never an ExprStmt, but might change once https://github.com/github/codeql/issues/3605 is fixed + resultExpr = stmt.(ExprStmt).getExpr() + ) + | + result = resultExpr.(MethodAccess).getReceiverType() or + result = resultExpr.(ClassInstanceExpr).getConstructedType() or + result = resultExpr.(ArrayCreationExpr).getType() + ) + } + /** * Gets the method or constructor referenced by this member reference expression. */ diff --git a/java/ql/test/library-tests/MemberRefExpr/MemberRefExpr.expected b/java/ql/test/library-tests/MemberRefExpr/MemberRefExpr.expected new file mode 100644 index 00000000000..b02fa9c0e9a --- /dev/null +++ b/java/ql/test/library-tests/MemberRefExpr/MemberRefExpr.expected @@ -0,0 +1,14 @@ +| Test.java:24:26:24:51 | ...::... | Inner<>.Inner<> | Test$Generic$Inner.class:0:0:0:0 | Inner<> | +| Test.java:38:29:38:42 | ...::... | Object.toString | Test.java:1:7:1:10 | Test | +| Test.java:39:29:39:42 | ...::... | Object.hashCode | Test.java:1:7:1:10 | Test | +| Test.java:40:29:40:39 | ...::... | Object.clone | Test.java:1:7:1:10 | Test | +| Test.java:41:40:41:64 | ...::... | Object.toString | Test$Generic.class:0:0:0:0 | Generic<String> | +| Test.java:43:23:43:36 | ...::... | Object.toString | Test.java:1:7:1:10 | Test | +| Test.java:44:23:44:36 | ...::... | Object.hashCode | Test.java:1:7:1:10 | Test | +| Test.java:45:23:45:33 | ...::... | Object.clone | Test.java:1:7:1:10 | Test | +| Test.java:48:22:48:35 | ...::... | Object.toString | Test.java:1:7:1:10 | Test | +| Test.java:51:13:51:21 | ...::... | Test.Test | Test.java:1:7:1:10 | Test | +| Test.java:52:13:52:32 | ...::... | Generic<String>.Generic<String> | Test$Generic.class:0:0:0:0 | Generic<String> | +| Test.java:56:13:56:22 | ...::... | | file://:0:0:0:0 | int[] | +| Test.java:57:13:57:26 | ...::... | | file://:0:0:0:0 | Generic<>[] | +| Test.java:61:31:61:47 | ...::... | Test.doSomething | Test.java:1:7:1:10 | Test | diff --git a/java/ql/test/library-tests/MemberRefExpr/MemberRefExpr.ql b/java/ql/test/library-tests/MemberRefExpr/MemberRefExpr.ql new file mode 100644 index 00000000000..2f83916c50e --- /dev/null +++ b/java/ql/test/library-tests/MemberRefExpr/MemberRefExpr.ql @@ -0,0 +1,10 @@ +import java + +string getReferencedCallable(MemberRefExpr e) { + if exists(e.getReferencedCallable()) + then result = e.getReferencedCallable().getQualifiedName() + else result = "" +} + +from MemberRefExpr e +select e, getReferencedCallable(e), e.getReceiverType() diff --git a/java/ql/test/library-tests/MemberRefExpr/Test.java b/java/ql/test/library-tests/MemberRefExpr/Test.java new file mode 100644 index 00000000000..d477cf659a9 --- /dev/null +++ b/java/ql/test/library-tests/MemberRefExpr/Test.java @@ -0,0 +1,63 @@ +class Test { + interface Function<T> { + Object apply(T o) throws Exception; + } + + interface IntFunction { + Object apply(int i); + } + + interface Supplier { + Object get() throws Exception; + } + + public Test() { } + + static class Generic<T> { + public Generic() { } + + class Inner { + public Inner() { } + } + + void test() { + Supplier s = Generic<Number>.Inner::new; + } + } + + void doSomething() { } + + static class Sub extends Test { + } + + interface SubtypeConsumer { + void consume(Sub s); + } + + void test() { + Function<Test> f0 = Test::toString; + Function<Test> f1 = Test::hashCode; + Function<Test> f2 = Test::clone; + Function<Generic<String>> f3 = Generic<String>::toString; + + Supplier s0 = this::toString; + Supplier s1 = this::hashCode; + Supplier s2 = this::clone; + + // Discards result of method call + Runnable r = this::toString; + + Supplier[] classInstances = { + Test::new, + Generic<String>::new, + }; + + IntFunction[] arrays = { + int[]::new, + Generic[]::new, + }; + + // SubtypeConsumer has `Sub` as parameter type, but receiver here is `Test` (supertype) + SubtypeConsumer sub = Test::doSomething; + } +} From ea67ca22a913db00143284a0c7c724163a4c3ff2 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Mon, 18 Oct 2021 09:00:00 +0100 Subject: [PATCH 315/361] C++: Undo changes to shared dataflow files. --- .../code/cpp/dataflow/internal/DataFlowImpl.qll | 16 +++++++--------- .../code/cpp/dataflow/internal/DataFlowImpl2.qll | 16 +++++++--------- .../code/cpp/dataflow/internal/DataFlowImpl3.qll | 16 +++++++--------- .../code/cpp/dataflow/internal/DataFlowImpl4.qll | 16 +++++++--------- .../cpp/dataflow/internal/DataFlowImplLocal.qll | 16 +++++++--------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 16 +++++++--------- .../cpp/ir/dataflow/internal/DataFlowImpl2.qll | 16 +++++++--------- .../cpp/ir/dataflow/internal/DataFlowImpl3.qll | 16 +++++++--------- .../cpp/ir/dataflow/internal/DataFlowImpl4.qll | 16 +++++++--------- 9 files changed, 63 insertions(+), 81 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 c3b2fc44f14..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index c3b2fc44f14..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index c3b2fc44f14..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index c3b2fc44f14..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index c3b2fc44f14..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and 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 c3b2fc44f14..4ca06c93362 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 @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index c3b2fc44f14..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index c3b2fc44f14..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index c3b2fc44f14..4ca06c93362 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + result = "[" + this.toStringImpl(true) + length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,11 +3309,9 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + override string toString() { result = this.getNodeEx().toString() + ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3381,11 +3379,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = this.getSuccMid() + result = getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = this.getSuccMid() and + mid = getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and From 54d20289201030090615cb3c9328df2c9ef5f39b Mon Sep 17 00:00:00 2001 From: Ian Lynagh <igfoo@github.com> Date: Mon, 18 Oct 2021 10:12:01 +0100 Subject: [PATCH 316/361] Update java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll Co-authored-by: Chris Smowton <smowton@github.com> --- java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll b/java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll index b4bdc9283a0..d88f1bb82c7 100644 --- a/java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll +++ b/java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll @@ -228,7 +228,7 @@ private predicate closeCalled(Variable v) { ) or // The "close" call could happen indirectly inside a helper method of unknown name. - exists(int i | v.getAnAccess().isNthChildOf(e, i) | + exists(int i | e.getArgument(i) = v.getAnAccess() | exists(Parameter p, int j | p.getPosition() = j and p.getCallable() = e.getMethod() | closeCalled(p) and i = j or From df9836cce092094d5cdae6243a58aef3c9605dab Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Mon, 18 Oct 2021 14:04:16 +0200 Subject: [PATCH 317/361] Work around compiler bug. --- java/ql/lib/semmle/code/java/security/CommandArguments.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/security/CommandArguments.qll b/java/ql/lib/semmle/code/java/security/CommandArguments.qll index d8ec58e623e..8be5536f25c 100644 --- a/java/ql/lib/semmle/code/java/security/CommandArguments.qll +++ b/java/ql/lib/semmle/code/java/security/CommandArguments.qll @@ -155,7 +155,7 @@ private class CommandArgArrayImmutableFirst extends CommandArgumentArray { Expr getFirstElement() { result = this.getAWrite(0) or - not exists(this.getAWrite(0)) and + not exists(getAWrite(0)) and result = firstElementOf(this.getDefiningExpr()) } From 91ea064980b077582cb7cca194e4a84a38a197f3 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Mon, 18 Oct 2021 14:04:50 +0200 Subject: [PATCH 318/361] Sync --- .../code/cpp/dataflow/internal/DataFlowImpl.qll | 16 +++++++++------- .../code/cpp/dataflow/internal/DataFlowImpl2.qll | 16 +++++++++------- .../code/cpp/dataflow/internal/DataFlowImpl3.qll | 16 +++++++++------- .../code/cpp/dataflow/internal/DataFlowImpl4.qll | 16 +++++++++------- .../cpp/dataflow/internal/DataFlowImplLocal.qll | 16 +++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 16 +++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl2.qll | 16 +++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl3.qll | 16 +++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl4.qll | 16 +++++++++------- .../csharp/dataflow/internal/DataFlowImpl.qll | 16 +++++++++------- .../csharp/dataflow/internal/DataFlowImpl2.qll | 16 +++++++++------- .../csharp/dataflow/internal/DataFlowImpl3.qll | 16 +++++++++------- .../csharp/dataflow/internal/DataFlowImpl4.qll | 16 +++++++++------- .../csharp/dataflow/internal/DataFlowImpl5.qll | 16 +++++++++------- .../dataflow/new/internal/DataFlowImpl.qll | 16 +++++++++------- .../dataflow/new/internal/DataFlowImpl2.qll | 16 +++++++++------- .../dataflow/new/internal/DataFlowImpl3.qll | 16 +++++++++------- .../dataflow/new/internal/DataFlowImpl4.qll | 16 +++++++++------- 18 files changed, 162 insertions(+), 126 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 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and 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 4ca06c93362..c3b2fc44f14 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 @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and 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 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and 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 4ca06c93362..c3b2fc44f14 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 4ca06c93362..c3b2fc44f14 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -110,12 +110,12 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` @@ -3170,7 +3170,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { } override string toString() { - result = "[" + this.toStringImpl(true) + length().toString() + ")]" + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" or result = "[" + this.toStringImpl(false) } @@ -3309,9 +3309,11 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + ppAp() } + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -3379,11 +3381,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { override PathNodeImpl getASuccessorImpl() { // an intermediate step to another intermediate node - result = getSuccMid() + result = this.getSuccMid() or // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges exists(PathNodeMid mid, PathNodeSink sink | - mid = getSuccMid() and + mid = this.getSuccMid() and mid.getNodeEx() = sink.getNodeEx() and mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and From e6954292aa4c42647acd8c0dbf939320558d37f7 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 18 Oct 2021 09:41:22 +0200 Subject: [PATCH 319/361] Address review comments --- .../code/cpp/dataflow/internal/DataFlowImpl.qll | 16 ++++++++++------ .../code/cpp/dataflow/internal/DataFlowImpl2.qll | 16 ++++++++++------ .../code/cpp/dataflow/internal/DataFlowImpl3.qll | 16 ++++++++++------ .../code/cpp/dataflow/internal/DataFlowImpl4.qll | 16 ++++++++++------ .../cpp/dataflow/internal/DataFlowImplLocal.qll | 16 ++++++++++------ .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 16 ++++++++++------ .../cpp/ir/dataflow/internal/DataFlowImpl2.qll | 16 ++++++++++------ .../cpp/ir/dataflow/internal/DataFlowImpl3.qll | 16 ++++++++++------ .../cpp/ir/dataflow/internal/DataFlowImpl4.qll | 16 ++++++++++------ .../csharp/dataflow/internal/DataFlowImpl.qll | 16 ++++++++++------ .../csharp/dataflow/internal/DataFlowImpl2.qll | 16 ++++++++++------ .../csharp/dataflow/internal/DataFlowImpl3.qll | 16 ++++++++++------ .../csharp/dataflow/internal/DataFlowImpl4.qll | 16 ++++++++++------ .../csharp/dataflow/internal/DataFlowImpl5.qll | 16 ++++++++++------ .../code/java/dataflow/internal/DataFlowImpl.qll | 16 ++++++++++------ .../java/dataflow/internal/DataFlowImpl2.qll | 16 ++++++++++------ .../java/dataflow/internal/DataFlowImpl3.qll | 16 ++++++++++------ .../java/dataflow/internal/DataFlowImpl4.qll | 16 ++++++++++------ .../java/dataflow/internal/DataFlowImpl5.qll | 16 ++++++++++------ .../java/dataflow/internal/DataFlowImpl6.qll | 16 ++++++++++------ .../internal/DataFlowImplForSerializability.qll | 16 ++++++++++------ .../dataflow/new/internal/DataFlowImpl.qll | 16 ++++++++++------ .../dataflow/new/internal/DataFlowImpl2.qll | 16 ++++++++++------ .../dataflow/new/internal/DataFlowImpl3.qll | 16 ++++++++++------ .../dataflow/new/internal/DataFlowImpl4.qll | 16 ++++++++++------ 25 files changed, 250 insertions(+), 150 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 0db4f7fc53e..e802b89fba2 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) 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 0db4f7fc53e..e802b89fba2 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 @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) 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 0db4f7fc53e..e802b89fba2 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) 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 0db4f7fc53e..e802b89fba2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) 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 0db4f7fc53e..e802b89fba2 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 0db4f7fc53e..e802b89fba2 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -3563,10 +3563,15 @@ private predicate parameterCand( pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config + AccessPath ap, Configuration config ) { - pathIntoArg(mid, i, outercc, call, ap, apa, config) and - callable = resolveCall(call, outercc) + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) } /** @@ -3579,9 +3584,8 @@ private predicate pathIntoCallable( PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call, Configuration config ) { - exists(int i, DataFlowCallable callable, AccessPath ap, AccessPathApprox apa | - pathIntoCallable0(mid, callable, i, outercc, call, ap, apa, config) and - parameterCand(callable, i, apa, config) and + exists(int i, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and p.isParameterOf(callable, i) and ( sc = TSummaryCtxSome(p, ap) From 86d53931aa5ac6d6a955bc27171209269d3506c7 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 18 Oct 2021 18:20:22 +0200 Subject: [PATCH 320/361] Java: Improve `MemberRefExpr.getReceiverType()` documentation --- java/ql/lib/semmle/code/java/Expr.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index 44da63f8fdc..c0205ed1c38 100755 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1227,8 +1227,9 @@ class MemberRefExpr extends FunctionalExpr, @memberref { /** * Gets the receiver type whose member this expression refers to. The result might not be - * the type which actually declares the member (makes a difference for inherited non-overridden - * methods). + * the type which actually declares the member. For example, for the member reference `ArrayList::toString`, + * this predicate has the result `java.util.ArrayList`, the type explicitly referred to, while + * `getReferencedCallable` will have `java.util.AbstractCollection.toString` as result, which `ArrayList` inherits. */ RefType getReceiverType() { exists(Stmt stmt, Expr resultExpr | From 4d7a8285adcc5d36a39a13efb8d8c15a2e7d0c0d Mon Sep 17 00:00:00 2001 From: Henry Mercer <henrymercer@github.com> Date: Mon, 18 Oct 2021 12:52:37 +0100 Subject: [PATCH 321/361] JS: Initial commit of Adaptive Threat Modeling --- .codeqlmanifest.json | 2 + .../adaptivethreatmodeling/README.md | 6 + .../adaptivethreatmodeling/ATMConfig.qll | 112 +++++ .../AdaptiveThreatModeling.qll | 125 +++++ .../adaptivethreatmodeling/BaseScoring.qll | 121 +++++ .../adaptivethreatmodeling/CodeToFeatures.qll | 444 ++++++++++++++++++ .../adaptivethreatmodeling/CoreKnowledge.qll | 208 ++++++++ .../EndpointFeatures.qll | 290 ++++++++++++ .../EndpointScoring.qll | 223 +++++++++ .../adaptivethreatmodeling/EndpointTypes.qll | 57 +++ .../FilteringReasons.qll | 196 ++++++++ .../NosqlInjectionATM.qll | 178 +++++++ .../SqlInjectionATM.qll | 94 ++++ .../StandardEndpointFilters.qll | 137 ++++++ .../adaptivethreatmodeling/TaintedPathATM.qll | 123 +++++ .../adaptivethreatmodeling/XssATM.qll | 103 ++++ .../lib/qlpack.lock.yml | 4 + .../adaptivethreatmodeling/lib/qlpack.yml | 6 + .../src/NosqlInjectionATM.ql | 30 ++ .../src/SqlInjectionATM.ql | 30 ++ .../src/TaintedPathATM.ql | 30 ++ .../adaptivethreatmodeling/src/XssATM.ql | 31 ++ .../javascript-atm-code-scanning.qls | 8 + .../src/qlpack.lock.yml | 4 + .../adaptivethreatmodeling/src/qlpack.yml | 6 + .../adaptivethreatmodeling/src/queries.xml | 1 + 26 files changed, 2569 insertions(+) create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/README.md create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/ATMConfig.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/AdaptiveThreatModeling.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/BaseScoring.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/CodeToFeatures.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/CoreKnowledge.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointScoring.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointTypes.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/FilteringReasons.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/NosqlInjectionATM.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/SqlInjectionATM.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/StandardEndpointFilters.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/TaintedPathATM.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/XssATM.qll create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.lock.yml create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/NosqlInjectionATM.ql create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/SqlInjectionATM.ql create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/TaintedPathATM.ql create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.ql create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.lock.yml create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/queries.xml diff --git a/.codeqlmanifest.json b/.codeqlmanifest.json index 4efe12f6d2b..5877584bdd5 100644 --- a/.codeqlmanifest.json +++ b/.codeqlmanifest.json @@ -4,5 +4,7 @@ "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml", "*/ql/examples/qlpack.yml", "*/upgrades/qlpack.yml", + "javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml", + "javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml", "misc/legacy-support/*/qlpack.yml", "misc/suite-helpers/qlpack.yml" ] } diff --git a/javascript/ql/experimental/adaptivethreatmodeling/README.md b/javascript/ql/experimental/adaptivethreatmodeling/README.md new file mode 100644 index 00000000000..341534e3fdf --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/README.md @@ -0,0 +1,6 @@ +# [Internal only] Adaptive Threat Modeling for JavaScript + +This directory contains CodeQL libraries and queries that power adaptive threat modeling for JavaScript. +All APIs are experimental and may change in the future. + +These queries can only be run by internal users; for external users they will return no results. diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/ATMConfig.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/ATMConfig.qll new file mode 100644 index 00000000000..bec90be46cc --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/ATMConfig.qll @@ -0,0 +1,112 @@ +/* + * For internal use only. + * + * Configures boosting for adaptive threat modeling (ATM). + */ + +private import javascript as raw +import EndpointTypes + +/** + * EXPERIMENTAL. This API may change in the future. + * + * A configuration class for defining known endpoints and endpoint filters for adaptive threat + * modeling (ATM). Each boosted query must define its own extension of this abstract class. + * + * A configuration defines a set of known sources (`isKnownSource`) and sinks (`isKnownSink`). + * It must also define a sink endpoint filter (`isEffectiveSink`) that filters candidate sinks + * predicted by the machine learning model to a set of effective sinks. + * + * To get started with ATM, you can copy-paste an implementation of the relevant predicates from a + * `DataFlow::Configuration` or `TaintTracking::Configuration` class for a standard security query. + * For example, for SQL injection you can start by defining the `isKnownSource` and `isKnownSink` + * predicates in the ATM configuration by copying and pasting the implementations of `isSource` and + * `isSink` from `SqlInjection::Configuration`. + * + * Note that if the security query configuration defines additional edges beyond the standard data + * flow edges, such as `NosqlInjection::Configuration`, you may need to replace the definition of + * `isAdditionalFlowStep` with a more generalised definition of additional edges. See + * `NosqlInjectionATM.qll` for an example of doing this. + */ +abstract class ATMConfig extends string { + bindingset[this] + ATMConfig() { any() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if `source` is a known source of flow. + */ + predicate isKnownSource(raw::DataFlow::Node source) { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if `sink` is a known sink of flow. + */ + predicate isKnownSink(raw::DataFlow::Node sink) { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if the candidate source `candidateSource` predicted by the machine learning model should be + * an effective source, i.e. one considered as a possible source of flow in the boosted query. + */ + predicate isEffectiveSource(raw::DataFlow::Node candidateSource) { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if the candidate sink `candidateSink` predicted by the machine learning model should be + * an effective sink, i.e. one considered as a possible sink of flow in the boosted query. + */ + predicate isEffectiveSink(raw::DataFlow::Node candidateSink) { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if the candidate sink `candidateSink` predicted by the machine learning model should be + * an effective sink that overrides the score provided by the machine learning model with the + * score `score` for reason `why`. The effective sinks identified by this predicate MUST be a + * subset of those identified by the `isEffectiveSink` predicate. + * + * For example, in the ATM external API query, we use this method to ensure the ATM external API + * query produces the same results as the standard external API query, but assigns flows + * involving sinks that are filtered out by the endpoint filters a score of 0. + * + * This predicate can be phased out once we no longer need to rely on predicates like + * `paddedScore` in the ATM CodeQL libraries to add scores to alert messages in a way that works + * with lexical sort orders. + */ + predicate isEffectiveSinkWithOverridingScore( + raw::DataFlow::Node candidateSink, float score, string why + ) { + none() + } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Get an endpoint type for the sources of this query. A query may have multiple applicable + * endpoint types for its sources. + */ + EndpointType getASourceEndpointType() { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Get an endpoint type for the sinks of this query. A query may have multiple applicable + * endpoint types for its sinks. + */ + EndpointType getASinkEndpointType() { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Specifies the default cut-off value that controls how many alerts are produced. + * The cut-off value must be in the range [0,1]. + * A cut-off value of 0 only produces alerts that are likely true-positives. + * A cut-off value of 1 produces all alerts including those that are likely false-positives. + */ + float getScoreCutoff() { result = 0.0 } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/AdaptiveThreatModeling.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/AdaptiveThreatModeling.qll new file mode 100644 index 00000000000..678182f3987 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/AdaptiveThreatModeling.qll @@ -0,0 +1,125 @@ +/* + * For internal use only. + * + * Provides information about the results of boosted queries for use in adaptive threat modeling (ATM). + */ + +private import javascript as raw +private import raw::DataFlow as DataFlow +import ATMConfig +private import BaseScoring +private import EndpointScoring as EndpointScoring + +module ATM { + /** + * EXPERIMENTAL. This API may change in the future. + * + * This module contains informational predicates about the results returned by adaptive threat + * modeling (ATM). + */ + module ResultsInfo { + /** + * Indicates whether the flow from source to sink represents a result with + * sufficiently high likelihood of being a true-positive. + */ + pragma[inline] + private predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) { + any(ScoringResults results).shouldResultBeIncluded(source, sink) + } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Returns the score for the flow between the source `source` and the `sink` sink in the + * boosted query. + */ + pragma[inline] + float getScoreForFlow(DataFlow::Node source, DataFlow::Node sink) { + any(DataFlow::Configuration cfg).hasFlow(source, sink) and + shouldResultBeIncluded(source, sink) and + result = unique(float s | s = any(ScoringResults results).getScoreForFlow(source, sink)) + } + + /** + * Pad a score returned from `getKnownScoreForFlow` to a particular length by adding a decimal + * point if one does not already exist, and "0"s after that decimal point. + * + * Note that this predicate must itself define an upper bound on `length`, so that it has a + * finite number of results. Currently this is defined as 12. + */ + private string paddedScore(float score, int length) { + // In this definition, we must restrict the values that `length` and `score` can take on so + // that the predicate has a finite number of results. + (score = getScoreForFlow(_, _) or score = 0) and + length = result.length() and + ( + // We need to make sure the padded score contains a "." so lexically sorting the padded + // scores is equivalent to numerically sorting the scores. + score.toString().charAt(_) = "." and + result = score.toString() + or + not score.toString().charAt(_) = "." and + result = score.toString() + "." + ) + or + result = paddedScore(score, length - 1) + "0" and + length <= 12 + } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Return a string representing the score of the flow between `source` and `sink` in the + * boosted query. + * + * The returned string is a fixed length, such that lexically sorting the strings returned by + * this predicate gives the same sort order as numerically sorting the scores of the flows. + */ + pragma[inline] + string getScoreStringForFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(float score | + score = getScoreForFlow(source, sink) and + ( + // A length of 12 is equivalent to 10 decimal places. + score.toString().length() >= 12 and + result = score.toString().substring(0, 12) + or + score.toString().length() < 12 and + result = paddedScore(score, 12) + ) + ) + } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Indicates whether the flow from source to sink is likely to be reported by the base security + * query. + * + * Currently this is a heuristic: it ignores potential differences in the definitions of + * additional flow steps. + */ + pragma[inline] + predicate isFlowLikelyInBaseQuery(DataFlow::Node source, DataFlow::Node sink) { + getCfg().isKnownSource(source) and getCfg().isKnownSink(sink) + } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Get additional information about why ATM included the flow from source to sink as an alert. + */ + pragma[inline] + string getAdditionalAlertInfo(DataFlow::Node source, DataFlow::Node sink) { + exists(string sourceOrigins, string sinkOrigins | + sourceOrigins = concat(any(ScoringResults results).getASourceOrigin(source), ", ") and + sinkOrigins = concat(any(ScoringResults results).getASinkOrigin(sink), ", ") and + result = + "[Source origins: " + + any(string s | if sourceOrigins != "" then s = sourceOrigins else s = "unknown") + + "; sink origins: " + + any(string s | if sinkOrigins != "" then s = sinkOrigins else s = "unknown") + "]" + ) + } + } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/BaseScoring.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/BaseScoring.qll new file mode 100644 index 00000000000..8d02cc8948c --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/BaseScoring.qll @@ -0,0 +1,121 @@ +/* + * For internal use only. + * + * Provides shared scoring functionality for use in adaptive threat modeling (ATM). + */ + +private import javascript +private import ATMConfig + +external predicate adaptiveThreatModelingModels( + string modelChecksum, string modelLanguage, string modelName, string modelType +); + +/** Get the ATM configuration. */ +ATMConfig getCfg() { any() } + +/** + * This module provides functionality that takes an endpoint and provides an entity that encloses that + * endpoint and is suitable for similarity analysis. + */ +module EndpointToEntity { + private import CodeToFeatures + + /** + * Get an entity enclosing the endpoint that is suitable for similarity analysis. In general, + * this may associate multiple entities to a single endpoint. + */ + DatabaseFeatures::Entity getAnEntityForEndpoint(DataFlow::Node endpoint) { + DatabaseFeatures::entities(result, _, _, _, _, _, _, _, _) and + result.getDefinedFunction() = endpoint.getContainer().getEnclosingContainer*() + } +} + +/** + * This module provides functionality that takes an entity and provides effective endpoints within + * that entity. + * + * We use the following terminology to describe endpoints: + * + * - The *candidate* endpoints are the set of data flow nodes that should be passed to the + * appropriate endpoint filter to produce the set of effective endpoints. + * When we have a model that beats the performance of the baseline, we will likely define the + * candidate endpoints based on the most confident predictions of the model. + * - An *effective* endpoint is a candidate endpoint which passes through the endpoint filter. + * In other words, it is a candidate endpoint for which the `isEffectiveSink` (or + * `isEffectiveSource`) predicate defined in the `ATMConfig` instance in scope holds. + */ +module EntityToEffectiveEndpoint { + private import CodeToFeatures + + /** + * Returns endpoint candidates within the specified entities. + * + * The baseline implementation of this is that a candidate endpoint is any data flow node that is + * enclosed within the specified entity. + */ + private DataFlow::Node getABaselineEndpointCandidate(DatabaseFeatures::Entity entity) { + result.getContainer().getEnclosingContainer*() = entity.getDefinedFunction() + } + + /** + * Get an effective source enclosed by the specified entity. + * + * N.B. This is _not_ an inverse of `EndpointToEntity::getAnEntityForEndpoint`: the effective + * source may occur in a function defined within the specified entity. + */ + DataFlow::Node getAnEffectiveSource(DatabaseFeatures::Entity entity) { + result = getABaselineEndpointCandidate(entity) and + getCfg().isEffectiveSource(result) + } + + /** + * Get an effective sink enclosed by the specified entity. + * + * N.B. This is _not_ an inverse of `EndpointToEntity::getAnEntityForEndpoint`: the effective + * sink may occur in a function defined within the specified entity. + */ + DataFlow::Node getAnEffectiveSink(DatabaseFeatures::Entity entity) { + result = getABaselineEndpointCandidate(entity) and + getCfg().isEffectiveSink(result) + } +} + +/** + * Scoring information produced by a scoring model. + * + * Scoring models include embedding models and endpoint scoring models. + */ +abstract class ScoringResults extends string { + bindingset[this] + ScoringResults() { any() } + + /** + * Get ATM's confidence that a path between `source` and `sink` represents a security + * vulnerability. This will be a number between 0.0 and 1.0. + */ + abstract float getScoreForFlow(DataFlow::Node source, DataFlow::Node sink); + + /** + * Get a string representing why ATM included the given source in the dataflow analysis. + * + * In general, there may be multiple reasons why ATM included the given source, in which case + * this predicate should have multiple results. + */ + abstract string getASourceOrigin(DataFlow::Node source); + + /** + * Get a string representing why ATM included the given sink in the dataflow analysis. + * + * In general, there may be multiple reasons why ATM included the given sink, in which case this + * predicate should have multiple results. + */ + abstract string getASinkOrigin(DataFlow::Node sink); + + /** + * Indicates whether the flow from source to sink represents a result with + * sufficiently high likelihood of being a true-positive. + */ + pragma[inline] + abstract predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink); +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/CodeToFeatures.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/CodeToFeatures.qll new file mode 100644 index 00000000000..3619415606b --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/CodeToFeatures.qll @@ -0,0 +1,444 @@ +/* + * For internal use only. + * + * Extracts data about the functions in the database for use in adaptive threat modeling (ATM). + */ + +module Raw { + private import javascript as raw + + class RawAstNode = raw::ASTNode; + + class Entity = raw::Function; + + class Location = raw::Location; + + /** + * Exposed as a tool for defining anchors for semantic search. + */ + class UnderlyingFunction = raw::Function; + + /** + * Determines whether an entity should be omitted from ATM. + */ + predicate isEntityIgnored(Entity entity) { + // Ignore entities which don't have definitions, for example those in TypeScript + // declaration files. + not exists(entity.getBody()) + or + // Ignore entities with an empty body, for example the JavaScript function () => {}. + entity.getNumBodyStmt() = 0 and not exists(entity.getAReturnedExpr()) + } + + newtype WrappedAstNode = TAstNode(RawAstNode rawNode) + + /** + * This class represents nodes in the AST. + */ + class AstNode extends TAstNode { + RawAstNode rawNode; + + AstNode() { this = TAstNode(rawNode) } + + AstNode getAChildNode() { result = TAstNode(rawNode.getAChild()) } + + AstNode getParentNode() { result = TAstNode(rawNode.getParent()) } + + /** + * Holds if the AST node has `result` as its `index`th attribute. + * + * The index is not intended to mean anything, and is only here for disambiguation. + * There are no guarantees about any particular index being used (or not being used). + */ + string astNodeAttribute(int index) { + ( + // NB: Unary and binary operator expressions e.g. -a, a + b and compound + // assignments e.g. a += b can be identified by the expression type. + result = rawNode.(raw::Identifier).getName() + or + // Computed property accesses for which we can predetermine the property being accessed. + // NB: May alias with operators e.g. could have '+' as a property name. + result = rawNode.(raw::IndexExpr).getPropertyName() + or + // We use `getRawValue` to give us distinct representations for `0xa`, `0xA`, and `10`. + result = rawNode.(raw::NumberLiteral).getRawValue() + or + // We use `getValue` rather than `getRawValue` so we assign `"a"` and `'a'` the same representation. + not rawNode instanceof raw::NumberLiteral and + result = rawNode.(raw::Literal).getValue() + or + result = rawNode.(raw::TemplateElement).getRawValue() + ) and + index = 0 + } + + /** + * Returns a string indicating the "type" of the AST node. + */ + string astNodeType() { + // The definition of this method should correspond with that of the `@ast_node` entry in the + // dbscheme. + result = "js_exprs." + any(int kind | exprs(rawNode, kind, _, _, _)) + or + result = "js_properties." + any(int kind | properties(rawNode, _, _, kind, _)) + or + result = "js_stmts." + any(int kind | stmts(rawNode, kind, _, _, _)) + or + result = "js_toplevel" and rawNode instanceof raw::TopLevel + or + result = "js_typeexprs." + any(int kind | typeexprs(rawNode, kind, _, _, _)) + } + + /** + * Holds if `result` is the `index`'th child of the AST node, for some arbitrary indexing. + * A root of the AST should be its own child, with an arbitrary (though conventionally + * 0) index. + * + * Notably, the order in which child nodes are visited is not required to be meaningful, + * and no particular index is required to be meaningful. However, `(parent, index)` + * should be a keyset. + */ + pragma[nomagic] + AstNode astNodeChild(int index) { + result = + rank[index - 1](AstNode child, raw::Location l | + child = this.getAChildNode() and l = child.getLocation() + | + child + order by + l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn(), + child.astNodeType() + ) + or + not exists(result.getParentNode()) and this = result and index = 0 + } + + raw::Location getLocation() { result = rawNode.getLocation() } + + string toString() { result = rawNode.toString() } + + predicate isEntityNameNode(Entity entity) { + exists(int index | + TAstNode(entity) = getParentNode() and + this = getParentNode().astNodeChild(index) and + // An entity name node must be the first child of the entity. + index = min(int otherIndex | exists(getParentNode().astNodeChild(otherIndex))) and + entity.getName() = rawNode.(raw::VarDecl).getName() + ) + } + } + + /** + * Holds if `result` is the `index`'th child of the `parent` entity. Such + * a node is a root of an AST associated with this entity. + */ + AstNode entityChild(AstNode parent, int index) { + // In JavaScript, entities appear in the AST parent/child relationship. + result = parent.astNodeChild(index) + } + + /** + * Holds if `node` is contained in `entity`. Note that a single node may be contained + * in multiple entities, if they are nested. An entity, in particular, should be + * reported as contained within itself. + */ + predicate entityContains(Entity entity, AstNode node) { + node.getParentNode*() = TAstNode(entity) and not node.isEntityNameNode(entity) + } + + /** + * Get the name of the entity. + * + * We attempt to assign unnamed entities approximate names if they are passed to a likely + * external library function. If we can't assign them an approximate name, we give them the name + * `""`, so that these entities are included in `AdaptiveThreatModeling.qll`. + * + * For entities which have multiple names, we choose the lexically smallest name. + */ + string getEntityName(Entity entity) { + if exists(entity.getName()) + then + // https://github.com/github/ml-ql-adaptive-threat-modeling/issues/244 discusses making use + // of all the names during training. + result = min(entity.getName()) + else + if exists(getApproximateNameForEntity(entity)) + then result = getApproximateNameForEntity(entity) + else result = "" + } + + /** + * Holds if the call `call` has `entity` is its `argumentIndex`th argument. + */ + private predicate entityUsedAsArgumentToCall( + Entity entity, raw::DataFlow::CallNode call, int argumentIndex + ) { + raw::DataFlow::localFlowStep*(call.getArgument(argumentIndex), entity.flow()) + } + + /** + * Returns a generated name for the entity. This name is generated such that + * entities with the same names have similar behaviour. + */ + private string getApproximateNameForEntity(Entity entity) { + count(raw::DataFlow::CallNode call, int index | entityUsedAsArgumentToCall(entity, call, index)) = + 1 and + exists(raw::DataFlow::CallNode call, int index, string basePart | + entityUsedAsArgumentToCall(entity, call, index) and + ( + if count(getReceiverName(call)) = 1 + then basePart = getReceiverName(call) + "." + else basePart = "" + ) and + result = basePart + call.getCalleeName() + "#functionalargument" + ) + } + + private string getReceiverName(raw::DataFlow::CallNode call) { + result = call.getReceiver().asExpr().(raw::VarAccess).getName() + } + + /** Consistency checks: these predicates should each have no results */ + module Consistency { + /** `getEntityName` should assign each entity a single name. */ + query predicate entityWithManyNames(Entity entity, string name) { + name = getEntityName(entity) and + count(getEntityName(entity)) > 1 + } + + query predicate nodeWithNoType(AstNode node) { not exists(node.astNodeType()) } + + query predicate nodeWithManyTypes(AstNode node, string type) { + type = node.astNodeType() and + count(node.astNodeType()) > 1 + } + + query predicate nodeWithNoParent(AstNode node, string type) { + not node = any(AstNode parent).astNodeChild(_) and + type = node.astNodeType() and + not exists(RawAstNode rawNode | node = TAstNode(rawNode) and rawNode instanceof raw::Module) + } + + query predicate duplicateChildIndex(AstNode parent, int index, AstNode child) { + child = parent.astNodeChild(index) and + count(parent.astNodeChild(index)) > 1 + } + + query predicate duplicateAttributeIndex(AstNode node, int index) { + exists(node.astNodeAttribute(index)) and + count(node.astNodeAttribute(index)) > 1 + } + } +} + +module Wrapped { + /* + * We require any node with attributes to be a leaf. Where a non-leaf node + * has an attribute, we instead create a synthetic leaf node that has that + * attribute. + */ + + /** + * Holds if the AST node `e` is a leaf node. + */ + private predicate isLeaf(Raw::AstNode e) { not exists(e.astNodeChild(_)) } + + newtype WrappedEntity = + TEntity(Raw::Entity entity) { + exists(entity.getLocation().getFile().getRelativePath()) and + Raw::entityContains(entity, _) + } + + /** + * A type ranging over the kinds of entities for which we want to consider embeddings. + */ + class Entity extends WrappedEntity { + Raw::Entity rawEntity; + + Entity() { this = TEntity(rawEntity) and not Raw::isEntityIgnored(rawEntity) } + + string getName() { result = Raw::getEntityName(rawEntity) } + + AstNode getAstRoot(int index) { + result = TAstNode(rawEntity, Raw::entityChild(Raw::TAstNode(rawEntity), index)) + } + + string toString() { result = rawEntity.toString() } + + Raw::Location getLocation() { result = rawEntity.getLocation() } + + Raw::UnderlyingFunction getDefinedFunction() { result = rawEntity } + } + + newtype WrappedAstNode = + TAstNode(Raw::Entity enclosingEntity, Raw::AstNode node) { + Raw::entityContains(enclosingEntity, node) + } or + TSyntheticNode( + Raw::Entity enclosingEntity, Raw::AstNode node, int syntheticChildIndex, int attrIndex + ) { + Raw::entityContains(enclosingEntity, node) and + exists(node.astNodeAttribute(attrIndex)) and + not isLeaf(node) and + if exists(node.astNodeChild(_)) + then + syntheticChildIndex = + attrIndex - min(int other | exists(node.astNodeAttribute(other))) + + max(int other | exists(node.astNodeChild(other))) + 1 + else syntheticChildIndex = attrIndex + } + + pragma[nomagic] + private AstNode injectedChild(Raw::Entity enclosingEntity, Raw::AstNode parent, int index) { + result = TAstNode(enclosingEntity, parent.astNodeChild(index)) or + result = TSyntheticNode(enclosingEntity, parent, index, _) + } + + /** + * A type ranging over AST nodes. Ultimately, only nodes contained in entities will + * be considered. + */ + class AstNode extends WrappedAstNode { + Raw::Entity enclosingEntity; + Raw::AstNode rawNode; + + AstNode() { + ( + this = TAstNode(enclosingEntity, rawNode) or + this = TSyntheticNode(enclosingEntity, rawNode, _, _) + ) and + not Raw::isEntityIgnored(enclosingEntity) + } + + string getAttribute(int index) { + result = rawNode.astNodeAttribute(index) and + not exists(TSyntheticNode(enclosingEntity, rawNode, _, index)) + } + + string getType() { result = rawNode.astNodeType() } + + AstNode getChild(int index) { result = injectedChild(enclosingEntity, rawNode, index) } + + string toString() { result = getType() } + + Raw::Location getLocation() { result = rawNode.getLocation() } + } + + /** + * A synthetic AST node, created to be a leaf for an otherwise non-leaf attribute. + */ + class SyntheticAstNode extends AstNode, TSyntheticNode { + int childIndex; + int attributeIndex; + + SyntheticAstNode() { + this = TSyntheticNode(enclosingEntity, rawNode, childIndex, attributeIndex) + } + + override string getAttribute(int index) { + result = rawNode.astNodeAttribute(attributeIndex) and index = attributeIndex + } + + override string getType() { + result = rawNode.astNodeType() + "::<synthetic " + childIndex + ">" + } + + override AstNode getChild(int index) { none() } + } +} + +module DatabaseFeatures { + /** + * Exposed as a tool for defining anchors for semantic search. + */ + class UnderlyingFunction = Raw::UnderlyingFunction; + + private class Location = Raw::Location; + + private newtype TEntityOrAstNode = + TEntity(Wrapped::Entity entity) or + TAstNode(Wrapped::AstNode astNode) + + class EntityOrAstNode extends TEntityOrAstNode { + abstract string getType(); + + abstract string toString(); + + abstract Location getLocation(); + } + + class Entity extends EntityOrAstNode, TEntity { + Wrapped::Entity entity; + + Entity() { this = TEntity(entity) } + + string getName() { result = entity.getName() } + + AstNode getAstRoot(int index) { result = TAstNode(entity.getAstRoot(index)) } + + override string getType() { result = "javascript function" } + + override string toString() { result = "Entity: " + getName() } + + override Location getLocation() { result = entity.getLocation() } + + UnderlyingFunction getDefinedFunction() { result = entity.getDefinedFunction() } + } + + class AstNode extends EntityOrAstNode, TAstNode { + Wrapped::AstNode rawNode; + + AstNode() { this = TAstNode(rawNode) } + + AstNode getChild(int index) { result = TAstNode(rawNode.getChild(index)) } + + string getAttribute(int index) { result = rawNode.getAttribute(index) } + + override string getType() { result = rawNode.getType() } + + override string toString() { result = this.getType() } + + override Location getLocation() { result = rawNode.getLocation() } + } + + /** Consistency checks: these predicates should each have no results */ + module Consistency { + query predicate nonLeafAttribute(AstNode node, int index, string attribute) { + attribute = node.getAttribute(index) and + exists(node.getChild(_)) + } + } + + query predicate entities( + Entity entity, string entity_name, string entity_type, string path, int startLine, + int startColumn, int endLine, int endColumn, string absolutePath + ) { + entity_name = entity.getName() and + entity_type = entity.getType() and + exists(Location l | l = entity.getLocation() | + path = l.getFile().getRelativePath() and + absolutePath = l.getFile().getAbsolutePath() and + l.hasLocationInfo(_, startLine, startColumn, endLine, endColumn) + ) + } + + query predicate astNodes( + Entity enclosingEntity, EntityOrAstNode parent, int index, AstNode node, string node_type + ) { + node = enclosingEntity.getAstRoot(index) and + parent = enclosingEntity and + node_type = node.getType() + or + astNodes(enclosingEntity, _, _, parent, _) and + node = parent.(AstNode).getChild(index) and + node_type = node.getType() + } + + query predicate nodeAttributes(AstNode node, string attr) { + // Only get attributes of AST nodes we extract. + // This excludes nodes in standard libraries since the standard library files + // are located outside the source root. + astNodes(_, _, _, node, _) and + attr = node.getAttribute(_) + } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/CoreKnowledge.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/CoreKnowledge.qll new file mode 100644 index 00000000000..29494c16855 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/CoreKnowledge.qll @@ -0,0 +1,208 @@ +/* + * For internal use only. + * + * Provides predicates that expose the knowledge of models + * in the core CodeQL JavaScript libraries. + */ + +private import javascript +private import semmle.javascript.security.dataflow.XxeCustomizations +private import semmle.javascript.security.dataflow.RemotePropertyInjectionCustomizations +private import semmle.javascript.security.dataflow.TypeConfusionThroughParameterTamperingCustomizations +private import semmle.javascript.security.dataflow.ZipSlipCustomizations +private import semmle.javascript.security.dataflow.TaintedPathCustomizations +private import semmle.javascript.security.dataflow.CleartextLoggingCustomizations +private import semmle.javascript.security.dataflow.XpathInjectionCustomizations +private import semmle.javascript.security.dataflow.Xss::Shared as Xss +private import semmle.javascript.security.dataflow.StackTraceExposureCustomizations +private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomizations +private import semmle.javascript.security.dataflow.CodeInjectionCustomizations +private import semmle.javascript.security.dataflow.RequestForgeryCustomizations +private import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentialsCustomizations +private import semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironmentCustomizations +private import semmle.javascript.security.dataflow.DifferentKindsComparisonBypassCustomizations +private import semmle.javascript.security.dataflow.CommandInjectionCustomizations +private import semmle.javascript.security.dataflow.PrototypePollutionCustomizations +private import semmle.javascript.security.dataflow.UnvalidatedDynamicMethodCallCustomizations +private import semmle.javascript.security.dataflow.TaintedFormatStringCustomizations +private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations +private import semmle.javascript.security.dataflow.PostMessageStarCustomizations +private import semmle.javascript.security.dataflow.RegExpInjectionCustomizations +private import semmle.javascript.security.dataflow.SqlInjectionCustomizations +private import semmle.javascript.security.dataflow.InsecureRandomnessCustomizations +private import semmle.javascript.security.dataflow.XmlBombCustomizations +private import semmle.javascript.security.dataflow.InsufficientPasswordHashCustomizations +private import semmle.javascript.security.dataflow.HardcodedCredentialsCustomizations +private import semmle.javascript.security.dataflow.FileAccessToHttpCustomizations +private import semmle.javascript.security.dataflow.UnsafeDynamicMethodAccessCustomizations +private import semmle.javascript.security.dataflow.UnsafeDeserializationCustomizations +private import semmle.javascript.security.dataflow.HardcodedDataInterpretedAsCodeCustomizations +private import semmle.javascript.security.dataflow.ServerSideUrlRedirectCustomizations +private import semmle.javascript.security.dataflow.IndirectCommandInjectionCustomizations +private import semmle.javascript.security.dataflow.ConditionalBypassCustomizations +private import semmle.javascript.security.dataflow.HttpToFileAccessCustomizations +private import semmle.javascript.security.dataflow.BrokenCryptoAlgorithmCustomizations +private import semmle.javascript.security.dataflow.LoopBoundInjectionCustomizations +private import semmle.javascript.security.dataflow.CleartextStorageCustomizations +import FilteringReasons + +/** + * Holds if the node `n` is a known sink in a modeled library, or a sibling-argument of such a sink. + */ +predicate isArgumentToKnownLibrarySinkFunction(DataFlow::Node n) { + exists(DataFlow::InvokeNode invk, DataFlow::Node known | + invk.getAnArgument() = n and invk.getAnArgument() = known and isKnownLibrarySink(known) + ) +} + +/** + * Holds if the node `n` is a known sink for the external API security query. + * + * This corresponds to known sinks from security queries whose sources include remote flow and + * DOM-based sources. + */ +predicate isKnownExternalAPIQuerySink(DataFlow::Node n) { + n instanceof Xxe::Sink or + n instanceof TaintedPath::Sink or + n instanceof XpathInjection::Sink or + n instanceof Xss::Sink or + n instanceof ClientSideUrlRedirect::Sink or + n instanceof CodeInjection::Sink or + n instanceof RequestForgery::Sink or + n instanceof CorsMisconfigurationForCredentials::Sink or + n instanceof CommandInjection::Sink or + n instanceof PrototypePollution::Sink or + n instanceof UnvalidatedDynamicMethodCall::Sink or + n instanceof TaintedFormatString::Sink or + n instanceof NosqlInjection::Sink or + n instanceof PostMessageStar::Sink or + n instanceof RegExpInjection::Sink or + n instanceof SqlInjection::Sink or + n instanceof XmlBomb::Sink or + n instanceof ZipSlip::Sink or + n instanceof UnsafeDeserialization::Sink or + n instanceof ServerSideUrlRedirect::Sink or + n instanceof CleartextStorage::Sink or + n instanceof HttpToFileAccess::Sink +} + +/** + * Holds if the node `n` is a known sink in a modeled library. + */ +predicate isKnownLibrarySink(DataFlow::Node n) { + isKnownExternalAPIQuerySink(n) or + n instanceof CleartextLogging::Sink or + n instanceof StackTraceExposure::Sink or + n instanceof ShellCommandInjectionFromEnvironment::Sink or + n instanceof InsecureRandomness::Sink or + n instanceof FileAccessToHttp::Sink or + n instanceof IndirectCommandInjection::Sink +} + +/** + * Holds if the node `n` is known as the predecessor in a modeled flow step. + */ +predicate isKnownStepSrc(DataFlow::Node n) { + any(TaintTracking::AdditionalTaintStep s).step(n, _) or + any(DataFlow::AdditionalFlowStep s).step(n, _) or + any(DataFlow::AdditionalFlowStep s).step(n, _, _, _) +} + +/** + * Holds if `n` is an argument to a function of a builtin object. + */ +private predicate isArgumentToBuiltinFunction(DataFlow::Node n, FilteringReason reason) { + exists(DataFlow::SourceNode builtin, DataFlow::SourceNode receiver, DataFlow::InvokeNode invk | + ( + builtin instanceof DataFlow::ArrayCreationNode and + reason instanceof ArgumentToArrayReason + or + builtin = + DataFlow::globalVarRef([ + "Map", "Set", "WeakMap", "WeakSet", "Number", "Object", "String", "Array", "Error", + "Math", "Boolean" + ]) and + reason instanceof ArgumentToBuiltinGlobalVarRefReason + ) + | + receiver = [builtin.getAnInvocation(), builtin] and + invk = [receiver, receiver.getAPropertyRead()].getAnInvocation() and + invk.getAnArgument() = n + ) + or + exists(Expr primitive, MethodCallExpr c | + primitive instanceof ConstantString or + primitive instanceof NumberLiteral or + primitive instanceof BooleanLiteral + | + c.calls(primitive, _) and + c.getAnArgument() = n.asExpr() and + reason instanceof ConstantReceiverReason + ) + or + exists(DataFlow::CallNode call | + call.getAnArgument() = n and + call.getCalleeName() = + [ + "indexOf", "hasOwnProperty", "substring", "isDecimal", "decode", "encode", "keys", "shift", + "values", "forEach", "toString", "slice", "splice", "push", "isArray", "sort" + ] and + reason instanceof BuiltinCallNameReason + ) +} + +predicate isOtherModeledArgument(DataFlow::Node n, FilteringReason reason) { + isArgumentToBuiltinFunction(n, reason) + or + any(LodashUnderscore::Member m).getACall().getAnArgument() = n and + reason instanceof LodashUnderscoreArgumentReason + or + exists(ClientRequest r | + r.getAnArgument() = n or n = r.getUrl() or n = r.getHost() or n = r.getADataNode() + ) and + reason instanceof ClientRequestReason + or + exists(PromiseDefinition p | + n = [p.getResolveParameter(), p.getRejectParameter()].getACall().getAnArgument() + ) and + reason instanceof PromiseDefinitionReason + or + n instanceof CryptographicKey and reason instanceof CryptographicKeyReason + or + any(CryptographicOperation op).getInput().flow() = n and + reason instanceof CryptographicOperationFlowReason + or + exists(DataFlow::CallNode call | n = call.getAnArgument() | + call.getCalleeName() = getAStandardLoggerMethodName() and + reason instanceof LoggerMethodReason + or + call.getCalleeName() = ["setTimeout", "clearTimeout"] and + reason instanceof TimeoutReason + or + call.getReceiver() = DataFlow::globalVarRef(["localStorage", "sessionStorage"]) and + reason instanceof ReceiverStorageReason + or + call instanceof StringOps::StartsWith and reason instanceof StringStartsWithReason + or + call instanceof StringOps::EndsWith and reason instanceof StringEndsWithReason + or + call instanceof StringOps::RegExpTest and reason instanceof StringRegExpTestReason + or + call instanceof EventRegistration and reason instanceof EventRegistrationReason + or + call instanceof EventDispatch and reason instanceof EventDispatchReason + or + call = any(MembershipCandidate c).getTest() and + reason instanceof MembershipCandidateTestReason + or + call instanceof FileSystemAccess and reason instanceof FileSystemAccessReason + or + call instanceof DatabaseAccess and reason instanceof DatabaseAccessReason + or + call = DOM::domValueRef() and reason instanceof DOMReason + or + call.getCalleeName() = "next" and + exists(DataFlow::FunctionNode f | call = f.getLastParameter().getACall()) and + reason instanceof NextFunctionCallReason + ) +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll new file mode 100644 index 00000000000..85ca174ca4e --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll @@ -0,0 +1,290 @@ +/* + * For internal use only. + * + * Extracts data about the database for use in adaptive threat modeling (ATM). + */ + +import javascript +import CodeToFeatures +import EndpointScoring + +/** + * Gets the value of the token-based feature named `featureName` for the endpoint `endpoint`. + * + * This is a single string containing a space-separated list of tokens. + */ +private string getTokenFeature(DataFlow::Node endpoint, string featureName) { + // Features for endpoints that are contained within a function. + exists(DatabaseFeatures::Entity entity | entity = getRepresentativeEntityForEndpoint(endpoint) | + // The name of the function that encloses the endpoint. + featureName = "enclosingFunctionName" and result = entity.getName() + or + // A feature containing natural language tokens from the function that encloses the endpoint in + // the order that they appear in the source code. + featureName = "enclosingFunctionBody" and + result = unique(string x | x = FunctionBodies::getBodyTokenFeatureForEntity(entity)) + ) + or + exists(getACallBasedTokenFeatureComponent(endpoint, _, featureName)) and + result = + concat(DataFlow::CallNode call, string component | + component = getACallBasedTokenFeatureComponent(endpoint, call, featureName) + | + component, " " + ) + or + // The access path of the function being called, both with and without structural info, if the + // function being called originates from an external API. For example, the endpoint here: + // + // ```js + // const mongoose = require('mongoose'), + // User = mongoose.model('User', null); + // User.findOne(ENDPOINT); + // ``` + // + // would have a callee access path with structural info of + // `mongoose member model instanceorreturn member findOne instanceorreturn`, and a callee access + // path without structural info of `mongoose model findOne`. + // + // These features indicate that the callee comes from (reading the access path backwards) an + // instance of the `findOne` member of an instance of the `model` member of the `mongoose` + // external library. + exists(AccessPaths::Boolean includeStructuralInfo | + featureName = + "calleeAccessPath" + + any(string x | if includeStructuralInfo = true then x = "WithStructuralInfo" else x = "") and + result = + concat(API::Node node, string accessPath | + node.getInducingNode().(DataFlow::CallNode).getAnArgument() = endpoint and + accessPath = AccessPaths::getAccessPath(node, includeStructuralInfo) + | + accessPath, " " + ) + ) +} + +/** + * Gets a value of the function-call-related token-based feature named `featureName` associated + * with the function call `call` and the endpoint `endpoint`. + * + * This may in general report multiple strings, each containing a space-separated list of tokens. + * + * **Technical details:** This predicate can have multiple values per endpoint and feature name. As a + * result, the results from this predicate must be concatenated together. However concatenating + * other features like the function body tokens is expensive, so we separate out this predicate + * from others like `FunctionBodies::getBodyTokenFeatureForEntity` to avoid having to perform this + * concatenation operation on other features like the function body tokens. + */ +private string getACallBasedTokenFeatureComponent( + DataFlow::Node endpoint, DataFlow::CallNode call, string featureName +) { + // Features for endpoints that are an argument to a function call. + endpoint = call.getAnArgument() and + ( + // The name of the function being called, e.g. in a call `Artist.findOne(...)`, this is `findOne`. + featureName = "calleeName" and result = call.getCalleeName() + or + // The name of the receiver of the call, e.g. in a call `Artist.findOne(...)`, this is `Artist`. + featureName = "receiverName" and result = call.getReceiver().asExpr().(VarRef).getName() + or + // The argument index of the endpoint, e.g. in `f(a, endpoint, b)`, this is 1. + featureName = "argumentIndex" and + result = any(int argIndex | call.getArgument(argIndex) = endpoint).toString() + or + // The name of the API that the function being called originates from, if the function being + // called originates from an external API. For example, the endpoint here: + // + // ```js + // const mongoose = require('mongoose'), + // User = mongoose.model('User', null); + // User.findOne(ENDPOINT); + // ``` + // + // would have a callee API name of `mongoose`. + featureName = "calleeApiName" and + result = getAnApiName(call) + ) +} + +/** This module provides functionality for getting the function body feature associated with a particular entity. */ +module FunctionBodies { + /** Holds if `node` is an AST node within the entity `entity` and `token` is a node attribute associated with `node`. */ + private predicate bodyTokens( + DatabaseFeatures::Entity entity, DatabaseFeatures::AstNode node, string token + ) { + DatabaseFeatures::astNodes(entity, _, _, node, _) and + token = unique(string t | DatabaseFeatures::nodeAttributes(node, t)) + } + + /** + * Gets the body token feature for the specified entity. + * + * This is a string containing natural language tokens in the order that they appear in the source code for the entity. + */ + string getBodyTokenFeatureForEntity(DatabaseFeatures::Entity entity) { + // If a function has more than 256 body subtokens, then featurize it as absent. This + // approximates the behavior of the classifer on non-generic body features where large body + // features are replaced by the absent token. + if count(DatabaseFeatures::AstNode node, string token | bodyTokens(entity, node, token)) > 256 + then result = "" + else + result = + concat(int i, string rankedToken | + rankedToken = + rank[i](DatabaseFeatures::AstNode node, string token, Location l | + bodyTokens(entity, node, token) and l = node.getLocation() + | + token + order by + l.getFile().getAbsolutePath(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), + l.getEndColumn(), token + ) + | + rankedToken, " " order by i + ) + } +} + +/** + * Returns a name of the API that a node originates from, if the node originates from an API. + * + * This predicate may have multiple results if the node corresponds to multiple nodes in the API graph forest. + */ +pragma[inline] +private string getAnApiName(DataFlow::Node node) { + API::moduleImport(result).getASuccessor*().getInducingNode() = node +} + +/** + * This module provides functionality for getting a representation of the access path of nodes + * within the program. + * + * For example, it gives the `User.find` callee here: + * + * ```js + * const mongoose = require('mongoose'), + * User = mongoose.model('User', null); + * User.find({ 'isAdmin': true }) + * ``` + * the access path `mongoose member model instanceorreturn member find instanceorreturn`. + * + * This access path is based on the simplified access path that the untrusted data flowing to + * external API query associates to each of its sinks, with modifications to optionally include + * explicit structural information and to improve how well the path tokenizes. + */ +private module AccessPaths { + bindingset[str] + private predicate isNumericString(string str) { exists(str.toInt()) } + + /** + * Gets a parameter of `base` with name `name`, or a property named `name` of a destructuring parameter. + */ + private API::Node getNamedParameter(API::Node base, string name) { + exists(API::Node param | + param = base.getAParameter() and + not param = base.getReceiver() + | + result = param and + name = param.getAnImmediateUse().asExpr().(Parameter).getName() + or + param.getAnImmediateUse().asExpr() instanceof DestructuringPattern and + result = param.getMember(name) + ) + } + + /** + * A utility class that is equivalent to `boolean` but does not require type joining. + */ + class Boolean extends boolean { + Boolean() { this = true or this = false } + } + + /** Get the access path for the node. This includes structural information like `member`, `param`, and `functionalarg` if `includeStructuralInfo` is true. */ + string getAccessPath(API::Node node, Boolean includeStructuralInfo) { + node = API::moduleImport(result) + or + exists(API::Node base, string baseName | + base.getDepth() < node.getDepth() and baseName = getAccessPath(base, includeStructuralInfo) + | + // e.g. `new X`, `X()` + node = [base.getInstance(), base.getReturn()] and + if includeStructuralInfo = true + then result = baseName + " instanceorreturn" + else result = baseName + or + // e.g. `x.y`, `x[y]`, `const { y } = x`, where `y` is non-numeric and is known at analysis + // time. + exists(string member | + node = base.getMember(member) and + not node = base.getUnknownMember() and + not isNumericString(member) and + not (member = "default" and base = API::moduleImport(_)) and + not member = "then" // use the 'promised' edges for .then callbacks + | + if includeStructuralInfo = true + then result = baseName + " member " + member + else result = baseName + " " + member + ) + or + // e.g. `x.y`, `x[y]`, `const { y } = x`, where `y` is numeric or not known at analysis time. + ( + node = base.getUnknownMember() or + node = base.getMember(any(string s | isNumericString(s))) + ) and + if includeStructuralInfo = true then result = baseName + " member" else result = baseName + or + // e.g. `x.then(y => ...)` + node = base.getPromised() and + result = baseName + or + // e.g. `x.y((a, b) => ...)` + // Name callback parameters after their name in the source code. + // For example, the `res` parameter in `express.get('/foo', (req, res) => {...})` will be + // named `express member get functionalarg param res`. + exists(string paramName | + node = getNamedParameter(base.getAParameter(), paramName) and + ( + if includeStructuralInfo = true + then result = baseName + " functionalarg param " + paramName + else result = baseName + " " + paramName + ) + or + exists(string callbackName, string index | + node = + getNamedParameter(base.getASuccessor("param " + index).getMember(callbackName), + paramName) and + index != "-1" and // ignore receiver + if includeStructuralInfo = true + then + result = + baseName + " functionalarg " + index + " " + callbackName + " param " + paramName + else result = baseName + " " + index + " " + callbackName + " " + paramName + ) + ) + ) + } +} + +/** Get a name of a supported generic token-based feature. */ +private string getASupportedFeatureName() { + result = + [ + "enclosingFunctionName", "calleeName", "receiverName", "argumentIndex", "calleeApiName", + "calleeAccessPath", "calleeAccessPathWithStructuralInfo", "enclosingFunctionBody" + ] +} + +/** + * Generic token-based features for ATM. + * + * This predicate holds if the generic token-based feature named `featureName` has the value + * `featureValue` for the endpoint `endpoint`. + */ +predicate tokenFeatures(DataFlow::Node endpoint, string featureName, string featureValue) { + featureName = getASupportedFeatureName() and + ( + featureValue = unique(string x | x = getTokenFeature(endpoint, featureName)) + or + not exists(unique(string x | x = getTokenFeature(endpoint, featureName))) and featureValue = "" + ) +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointScoring.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointScoring.qll new file mode 100644 index 00000000000..8efe184e10e --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointScoring.qll @@ -0,0 +1,223 @@ +/* + * For internal use only. + * + * Provides an implementation of scoring alerts for use in adaptive threat modeling (ATM). + */ + +private import javascript +import BaseScoring +import CodeToFeatures +import EndpointFeatures as EndpointFeatures +import EndpointTypes + +private string getACompatibleModelChecksum() { + adaptiveThreatModelingModels(result, "javascript", _, "atm-endpoint-scoring") +} + +/** + * The maximum number of AST nodes an entity containing an endpoint should have before we should + * choose a smaller entity to represent the endpoint. + * + * This is intended to represent a balance in terms of the amount of context we provide to the + * model: we don't want the function to be too small, because then it doesn't contain very much + * context and miss useful information, but also we don't want it to be too large, because then + * there's likely to be a lot of irrelevant or very loosely related context. + */ +private int getMaxNumAstNodes() { result = 1024 } + +/** + * Returns the number of AST nodes contained within the specified entity. + */ +private int getNumAstNodesInEntity(DatabaseFeatures::Entity entity) { + // Restrict the values `entity` can take on + entity = EndpointToEntity::getAnEntityForEndpoint(_) and + result = + count(DatabaseFeatures::AstNode astNode | DatabaseFeatures::astNodes(entity, _, _, astNode, _)) +} + +/** + * Get a single entity to use as the representative entity for the endpoint. + * + * We try to use the largest entity containing the endpoint that's below the AST node limit defined + * in `getMaxNumAstNodes`. In the event of a tie, we use the entity that appears first within the + * source archive. + * + * If no entities are smaller than the AST node limit, then we use the smallest entity containing + * the endpoint. + */ +DatabaseFeatures::Entity getRepresentativeEntityForEndpoint(DataFlow::Node endpoint) { + // Check whether there's an entity containing the endpoint that's smaller than the AST node limit. + if + getNumAstNodesInEntity(EndpointToEntity::getAnEntityForEndpoint(endpoint)) <= + getMaxNumAstNodes() + then + // Use the largest entity smaller than the AST node limit, resolving ties using the entity that + // appears first in the source archive. + result = + rank[1](DatabaseFeatures::Entity entity, int numAstNodes, Location l | + entity = EndpointToEntity::getAnEntityForEndpoint(endpoint) and + numAstNodes = getNumAstNodesInEntity(entity) and + numAstNodes <= getMaxNumAstNodes() and + l = entity.getLocation() + | + entity + order by + numAstNodes desc, l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() + ) + else + // Use the smallest entity, resolving ties using the entity that + // appears first in the source archive. + result = + rank[1](DatabaseFeatures::Entity entity, int numAstNodes, Location l | + entity = EndpointToEntity::getAnEntityForEndpoint(endpoint) and + numAstNodes = getNumAstNodesInEntity(entity) and + l = entity.getLocation() + | + entity + order by + numAstNodes, l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() + ) +} + +module ModelScoring { + predicate endpoints(DataFlow::Node endpoint) { + getCfg().isEffectiveSource(endpoint) or + getCfg().isEffectiveSink(endpoint) + } + + private int requestedEndpointTypes() { result = any(EndpointType type).getEncoding() } + + private predicate relevantTokenFeatures( + DataFlow::Node endpoint, string featureName, string featureValue + ) { + endpoints(endpoint) and + EndpointFeatures::tokenFeatures(endpoint, featureName, featureValue) + } + + predicate endpointScores(DataFlow::Node endpoint, int encodedEndpointType, float score) = + scoreEndpoints(endpoints/1, requestedEndpointTypes/0, relevantTokenFeatures/3, + getACompatibleModelChecksum/0)(endpoint, encodedEndpointType, score) +} + +/** + * Return ATM's confidence that `source` is a source for the given security query. This will be a + * number between 0.0 and 1.0. + */ +private float getScoreForSource(DataFlow::Node source) { + if getCfg().isKnownSource(source) + then result = 1.0 + else ( + // This restriction on `source` has no semantic effect but improves performance. + getCfg().isEffectiveSource(source) and + ModelScoring::endpointScores(source, getCfg().getASourceEndpointType().getEncoding(), result) + ) +} + +/** + * Return ATM's confidence that `sink` is a sink for the given security query. This will be a + * number between 0.0 and 1.0. + */ +private float getScoreForSink(DataFlow::Node sink) { + if getCfg().isKnownSink(sink) + then result = 1.0 + else + if getCfg().isEffectiveSinkWithOverridingScore(sink, result, _) + then any() + else ( + // This restriction on `sink` has no semantic effect but improves performance. + getCfg().isEffectiveSink(sink) and + ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(), result) + ) +} + +class EndpointScoringResults extends ScoringResults { + EndpointScoringResults() { + this = "EndpointScoringResults" and exists(getACompatibleModelChecksum()) + } + + /** + * Get ATM's confidence that a path between `source` and `sink` represents a security + * vulnerability. This will be a number between 0.0 and 1.0. + */ + override float getScoreForFlow(DataFlow::Node source, DataFlow::Node sink) { + result = getScoreForSource(source) * getScoreForSink(sink) + } + + /** + * Get a string representing why ATM included the given source in the dataflow analysis. + * + * In general, there may be multiple reasons why ATM included the given source, in which case + * this predicate should have multiple results. + */ + pragma[inline] + override string getASourceOrigin(DataFlow::Node source) { + result = "known" and getCfg().isKnownSource(source) + or + result = "predicted" and getCfg().isEffectiveSource(source) + } + + /** + * Get a string representing why ATM included the given sink in the dataflow analysis. + * + * In general, there may be multiple reasons why ATM included the given sink, in which case + * this predicate should have multiple results. + */ + pragma[inline] + override string getASinkOrigin(DataFlow::Node sink) { + result = "known" and getCfg().isKnownSink(sink) + or + not getCfg().isKnownSink(sink) and + getCfg().isEffectiveSinkWithOverridingScore(sink, _, result) + or + not getCfg().isKnownSink(sink) and + not getCfg().isEffectiveSinkWithOverridingScore(sink, _, _) and + result = + "predicted (scores: " + + concat(EndpointType type, float score | + ModelScoring::endpointScores(sink, type.getEncoding(), score) + | + type.getDescription() + "=" + score.toString(), ", " order by type.getEncoding() + ) + ")" and + getCfg().isEffectiveSink(sink) + } + + pragma[inline] + override predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) { + if getCfg().isKnownSink(sink) + then any() + else + if getCfg().isEffectiveSinkWithOverridingScore(sink, _, _) + then + exists(float score | + getCfg().isEffectiveSinkWithOverridingScore(sink, score, _) and + score >= getCfg().getScoreCutoff() + ) + else ( + // This restriction on `sink` has no semantic effect but improves performance. + getCfg().isEffectiveSink(sink) and + exists(float sinkScore | + ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(), + sinkScore) and + // Include the endpoint if (a) the query endpoint type scores higher than all other + // endpoint types, or (b) the query endpoint type scores at least + // 0.5 - (getCfg().getScoreCutoff() / 2). + sinkScore >= + [ + max(float s | ModelScoring::endpointScores(sink, _, s)), + 0.5 - getCfg().getScoreCutoff() / 2 + ] + ) + ) + } +} + +module Debugging { + query predicate hopInputEndpoints = ModelScoring::endpoints/1; + + query predicate endpointScores = ModelScoring::endpointScores/3; + + query predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) { + any(ScoringResults scoringResults).shouldResultBeIncluded(source, sink) and + any(DataFlow::Configuration cfg).hasFlow(source, sink) + } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointTypes.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointTypes.qll new file mode 100644 index 00000000000..4f4bc2782ab --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointTypes.qll @@ -0,0 +1,57 @@ +/** + * For internal use only. + * + * Defines the set of classes that endpoint scoring models can predict. Endpoint scoring models must + * only predict classes defined within this file. This file is the source of truth for the integer + * representation of each of these classes. + */ +newtype TEndpointType = + TNotASinkType() or + TXssSinkType() or + TNosqlInjectionSinkType() or + TSqlInjectionSinkType() or + TTaintedPathSinkType() + +/** A class that can be predicted by endpoint scoring models. */ +abstract class EndpointType extends TEndpointType { + abstract string getDescription(); + + abstract int getEncoding(); + + string toString() { result = getDescription() } +} + +/** The `NotASink` class that can be predicted by endpoint scoring models. */ +class NotASinkType extends EndpointType, TNotASinkType { + override string getDescription() { result = "NotASink" } + + override int getEncoding() { result = 0 } +} + +/** The `XssSink` class that can be predicted by endpoint scoring models. */ +class XssSinkType extends EndpointType, TXssSinkType { + override string getDescription() { result = "XssSink" } + + override int getEncoding() { result = 1 } +} + +/** The `NosqlInjectionSink` class that can be predicted by endpoint scoring models. */ +class NosqlInjectionSinkType extends EndpointType, TNosqlInjectionSinkType { + override string getDescription() { result = "NosqlInjectionSink" } + + override int getEncoding() { result = 2 } +} + +/** The `SqlInjectionSink` class that can be predicted by endpoint scoring models. */ +class SqlInjectionSinkType extends EndpointType, TSqlInjectionSinkType { + override string getDescription() { result = "SqlInjectionSink" } + + override int getEncoding() { result = 3 } +} + +/** The `TaintedPathSink` class that can be predicted by endpoint scoring models. */ +class TaintedPathSinkType extends EndpointType, TTaintedPathSinkType { + override string getDescription() { result = "TaintedPathSink" } + + override int getEncoding() { result = 4 } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/FilteringReasons.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/FilteringReasons.qll new file mode 100644 index 00000000000..c046fbd12ef --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/FilteringReasons.qll @@ -0,0 +1,196 @@ +/** + * For internal use only. + * + * Defines a set of reasons why a particular endpoint was filtered out. This set of reasons + * contains both reasons why an endpoint could be `NotASink` and reasons why an endpoint could be + * `LikelyNotASink`. The `NotASinkReason`s defined here are exhaustive, but the + * `LikelyNotASinkReason`s are not exhaustive. + */ +newtype TFilteringReason = + TIsArgumentToBuiltinFunctionReason() or + TLodashUnderscoreArgumentReason() or + TClientRequestReason() or + TPromiseDefinitionReason() or + TCryptographicKeyReason() or + TCryptographicOperationFlowReason() or + TLoggerMethodReason() or + TTimeoutReason() or + TReceiverStorageReason() or + TStringStartsWithReason() or + TStringEndsWithReason() or + TStringRegExpTestReason() or + TEventRegistrationReason() or + TEventDispatchReason() or + TMembershipCandidateTestReason() or + TFileSystemAccessReason() or + TDatabaseAccessReason() or + TDOMReason() or + TNextFunctionCallReason() or + TArgumentToArrayReason() or + TArgumentToBuiltinGlobalVarRefReason() or + TConstantReceiverReason() or + TBuiltinCallNameReason() + +/** A reason why a particular endpoint was filtered out by the endpoint filters. */ +abstract class FilteringReason extends TFilteringReason { + abstract string getDescription(); + + abstract int getEncoding(); + + string toString() { result = getDescription() } +} + +/** + * A reason why a particular endpoint might be considered to be `NotASink`. + * + * An endpoint is `NotASink` if it has at least one `NotASinkReason`, it does not have any + * `LikelyNotASinkReason`s, and it is not a known sink. + */ +abstract class NotASinkReason extends FilteringReason { } + +/** + * A reason why a particular endpoint might be considered to be `LikelyNotASink`. + * + * An endpoint is `LikelyNotASink` if it has at least one `LikelyNotASinkReason` and it is not a + * known sink. + */ +abstract class LikelyNotASinkReason extends FilteringReason { } + +class IsArgumentToBuiltinFunctionReason extends NotASinkReason, TIsArgumentToBuiltinFunctionReason { + override string getDescription() { result = "IsArgumentToBuiltinFunction" } + + override int getEncoding() { result = 5 } +} + +class LodashUnderscoreArgumentReason extends NotASinkReason, TLodashUnderscoreArgumentReason { + override string getDescription() { result = "LodashUnderscoreArgument" } + + override int getEncoding() { result = 6 } +} + +class ClientRequestReason extends NotASinkReason, TClientRequestReason { + override string getDescription() { result = "ClientRequest" } + + override int getEncoding() { result = 7 } +} + +class PromiseDefinitionReason extends NotASinkReason, TPromiseDefinitionReason { + override string getDescription() { result = "PromiseDefinition" } + + override int getEncoding() { result = 8 } +} + +class CryptographicKeyReason extends NotASinkReason, TCryptographicKeyReason { + override string getDescription() { result = "CryptographicKey" } + + override int getEncoding() { result = 9 } +} + +class CryptographicOperationFlowReason extends NotASinkReason, TCryptographicOperationFlowReason { + override string getDescription() { result = "CryptographicOperationFlow" } + + override int getEncoding() { result = 10 } +} + +class LoggerMethodReason extends NotASinkReason, TLoggerMethodReason { + override string getDescription() { result = "LoggerMethod" } + + override int getEncoding() { result = 11 } +} + +class TimeoutReason extends NotASinkReason, TTimeoutReason { + override string getDescription() { result = "Timeout" } + + override int getEncoding() { result = 12 } +} + +class ReceiverStorageReason extends NotASinkReason, TReceiverStorageReason { + override string getDescription() { result = "ReceiverStorage" } + + override int getEncoding() { result = 13 } +} + +class StringStartsWithReason extends NotASinkReason, TStringStartsWithReason { + override string getDescription() { result = "StringStartsWith" } + + override int getEncoding() { result = 14 } +} + +class StringEndsWithReason extends NotASinkReason, TStringEndsWithReason { + override string getDescription() { result = "StringEndsWith" } + + override int getEncoding() { result = 15 } +} + +class StringRegExpTestReason extends NotASinkReason, TStringRegExpTestReason { + override string getDescription() { result = "StringRegExpTest" } + + override int getEncoding() { result = 16 } +} + +class EventRegistrationReason extends NotASinkReason, TEventRegistrationReason { + override string getDescription() { result = "EventRegistration" } + + override int getEncoding() { result = 17 } +} + +class EventDispatchReason extends NotASinkReason, TEventDispatchReason { + override string getDescription() { result = "EventDispatch" } + + override int getEncoding() { result = 18 } +} + +class MembershipCandidateTestReason extends NotASinkReason, TMembershipCandidateTestReason { + override string getDescription() { result = "MembershipCandidateTest" } + + override int getEncoding() { result = 19 } +} + +class FileSystemAccessReason extends NotASinkReason, TFileSystemAccessReason { + override string getDescription() { result = "FileSystemAccess" } + + override int getEncoding() { result = 20 } +} + +class DatabaseAccessReason extends NotASinkReason, TDatabaseAccessReason { + override string getDescription() { result = "DatabaseAccess" } + + override int getEncoding() { result = 21 } +} + +class DOMReason extends NotASinkReason, TDOMReason { + override string getDescription() { result = "DOM" } + + override int getEncoding() { result = 22 } +} + +class NextFunctionCallReason extends NotASinkReason, TNextFunctionCallReason { + override string getDescription() { result = "NextFunctionCall" } + + override int getEncoding() { result = 23 } +} + +class ArgumentToArrayReason extends LikelyNotASinkReason, TArgumentToArrayReason { + override string getDescription() { result = "ArgumentToArray" } + + override int getEncoding() { result = 24 } +} + +class ArgumentToBuiltinGlobalVarRefReason extends LikelyNotASinkReason, + TArgumentToBuiltinGlobalVarRefReason { + override string getDescription() { result = "ArgumentToBuiltinGlobalVarRef" } + + override int getEncoding() { result = 25 } +} + +class ConstantReceiverReason extends NotASinkReason, TConstantReceiverReason { + override string getDescription() { result = "ConstantReceiver" } + + override int getEncoding() { result = 26 } +} + +class BuiltinCallNameReason extends NotASinkReason, TBuiltinCallNameReason { + override string getDescription() { result = "BuiltinCallName" } + + override int getEncoding() { result = 27 } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/NosqlInjectionATM.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/NosqlInjectionATM.qll new file mode 100644 index 00000000000..7fc5c44f2f6 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/NosqlInjectionATM.qll @@ -0,0 +1,178 @@ +/** + * For internal use only. + * + * Defines shared code used by the NoSQL injection boosted query. + */ + +import javascript +private import semmle.javascript.heuristics.SyntacticHeuristics +private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations +private import semmle.javascript.security.TaintedObject +import AdaptiveThreatModeling +private import CoreKnowledge as CoreKnowledge +private import StandardEndpointFilters as StandardEndpointFilters + +module SinkEndpointFilter { + /** + * Provides a set of reasons why a given data flow node should be excluded as a sink candidate. + * + * If this predicate has no results for a sink candidate `n`, then we should treat `n` as an + * effective sink. + */ + string getAReasonSinkExcluded(DataFlow::Node sinkCandidate) { + ( + result = StandardEndpointFilters::getAReasonSinkExcluded(sinkCandidate) + or + // Require NoSQL injection sink candidates to be direct arguments to external library calls. + // + // The standard endpoint filters allow sink candidates which are within object literals or + // array literals, for example `req.sendFile(_, { path: ENDPOINT })`. + // + // However, the NoSQL injection query deals differently with these types of sinks compared to + // other security queries. Other security queries such as SQL injection tend to treat + // `ENDPOINT` as the ground truth sink, but the NoSQL injection query instead treats + // `{ path: ENDPOINT }` as the ground truth sink and defines an additional flow step to ensure + // data flows from `ENDPOINT` to the ground truth sink `{ path: ENDPOINT }`. + // + // Therefore for the NoSQL injection boosted query, we must explicitly ignore sink candidates + // within object literals or array literals, to avoid having multiple alerts for the same + // security vulnerability (one FP where the sink is `ENDPOINT` and one TP where the sink is + // `{ path: ENDPOINT }`). + // + // We use the same reason as in the standard endpoint filters to avoid duplicate reasons for + // endpoints that are neither direct nor indirect arguments to a likely external library call. + not sinkCandidate = StandardEndpointFilters::getALikelyExternalLibraryCall().getAnArgument() and + result = "not an argument to a likely external library call" + or + exists(DataFlow::CallNode call | sinkCandidate = call.getAnArgument() | + // additional databases accesses that aren't modeled yet + call.(DataFlow::MethodCallNode).getMethodName() = + ["create", "createCollection", "createIndexes"] and + result = "matches database access call heuristic" + or + // Remove modeled sinks + CoreKnowledge::isArgumentToKnownLibrarySinkFunction(sinkCandidate) and + result = "modeled sink" + or + // Remove common kinds of unlikely sinks + CoreKnowledge::isKnownStepSrc(sinkCandidate) and + result = "predecessor in a modeled flow step" + or + // Remove modeled database calls. Arguments to modeled calls are very likely to be modeled + // as sinks if they are true positives. Therefore arguments that are not modeled as sinks + // are unlikely to be true positives. + call instanceof DatabaseAccess and + result = "modeled database access" + or + // Remove calls to APIs that aren't relevant to NoSQL injection + call.getReceiver().asExpr() instanceof HTTP::RequestExpr and + result = "receiver is a HTTP request expression" + or + call.getReceiver().asExpr() instanceof HTTP::ResponseExpr and + result = "receiver is a HTTP response expression" + ) + ) and + not ( + // Explicitly allow the following heuristic sinks. + // + // These are copied from the `HeuristicNosqlInjectionSink` class defined within + // `codeql/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll`. + // We can't reuse the class because importing that file would cause us to treat these + // heuristic sinks as known sinks. + isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)(nosql|query)") or + isArgTo(sinkCandidate, "(?i)(query)") + ) + } +} + +class NosqlInjectionATMConfig extends ATMConfig { + NosqlInjectionATMConfig() { this = "NosqlInjectionATMConfig" } + + override predicate isKnownSource(DataFlow::Node source) { + source instanceof NosqlInjection::Source or TaintedObject::isSource(source, _) + } + + override predicate isKnownSink(DataFlow::Node sink) { sink instanceof NosqlInjection::Sink } + + override predicate isEffectiveSink(DataFlow::Node sinkCandidate) { + not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate)) + } + + override EndpointType getASinkEndpointType() { result instanceof NosqlInjectionSinkType } +} + +/** Holds if src -> trg is an additional flow step in the non-boosted NoSQL injection security query. */ +predicate isBaseAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl +) { + TaintedObject::step(src, trg, inlbl, outlbl) + or + // additional flow step to track taint through NoSQL query objects + inlbl = TaintedObject::label() and + outlbl = TaintedObject::label() and + exists(NoSQL::Query query, DataFlow::SourceNode queryObj | + queryObj.flowsToExpr(query) and + queryObj.flowsTo(trg) and + src = queryObj.getAPropertyWrite().getRhs() + ) +} + +/** + * This predicate allows us to propagate data flow through property writes and array constructors + * within a query object, enabling the security query to pick up NoSQL injection vulnerabilities + * involving more complex queries. + */ +DataFlow::Node getASubexpressionWithinQuery(DataFlow::Node query) { + exists(DataFlow::SourceNode receiver | + receiver.flowsTo(getASubexpressionWithinQuery*(query.getALocalSource())) and + result = + [ + receiver.(DataFlow::SourceNode).getAPropertyWrite().getRhs(), + receiver.(DataFlow::ArrayCreationNode).getAnElement() + ] + ) +} + +/** + * A taint-tracking configuration for reasoning about NoSQL injection vulnerabilities. + * + * This is largely a copy of the taint tracking configuration for the standard NoSQL injection + * query, except additional ATM sinks have been added and the additional flow step has been + * generalised to cover the sinks predicted by ATM. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "NosqlInjectionATM" } + + override predicate isSource(DataFlow::Node source) { source instanceof NosqlInjection::Source } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + TaintedObject::isSource(source, label) + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink.(NosqlInjection::Sink).getAFlowLabel() = label + or + // Allow effective sinks to have any taint label + any(NosqlInjectionATMConfig cfg).isEffectiveSink(sink) + } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof NosqlInjection::Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof TaintedObject::SanitizerGuard + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + // additional flow steps from the base (non-boosted) security query + isBaseAdditionalFlowStep(src, trg, inlbl, outlbl) + or + // relaxed version of previous step to track taint through unmodeled NoSQL query objects + any(NosqlInjectionATMConfig cfg).isEffectiveSink(trg) and + src = getASubexpressionWithinQuery(trg) + } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/SqlInjectionATM.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/SqlInjectionATM.qll new file mode 100644 index 00000000000..0893c689b95 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/SqlInjectionATM.qll @@ -0,0 +1,94 @@ +/** + * For internal use only. + * + * Defines shared code used by the SQL injection boosted query. + */ + +import semmle.javascript.heuristics.SyntacticHeuristics +import semmle.javascript.security.dataflow.SqlInjectionCustomizations +import AdaptiveThreatModeling +import CoreKnowledge as CoreKnowledge +import StandardEndpointFilters as StandardEndpointFilters + +/** + * This module provides logic to filter candidate sinks to those which are likely SQL injection + * sinks. + */ +module SinkEndpointFilter { + private import javascript + private import SQL + + /** + * Provides a set of reasons why a given data flow node should be excluded as a sink candidate. + * + * If this predicate has no results for a sink candidate `n`, then we should treat `n` as an + * effective sink. + */ + string getAReasonSinkExcluded(DataFlow::Node sinkCandidate) { + ( + result = StandardEndpointFilters::getAReasonSinkExcluded(sinkCandidate) + or + exists(DataFlow::CallNode call | sinkCandidate = call.getAnArgument() | + // prepared statements for SQL + any(DataFlow::CallNode cn | cn.getCalleeName() = "prepare") + .getAMethodCall("run") + .getAnArgument() = sinkCandidate and + result = "prepared SQL statement" + or + sinkCandidate instanceof DataFlow::ArrayCreationNode and + result = "array creation" + or + // UI is unrelated to SQL + call.getCalleeName().regexpMatch("(?i).*(render|html).*") and + result = "HTML / rendering" + ) + ) and + not ( + // Explicitly allow the following heuristic sinks. + // + // These are copied from the `HeuristicSqlInjectionSink` class defined within + // `codeql/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll`. + // We can't reuse the class because importing that file would cause us to treat these + // heuristic sinks as known sinks. + isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)(sql|query)") or + isArgTo(sinkCandidate, "(?i)(query)") or + isConcatenatedWithString(sinkCandidate, + "(?s).*(ALTER|COUNT|CREATE|DATABASE|DELETE|DISTINCT|DROP|FROM|GROUP|INSERT|INTO|LIMIT|ORDER|SELECT|TABLE|UPDATE|WHERE).*") + ) + } +} + +class SqlInjectionATMConfig extends ATMConfig { + SqlInjectionATMConfig() { this = "SqlInjectionATMConfig" } + + override predicate isKnownSource(DataFlow::Node source) { source instanceof SqlInjection::Source } + + override predicate isKnownSink(DataFlow::Node sink) { sink instanceof SqlInjection::Sink } + + override predicate isEffectiveSink(DataFlow::Node sinkCandidate) { + not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate)) + } + + override EndpointType getASinkEndpointType() { result instanceof SqlInjectionSinkType } +} + +/** + * A taint-tracking configuration for reasoning about SQL injection vulnerabilities. + * + * This is largely a copy of the taint tracking configuration for the standard SQL injection + * query, except additional sinks have been added using the sink endpoint filter. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "SqlInjectionATM" } + + override predicate isSource(DataFlow::Node source) { source instanceof SqlInjection::Source } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof SqlInjection::Sink or any(SqlInjectionATMConfig cfg).isEffectiveSink(sink) + } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof SqlInjection::Sanitizer + } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/StandardEndpointFilters.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/StandardEndpointFilters.qll new file mode 100644 index 00000000000..333dc61ff96 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/StandardEndpointFilters.qll @@ -0,0 +1,137 @@ +/** + * For internal use only. + * + * Provides classes and predicates that are useful for endpoint filters. + * + * The standard use of this library is to make use of `isPotentialEffectiveSink/1` + */ + +private import javascript +private import semmle.javascript.filters.ClassifyFiles as ClassifyFiles +private import semmle.javascript.heuristics.SyntacticHeuristics +private import CoreKnowledge as CoreKnowledge + +/** Provides a set of reasons why a given data flow node should be excluded as a sink candidate. */ +string getAReasonSinkExcluded(DataFlow::Node n) { + not flowsToArgumentOfLikelyExternalLibraryCall(n) and + result = "not an argument to a likely external library call" + or + isArgumentToModeledFunction(n) and result = "argument to modeled function" + or + isArgumentToSinklessLibrary(n) and result = "argument to sinkless library" + or + isSanitizer(n) and result = "sanitizer" + or + isPredicate(n) and result = "predicate" + or + isHash(n) and result = "hash" + or + isNumeric(n) and result = "numeric" + or + // Ignore candidate sinks within externs, generated, library, and test code + exists(string category | category = ["externs", "generated", "library", "test"] | + ClassifyFiles::classify(n.getFile(), category) and + result = "in " + category + " file" + ) +} + +/** + * Holds if the node `n` is an argument to a function that has a manual model. + */ +predicate isArgumentToModeledFunction(DataFlow::Node n) { + exists(DataFlow::InvokeNode invk, DataFlow::Node known | + invk.getAnArgument() = n and invk.getAnArgument() = known and isSomeModeledArgument(known) + ) +} + +/** + * Holds if the node `n` is an argument that has a manual model. + */ +predicate isSomeModeledArgument(DataFlow::Node n) { + CoreKnowledge::isKnownLibrarySink(n) or + CoreKnowledge::isKnownStepSrc(n) or + CoreKnowledge::isOtherModeledArgument(n, _) +} + +/** + * Holds if `n` appears to be a numeric value. + */ +predicate isNumeric(DataFlow::Node n) { isReadFrom(n, ".*index.*") } + +/** + * Holds if `n` is an argument to a library without sinks. + */ +predicate isArgumentToSinklessLibrary(DataFlow::Node n) { + exists(DataFlow::InvokeNode invk, DataFlow::SourceNode commonSafeLibrary, string libraryName | + libraryName = ["slugify", "striptags", "marked"] + | + commonSafeLibrary = DataFlow::moduleImport(libraryName) and + invk = [commonSafeLibrary, commonSafeLibrary.getAPropertyRead()].getAnInvocation() and + n = invk.getAnArgument() + ) +} + +predicate isSanitizer(DataFlow::Node n) { + exists(DataFlow::CallNode call | n = call.getAnArgument() | + call.getCalleeName().regexpMatch("(?i).*(escape|valid(ate)?|sanitize|purify).*") + ) +} + +predicate isPredicate(DataFlow::Node n) { + exists(DataFlow::CallNode call | n = call.getAnArgument() | + call.getCalleeName().regexpMatch("(equals|(|is|has|can)(_|[A-Z])).*") + ) +} + +predicate isHash(DataFlow::Node n) { + exists(DataFlow::CallNode call | n = call.getAnArgument() | + call.getCalleeName().regexpMatch("(?i)^(sha\\d*|md5|hash)$") + ) +} + +/** + * Holds if the data flow node is a (possibly indirect) argument of a likely external library call. + * + * This includes direct arguments of likely external library calls as well as nested object + * literals within those calls. + */ +predicate flowsToArgumentOfLikelyExternalLibraryCall(DataFlow::Node n) { + n = getACallWithoutCallee().getAnArgument() + or + exists(DataFlow::SourceNode src | flowsToArgumentOfLikelyExternalLibraryCall(src) | + n = src.getAPropertyWrite().getRhs() + ) + or + exists(DataFlow::ArrayCreationNode arr | flowsToArgumentOfLikelyExternalLibraryCall(arr) | + n = arr.getAnElement() + ) +} + +/** + * Get calls which are likely to be to external non-built-in libraries. + */ +DataFlow::CallNode getALikelyExternalLibraryCall() { result = getACallWithoutCallee() } + +/** + * Gets a node that flows to callback-parameter `p`. + */ +private DataFlow::SourceNode getACallback(DataFlow::ParameterNode p, DataFlow::TypeBackTracker t) { + t.start() and + result = p and + any(DataFlow::FunctionNode f).getLastParameter() = p and + exists(p.getACall()) + or + exists(DataFlow::TypeBackTracker t2 | result = getACallback(p, t2).backtrack(t2, t)) +} + +/** + * Get calls for which we do not have the callee (i.e. the definition of the called function). This + * acts as a heuristic for identifying calls to external library functions. + */ +private DataFlow::CallNode getACallWithoutCallee() { + forall(Function callee | callee = result.getACallee() | callee.getTopLevel().isExterns()) and + not exists(DataFlow::ParameterNode param, DataFlow::FunctionNode callback | + param.flowsTo(result.getCalleeNode()) and + callback = getACallback(param, DataFlow::TypeBackTracker::end()) + ) +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/TaintedPathATM.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/TaintedPathATM.qll new file mode 100644 index 00000000000..5bbacae50b7 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/TaintedPathATM.qll @@ -0,0 +1,123 @@ +/** + * For internal use only. + * + * Defines shared code used by the path injection boosted query. + */ + +import semmle.javascript.heuristics.SyntacticHeuristics +import semmle.javascript.security.dataflow.TaintedPathCustomizations +import AdaptiveThreatModeling +import CoreKnowledge as CoreKnowledge +import StandardEndpointFilters as StandardEndpointFilters + +/** + * This module provides logic to filter candidate sinks to those which are likely path injection + * sinks. + */ +module SinkEndpointFilter { + private import javascript + private import TaintedPath + + /** + * Provides a set of reasons why a given data flow node should be excluded as a sink candidate. + * + * If this predicate has no results for a sink candidate `n`, then we should treat `n` as an + * effective sink. + */ + string getAReasonSinkExcluded(DataFlow::Node sinkCandidate) { + result = StandardEndpointFilters::getAReasonSinkExcluded(sinkCandidate) and + not ( + // Explicitly allow the following heuristic sinks. + // + // These are mostly copied from the `HeuristicTaintedPathSink` class defined within + // `codeql/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll`. + // We can't reuse the class because importing that file would cause us to treat these + // heuristic sinks as known sinks. + isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)(file|folder|dir|absolute)") + or + isArgTo(sinkCandidate, "(?i)(get|read)file") + or + exists(string pathPattern | + // paths with at least two parts, and either a trailing or leading slash + pathPattern = "(?i)([a-z0-9_.-]+/){2,}" or + pathPattern = "(?i)(/[a-z0-9_.-]+){2,}" + | + isConcatenatedWithString(sinkCandidate, pathPattern) + ) + or + isConcatenatedWithStrings(".*/", sinkCandidate, "/.*") + or + // In addition to the names from `HeuristicTaintedPathSink` in the + // `isAssignedToOrConcatenatedWith` predicate call above, we also allow the noisier "path" + // name. + isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)path") + ) + } +} + +class TaintedPathATMConfig extends ATMConfig { + TaintedPathATMConfig() { this = "TaintedPathATMConfig" } + + override predicate isKnownSource(DataFlow::Node source) { source instanceof TaintedPath::Source } + + override predicate isKnownSink(DataFlow::Node sink) { sink instanceof TaintedPath::Sink } + + override predicate isEffectiveSink(DataFlow::Node sinkCandidate) { + not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate)) + } + + override EndpointType getASinkEndpointType() { result instanceof TaintedPathSinkType } +} + +/** + * A taint-tracking configuration for reasoning about path injection vulnerabilities. + * + * This is largely a copy of the taint tracking configuration for the standard path injection + * query, except additional ATM sinks have been added to the `isSink` predicate. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "TaintedPathATM" } + + override predicate isSource(DataFlow::Node source) { source instanceof TaintedPath::Source } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + label = sink.(TaintedPath::Sink).getAFlowLabel() + or + // Allow effective sinks to have any taint label + any(TaintedPathATMConfig cfg).isEffectiveSink(sink) + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof TaintedPath::Sanitizer } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { + node instanceof BarrierGuardNodeAsSanitizerGuardNode + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, + DataFlow::FlowLabel dstlabel + ) { + TaintedPath::isAdditionalTaintedPathFlowStep(src, dst, srclabel, dstlabel) + } +} + +/** + * This class provides sanitizer guards for path injection. + * + * The standard library path injection query uses a data flow configuration, and therefore defines + * barrier nodes. However we're using a taint tracking configuration for path injection to find new + * kinds of less certain results. Since taint tracking configurations use sanitizer guards instead + * of barrier guards, we port the barrier guards for the boosted query from the standard library to + * sanitizer guards here. + */ +class BarrierGuardNodeAsSanitizerGuardNode extends TaintTracking::LabeledSanitizerGuardNode { + BarrierGuardNodeAsSanitizerGuardNode() { this instanceof TaintedPath::BarrierGuardNode } + + override predicate sanitizes(boolean outcome, Expr e) { + blocks(outcome, e) or blocks(outcome, e, _) + } + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + sanitizes(outcome, e) + } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/XssATM.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/XssATM.qll new file mode 100644 index 00000000000..ba16b60aa31 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/XssATM.qll @@ -0,0 +1,103 @@ +/** + * For internal use only. + * + * Defines shared code used by the XSS boosted query. + */ + +private import semmle.javascript.heuristics.SyntacticHeuristics +private import semmle.javascript.security.dataflow.DomBasedXssCustomizations +import AdaptiveThreatModeling +import CoreKnowledge as CoreKnowledge +import StandardEndpointFilters as StandardEndpointFilters + +/** + * This module provides logic to filter candidate sinks to those which are likely XSS sinks. + */ +module SinkEndpointFilter { + private import javascript + private import DomBasedXss + + /** + * Provides a set of reasons why a given data flow node should be excluded as a sink candidate. + * + * If this predicate has no results for a sink candidate `n`, then we should treat `n` as an + * effective sink. + */ + string getAReasonSinkExcluded(DataFlow::Node sinkCandidate) { + ( + result = StandardEndpointFilters::getAReasonSinkExcluded(sinkCandidate) + or + exists(DataFlow::CallNode call | sinkCandidate = call.getAnArgument() | + call.getCalleeName() = "setState" + ) and + result = "setState calls ought to be safe in react applications" + ) and + not ( + // Explicitly allow the following heuristic sinks. + // + // These are copied from the `HeuristicDomBasedXssSink` class defined within + // `codeql/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll`. + // We can't reuse the class because importing that file would cause us to treat these + // heuristic sinks as known sinks. + isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)(html|innerhtml)") + or + isArgTo(sinkCandidate, "(?i)(html|render)") + or + sinkCandidate instanceof StringOps::HtmlConcatenationLeaf + or + isConcatenatedWithStrings("(?is).*<[a-z ]+.*", sinkCandidate, "(?s).*>.*") + or + // In addition to the heuristic sinks from `HeuristicDomBasedXssSink`, explicitly allow + // property writes like `elem.innerHTML = <TAINT>` that may not be picked up as HTML + // concatenation leaves. + exists(DataFlow::PropWrite pw | + pw.getPropertyName().regexpMatch("(?i).*html*") and + pw.getRhs() = sinkCandidate + ) + ) + } +} + +class DomBasedXssATMConfig extends ATMConfig { + DomBasedXssATMConfig() { this = "DomBasedXssATMConfig" } + + override predicate isKnownSource(DataFlow::Node source) { source instanceof DomBasedXss::Source } + + override predicate isKnownSink(DataFlow::Node sink) { sink instanceof DomBasedXss::Sink } + + override predicate isEffectiveSink(DataFlow::Node sinkCandidate) { + not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate)) + } + + override EndpointType getASinkEndpointType() { result instanceof XssSinkType } +} + +/** + * A taint-tracking configuration for reasoning about XSS vulnerabilities. + * + * This is largely a copy of the taint tracking configuration for the standard XSSThroughDom query, + * except additional ATM sinks have been added to the `isSink` predicate. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "DomBasedXssATMConfiguration" } + + override predicate isSource(DataFlow::Node source) { source instanceof DomBasedXss::Source } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof DomBasedXss::Sink or + any(DomBasedXssATMConfig cfg).isEffectiveSink(sink) + } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof DomBasedXss::Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof DomBasedXss::SanitizerGuard + } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + DomBasedXss::isOptionallySanitizedEdge(pred, succ) + } +} diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.lock.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml new file mode 100644 index 00000000000..98f6feeff90 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -0,0 +1,6 @@ +name: codeql/javascript-experimental-atm-lib +version: 0.0.0 +extractor: javascript +library: true +dependencies: + codeql/javascript-all: "*" diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/NosqlInjectionATM.ql b/javascript/ql/experimental/adaptivethreatmodeling/src/NosqlInjectionATM.ql new file mode 100644 index 00000000000..977de7353a9 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/NosqlInjectionATM.ql @@ -0,0 +1,30 @@ +/** + * For internal use only. + * + * @name NoSQL database query built from user-controlled sources (boosted) + * @description Building a database query from user-controlled sources is vulnerable to insertion of + * malicious code by the user. + * @kind path-problem + * @scored + * @problem.severity error + * @security-severity 8.8 + * @id adaptive-threat-modeling/js/nosql-injection + * @tags experimental experimental/atm security + */ + +import ATM::ResultsInfo +import DataFlow::PathGraph +import experimental.adaptivethreatmodeling.NosqlInjectionATM + +from + DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score, + string scoreString +where + cfg.hasFlowPath(source, sink) and + not isFlowLikelyInBaseQuery(source.getNode(), sink.getNode()) and + score = getScoreForFlow(source.getNode(), sink.getNode()) and + scoreString = getScoreStringForFlow(source.getNode(), sink.getNode()) +select sink.getNode(), source, sink, + "[Score = " + scoreString + "] This may be a NoSQL query depending on $@ " + + getAdditionalAlertInfo(source.getNode(), sink.getNode()), source.getNode(), + "a user-provided value", score diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/SqlInjectionATM.ql b/javascript/ql/experimental/adaptivethreatmodeling/src/SqlInjectionATM.ql new file mode 100644 index 00000000000..7878ad97a40 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/SqlInjectionATM.ql @@ -0,0 +1,30 @@ +/** + * For internal use only. + * + * @name SQL database query built from user-controlled sources (boosted) + * @description Building a database query from user-controlled sources is vulnerable to insertion of + * malicious code by the user. + * @kind path-problem + * @scored + * @problem.severity error + * @security-severity 8.8 + * @id adaptive-threat-modeling/js/sql-injection + * @tags experimental experimental/atm security + */ + +import experimental.adaptivethreatmodeling.SqlInjectionATM +import ATM::ResultsInfo +import DataFlow::PathGraph + +from + DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score, + string scoreString +where + cfg.hasFlowPath(source, sink) and + not isFlowLikelyInBaseQuery(source.getNode(), sink.getNode()) and + score = getScoreForFlow(source.getNode(), sink.getNode()) and + scoreString = getScoreStringForFlow(source.getNode(), sink.getNode()) +select sink.getNode(), source, sink, + "[Score = " + scoreString + "] This may be a js/sql result depending on $@ " + + getAdditionalAlertInfo(source.getNode(), sink.getNode()), source.getNode(), + "a user-provided value", score diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/TaintedPathATM.ql b/javascript/ql/experimental/adaptivethreatmodeling/src/TaintedPathATM.ql new file mode 100644 index 00000000000..352c290a82d --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/TaintedPathATM.ql @@ -0,0 +1,30 @@ +/** + * For internal use only. + * + * @name Uncontrolled data used in path expression (boosted) + * @description Accessing paths influenced by users can allow an attacker to access + * unexpected resources. + * @kind path-problem + * @scored + * @problem.severity error + * @security-severity 7.5 + * @id adaptive-threat-modeling/js/path-injection + * @tags experimental experimental/atm security + */ + +import ATM::ResultsInfo +import DataFlow::PathGraph +import experimental.adaptivethreatmodeling.TaintedPathATM + +from + DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score, + string scoreString +where + cfg.hasFlowPath(source, sink) and + not isFlowLikelyInBaseQuery(source.getNode(), sink.getNode()) and + score = getScoreForFlow(source.getNode(), sink.getNode()) and + scoreString = getScoreStringForFlow(source.getNode(), sink.getNode()) +select sink.getNode(), source, sink, + "[Score = " + scoreString + "] This may be a js/path-injection result depending on $@ " + + getAdditionalAlertInfo(source.getNode(), sink.getNode()), source.getNode(), + "a user-provided value", score diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.ql b/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.ql new file mode 100644 index 00000000000..1180846f71c --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.ql @@ -0,0 +1,31 @@ +/** + * For internal use only. + * + * @name Client-side cross-site scripting (boosted) + * @description Writing user input directly to the DOM allows for + * a cross-site scripting vulnerability. + * @kind path-problem + * @scored + * @problem.severity error + * @security-severity 6.1 + * @id adaptive-threat-modeling/js/xss + * @tags experimental experimental/atm security + */ + +import javascript +import ATM::ResultsInfo +import DataFlow::PathGraph +import experimental.adaptivethreatmodeling.XssATM + +from + DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score, + string scoreString +where + cfg.hasFlowPath(source, sink) and + not isFlowLikelyInBaseQuery(source.getNode(), sink.getNode()) and + score = getScoreForFlow(source.getNode(), sink.getNode()) and + scoreString = getScoreStringForFlow(source.getNode(), sink.getNode()) +select sink.getNode(), source, sink, + "[Score = " + scoreString + "] This may be a js/xss result depending on $@ " + + getAdditionalAlertInfo(source.getNode(), sink.getNode()), source.getNode(), + "a user-provided value", score diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls b/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls new file mode 100644 index 00000000000..fbd966ef5b3 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls @@ -0,0 +1,8 @@ +- description: ATM boosted Code Scanning queries for JavaScript +- qlpack: codeql/javascript-experimental-atm-src +- include: + id: + - adaptive-threat-modeling/js/nosql-injection + - adaptive-threat-modeling/js/sql-injection + - adaptive-threat-modeling/js/path-injection + - adaptive-threat-modeling/js/xss diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.lock.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml new file mode 100644 index 00000000000..623593c8cec --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -0,0 +1,6 @@ +name: codeql/javascript-experimental-atm-src +language: javascript +version: 0.0.0 +suites: codeql-suites +dependencies: + codeql/javascript-experimental-atm-lib: "*" diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/queries.xml b/javascript/ql/experimental/adaptivethreatmodeling/src/queries.xml new file mode 100644 index 00000000000..d4346295164 --- /dev/null +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/queries.xml @@ -0,0 +1 @@ +<queries language="javascript"/> From 6f34735f64d44844ec2b387a459d26fa1017d9e6 Mon Sep 17 00:00:00 2001 From: hubwriter <hubwriter@github.com> Date: Tue, 19 Oct 2021 09:27:54 +0100 Subject: [PATCH 322/361] Update docs/codeql/writing-codeql-queries/creating-path-queries.rst --- docs/codeql/writing-codeql-queries/creating-path-queries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/writing-codeql-queries/creating-path-queries.rst b/docs/codeql/writing-codeql-queries/creating-path-queries.rst index 3eb67207ccd..4eec766d488 100644 --- a/docs/codeql/writing-codeql-queries/creating-path-queries.rst +++ b/docs/codeql/writing-codeql-queries/creating-path-queries.rst @@ -116,7 +116,7 @@ Declaring sources and sinks You must provide information about the ``source`` and ``sink`` in your path query. These are objects that correspond to the nodes of the paths that you are exploring. The name and the type of the ``source`` and the ``sink`` must be declared in the ``from`` statement of the query, and the types must be compatible with the nodes of the graph computed by the ``edges`` predicate. -If you are querying C/C++, C#, Java, JavaScript, or Ruby code (and you have used ``import DataFlow::PathGraph`` in your query), the definitions of the ``source`` and ``sink`` are accessed via the ``Configuration`` class in the data flow library. You should declare all three of these objects in the ``from`` statement. +If you are querying C/C++, C#, Java, JavaScript, Python, or Ruby code (and you have used ``import DataFlow::PathGraph`` in your query), the definitions of the ``source`` and ``sink`` are accessed via the ``Configuration`` class in the data flow library. You should declare all three of these objects in the ``from`` statement. For example: .. code-block:: ql From 90a50e7ca94fb0d83fea0c632706de09602b1ff3 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Thu, 14 Oct 2021 09:26:55 +0200 Subject: [PATCH 323/361] Java: Fix bad join-order. --- java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll b/java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll index 26fcd109df2..94f67445785 100644 --- a/java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll +++ b/java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll @@ -39,7 +39,10 @@ private Expr getRunnerArgument(MethodAccess ma, Method runmethod) { or getRunnerArgument(ma, runmethod).(CastExpr).getExpr() = result or - getRunnerArgument(ma, runmethod).(VarAccess).getVariable().getAnAssignedValue() = result + pragma[only_bind_out](getRunnerArgument(ma, runmethod)) + .(VarAccess) + .getVariable() + .getAnAssignedValue() = result } /** From b71920209e12c4f56484826afc5cd0a892f4d71c Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 12 Oct 2021 17:08:52 +0100 Subject: [PATCH 324/361] Factor out string prefix logic --- .../code/java/dataflow/StringPrefixes.qll | 151 ++++++++++++++++++ .../code/java/security/RequestForgery.qll | 147 +---------------- 2 files changed, 156 insertions(+), 142 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll diff --git a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll new file mode 100644 index 00000000000..ac374ccaf72 --- /dev/null +++ b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll @@ -0,0 +1,151 @@ +/** + * Provides classes and predicates for identifying expressions that may be appended to an interesting prefix. + * + * To use this library, extend the abstract class `InterestingPrefix` to have the library identify expressions that + * may be appended to it, then check `InterestingPrefix.getAnAppendedExpression(Expr)` to get your results. + * + * For example, `private class FooPrefix extends InterestingPrefix { FooPrefix() { this = "foo:" } };` + * `predicate mayFollowFoo(Expr e) { e = any(FooPrefix fp).getAnAppendedExpression() }` + */ + +import java +import semmle.code.java.dataflow.TaintTracking +private import semmle.code.java.StringFormat + +abstract class InterestingPrefix extends CompileTimeConstantExpr { + /** + * Gets the offset in this constant string where the interesting substring begins. + */ + abstract int getOffset(); + + Expr getAnAppendedExpression() { mayFollowInterestingPrefix(this, result) } +} + +private Expr getAnInterestingPrefix(InterestingPrefix root) { + result = root + or + result.(AddExpr).getAnOperand() = getAnInterestingPrefix(root) +} + +private class StringBuilderAppend extends MethodAccess { + StringBuilderAppend() { + this.getMethod().getDeclaringType() instanceof StringBuildingType and + this.getMethod().hasName("append") + } +} + +private class StringBuilderConstructorOrAppend extends Call { + StringBuilderConstructorOrAppend() { + this instanceof StringBuilderAppend or + this.(ClassInstanceExpr).getConstructedType() instanceof StringBuildingType + } +} + +private Expr getQualifier(Expr e) { result = e.(MethodAccess).getQualifier() } + +/** + * An extension of `StringBuilderVar` that also accounts for strings appended in StringBuilder/Buffer's constructor + * and in `append` calls chained onto the constructor call. + * + * The original `StringBuilderVar` doesn't care about these because it is designed to model taint, and + * in taint rules terms these are not needed, as the connection between construction, appends and the + * eventual `toString` is more obvious. + */ +private class StringBuilderVarExt extends StringBuilderVar { + /** + * Returns a first assignment after this StringBuilderVar is first assigned. + * + * For example, for `StringBuilder sbv = new StringBuilder("1").append("2"); sbv.append("3").append("4");` + * this returns the append of `"3"`. + */ + private StringBuilderAppend getAFirstAppendAfterAssignment() { + result = this.getAnAppend() and not result = this.getNextAppend(_) + } + + /** + * Gets the next `append` after `prev`, where `prev` is, perhaps after some more `append` or other + * chained calls, assigned to this `StringBuilderVar`. + */ + private StringBuilderAppend getNextAssignmentChainedAppend(StringBuilderConstructorOrAppend prev) { + getQualifier*(result) = this.getAnAssignedValue() and + result.getQualifier() = prev + } + + /** + * Get a constructor call or `append` call that contributes a string to this string builder. + */ + StringBuilderConstructorOrAppend getAConstructorOrAppend() { + exists(this.getNextAssignmentChainedAppend(result)) or + result = this.getAnAssignedValue() or + result = this.getAnAppend() + } + + /** + * Like `StringBuilderVar.getNextAppend`, except including appends and constructors directly + * assigned to this `StringBuilderVar`. + */ + private StringBuilderAppend getNextAppendIncludingAssignmentChains( + StringBuilderConstructorOrAppend prev + ) { + result = getNextAssignmentChainedAppend(prev) + or + prev = this.getAnAssignedValue() and + result = this.getAFirstAppendAfterAssignment() + or + result = this.getNextAppend(prev) + } + + /** + * Implements `StringBuilderVarExt.getNextAppendIncludingAssignmentChains+(prev)`. + */ + pragma[nomagic] + StringBuilderAppend getSubsequentAppendIncludingAssignmentChains( + StringBuilderConstructorOrAppend prev + ) { + result = this.getNextAppendIncludingAssignmentChains(prev) or + result = + this.getSubsequentAppendIncludingAssignmentChains(this.getNextAppendIncludingAssignmentChains(prev)) + } +} + +/** + * Holds if `follows` may be concatenated after `prefix`. + */ +private predicate mayFollowInterestingPrefix(InterestingPrefix prefix, Expr follows) { + // Expressions that come after an interesting prefix in a tree of string additions: + follows = + any(AddExpr add | add.getLeftOperand() = getAnInterestingPrefix(prefix)).getRightOperand() + or + // Sanitize expressions that come after an interesting prefix in a sequence of StringBuilder operations: + exists( + StringBuilderConstructorOrAppend appendSanitizingConstant, StringBuilderAppend subsequentAppend, + StringBuilderVarExt v + | + appendSanitizingConstant = v.getAConstructorOrAppend() and + appendSanitizingConstant.getArgument(0) = getAnInterestingPrefix(prefix) and + v.getSubsequentAppendIncludingAssignmentChains(appendSanitizingConstant) = subsequentAppend and + follows = subsequentAppend.getArgument(0) + ) + or + // Sanitize expressions that come after an interesting prefix in the args to a format call: + exists( + FormattingCall formatCall, FormatString formatString, int prefixOffset, int laterOffset, + int sanitizedArg + | + formatString = unique(FormatString fs | fs = formatCall.getAFormatString()) and + ( + // An interesting prefix argument comes before this: + exists(int argIdx | + formatCall.getArgumentToBeFormatted(argIdx) = prefix and + prefixOffset = formatString.getAnArgUsageOffset(argIdx) + ) + or + // The format string itself contains an interesting prefix that precedes subsequent arguments: + formatString = prefix.getStringValue() and + prefixOffset = prefix.getOffset() + ) and + laterOffset > prefixOffset and + laterOffset = formatString.getAnArgUsageOffset(sanitizedArg) and + follows = formatCall.getArgumentToBeFormatted(sanitizedArg) + ) +} diff --git a/java/ql/lib/semmle/code/java/security/RequestForgery.qll b/java/ql/lib/semmle/code/java/security/RequestForgery.qll index 268bd364b15..be2f529d6ad 100644 --- a/java/ql/lib/semmle/code/java/security/RequestForgery.qll +++ b/java/ql/lib/semmle/code/java/security/RequestForgery.qll @@ -7,8 +7,7 @@ import semmle.code.java.frameworks.spring.Spring import semmle.code.java.frameworks.JaxWS import semmle.code.java.frameworks.javase.Http import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.TaintTracking -private import semmle.code.java.StringFormat +import semmle.code.java.dataflow.StringPrefixes private import semmle.code.java.dataflow.ExternalFlow /** @@ -52,10 +51,10 @@ private class PrimitiveSanitizer extends RequestForgerySanitizer { } } -private class HostnameSanitizingConstantPrefix extends CompileTimeConstantExpr { +private class HostnameSanitizingPrefix extends InterestingPrefix { int offset; - HostnameSanitizingConstantPrefix() { + HostnameSanitizingPrefix() { // Matches strings that look like when prepended to untrusted input, they will restrict // the host or entity addressed: for example, anything containing `?` or `#`, or a slash that // doesn't appear to be a protocol specifier (e.g. `http://` is not sanitizing), or specifically @@ -66,143 +65,7 @@ private class HostnameSanitizingConstantPrefix extends CompileTimeConstantExpr { ) } - /** - * Gets the offset in this constant string where a sanitizing substring begins. - */ - int getOffset() { result = offset } -} - -private Expr getAHostnameSanitizingPrefix() { - result instanceof HostnameSanitizingConstantPrefix - or - result.(AddExpr).getAnOperand() = getAHostnameSanitizingPrefix() -} - -private class StringBuilderAppend extends MethodAccess { - StringBuilderAppend() { - this.getMethod().getDeclaringType() instanceof StringBuildingType and - this.getMethod().hasName("append") - } -} - -private class StringBuilderConstructorOrAppend extends Call { - StringBuilderConstructorOrAppend() { - this instanceof StringBuilderAppend or - this.(ClassInstanceExpr).getConstructedType() instanceof StringBuildingType - } -} - -private Expr getQualifier(Expr e) { result = e.(MethodAccess).getQualifier() } - -/** - * An extension of `StringBuilderVar` that also accounts for strings appended in StringBuilder/Buffer's constructor - * and in `append` calls chained onto the constructor call. - * - * The original `StringBuilderVar` doesn't care about these because it is designed to model taint, and - * in taint rules terms these are not needed, as the connection between construction, appends and the - * eventual `toString` is more obvious. - */ -private class StringBuilderVarExt extends StringBuilderVar { - /** - * Returns a first assignment after this StringBuilderVar is first assigned. - * - * For example, for `StringBuilder sbv = new StringBuilder("1").append("2"); sbv.append("3").append("4");` - * this returns the append of `"3"`. - */ - private StringBuilderAppend getAFirstAppendAfterAssignment() { - result = this.getAnAppend() and not result = this.getNextAppend(_) - } - - /** - * Gets the next `append` after `prev`, where `prev` is, perhaps after some more `append` or other - * chained calls, assigned to this `StringBuilderVar`. - */ - private StringBuilderAppend getNextAssignmentChainedAppend(StringBuilderConstructorOrAppend prev) { - getQualifier*(result) = this.getAnAssignedValue() and - result.getQualifier() = prev - } - - /** - * Get a constructor call or `append` call that contributes a string to this string builder. - */ - StringBuilderConstructorOrAppend getAConstructorOrAppend() { - exists(this.getNextAssignmentChainedAppend(result)) or - result = this.getAnAssignedValue() or - result = this.getAnAppend() - } - - /** - * Like `StringBuilderVar.getNextAppend`, except including appends and constructors directly - * assigned to this `StringBuilderVar`. - */ - private StringBuilderAppend getNextAppendIncludingAssignmentChains( - StringBuilderConstructorOrAppend prev - ) { - result = this.getNextAssignmentChainedAppend(prev) - or - prev = this.getAnAssignedValue() and - result = this.getAFirstAppendAfterAssignment() - or - result = this.getNextAppend(prev) - } - - /** - * Implements `StringBuilderVarExt.getNextAppendIncludingAssignmentChains+(prev)`. - */ - pragma[nomagic] - StringBuilderAppend getSubsequentAppendIncludingAssignmentChains( - StringBuilderConstructorOrAppend prev - ) { - result = this.getNextAppendIncludingAssignmentChains(prev) or - result = - this.getSubsequentAppendIncludingAssignmentChains(this.getNextAppendIncludingAssignmentChains(prev)) - } -} - -/** - * An expression that is sanitized because it is concatenated onto a string that looks like - * a hostname or a URL separator, preventing the appended string from arbitrarily controlling - * the addressed server. - */ -private class HostnameSanitizedExpr extends Expr { - HostnameSanitizedExpr() { - // Sanitize expressions that come after a sanitizing prefix in a tree of string additions: - this = - any(AddExpr add | add.getLeftOperand() = getAHostnameSanitizingPrefix()).getRightOperand() - or - // Sanitize expressions that come after a sanitizing prefix in a sequence of StringBuilder operations: - exists( - StringBuilderConstructorOrAppend appendSanitizingConstant, - StringBuilderAppend subsequentAppend, StringBuilderVarExt v - | - appendSanitizingConstant = v.getAConstructorOrAppend() and - appendSanitizingConstant.getArgument(0) = getAHostnameSanitizingPrefix() and - v.getSubsequentAppendIncludingAssignmentChains(appendSanitizingConstant) = subsequentAppend and - this = subsequentAppend.getArgument(0) - ) - or - // Sanitize expressions that come after a sanitizing prefix in the args to a format call: - exists( - FormattingCall formatCall, FormatString formatString, HostnameSanitizingConstantPrefix prefix, - int sanitizedFromOffset, int laterOffset, int sanitizedArg - | - formatString = unique(FormatString fs | fs = formatCall.getAFormatString()) and - ( - // A sanitizing argument comes before this: - exists(int argIdx | - formatCall.getArgumentToBeFormatted(argIdx) = prefix and - sanitizedFromOffset = formatString.getAnArgUsageOffset(argIdx) - ) - or - // The format string itself sanitizes subsequent arguments: - formatString = prefix.getStringValue() and - sanitizedFromOffset = prefix.getOffset() - ) and - laterOffset > sanitizedFromOffset and - laterOffset = formatString.getAnArgUsageOffset(sanitizedArg) and - this = formatCall.getArgumentToBeFormatted(sanitizedArg) - ) - } + override int getOffset() { result = offset } } /** @@ -210,5 +73,5 @@ private class HostnameSanitizedExpr extends Expr { * host of a URL. */ private class HostnameSantizer extends RequestForgerySanitizer { - HostnameSantizer() { this.asExpr() instanceof HostnameSanitizedExpr } + HostnameSantizer() { this.asExpr() = any(HostnameSanitizingPrefix hsp).getAnAppendedExpression() } } From d0d17e3b843dac051e0446456b8070e3757b8281 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 12 Oct 2021 17:09:48 +0100 Subject: [PATCH 325/361] Make import private --- java/ql/lib/semmle/code/java/security/RequestForgery.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/security/RequestForgery.qll b/java/ql/lib/semmle/code/java/security/RequestForgery.qll index be2f529d6ad..b7d3e4a8a77 100644 --- a/java/ql/lib/semmle/code/java/security/RequestForgery.qll +++ b/java/ql/lib/semmle/code/java/security/RequestForgery.qll @@ -7,7 +7,7 @@ import semmle.code.java.frameworks.spring.Spring import semmle.code.java.frameworks.JaxWS import semmle.code.java.frameworks.javase.Http import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.StringPrefixes +private import semmle.code.java.dataflow.StringPrefixes private import semmle.code.java.dataflow.ExternalFlow /** From 3c25301593c369262ad771574558071ea2ae6a49 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Wed, 13 Oct 2021 11:11:41 +0100 Subject: [PATCH 326/361] Extend documentation --- .../code/java/dataflow/StringPrefixes.qll | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll index ac374ccaf72..98aea2587bc 100644 --- a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll @@ -4,20 +4,47 @@ * To use this library, extend the abstract class `InterestingPrefix` to have the library identify expressions that * may be appended to it, then check `InterestingPrefix.getAnAppendedExpression(Expr)` to get your results. * - * For example, `private class FooPrefix extends InterestingPrefix { FooPrefix() { this = "foo:" } };` - * `predicate mayFollowFoo(Expr e) { e = any(FooPrefix fp).getAnAppendedExpression() }` + * For example, to identify expressions that may follow "foo:" in some string, we could define: + * + * ``` + * private class FooPrefix extends InterestingPrefix { + * int offset; + * FooPrefix() { this.getStringValue().substring("foo:") = offset }; + * override int getOffset() { result = offset } + * }; + * + * predicate mayFollowFoo(Expr e) { e = any(FooPrefix fp).getAnAppendedExpression() } + * ``` + * + * This will identify all the `suffix` expressions in contexts such as: + * + * ``` + * "foo:" + suffix1 + * "barfoo:" + suffix2 + * stringBuilder.append("foo:").append(suffix3); + * String.format("%sfoo:%s", notSuffix, suffix4); + * ``` */ import java import semmle.code.java.dataflow.TaintTracking private import semmle.code.java.StringFormat +/** + * A string constant that contains a prefix whose possible successor strings are returned + * by `getAnAppendedExpression`. + * + * Extend this class to specify prefixes whose successors should be analysed. + */ abstract class InterestingPrefix extends CompileTimeConstantExpr { /** - * Gets the offset in this constant string where the interesting substring begins. + * Gets the offset in this constant string where the interesting prefix begins. */ abstract int getOffset(); + /** + * Gets an expression that may follow this prefix in a derived string. + */ Expr getAnAppendedExpression() { mayFollowInterestingPrefix(this, result) } } From 0d66cebfba5b934df1949a5c3247a5dd028d7836 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 19 Oct 2021 11:23:16 +0100 Subject: [PATCH 327/361] Autoformat --- .../semmle/code/java/dataflow/StringPrefixes.qll | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll index 98aea2587bc..fde9f644217 100644 --- a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll @@ -5,19 +5,19 @@ * may be appended to it, then check `InterestingPrefix.getAnAppendedExpression(Expr)` to get your results. * * For example, to identify expressions that may follow "foo:" in some string, we could define: - * + * * ``` - * private class FooPrefix extends InterestingPrefix { + * private class FooPrefix extends InterestingPrefix { * int offset; - * FooPrefix() { this.getStringValue().substring("foo:") = offset }; - * override int getOffset() { result = offset } + * FooPrefix() { this.getStringValue().substring("foo:") = offset }; + * override int getOffset() { result = offset } * }; - * + * * predicate mayFollowFoo(Expr e) { e = any(FooPrefix fp).getAnAppendedExpression() } * ``` * * This will identify all the `suffix` expressions in contexts such as: - * + * * ``` * "foo:" + suffix1 * "barfoo:" + suffix2 @@ -33,7 +33,7 @@ private import semmle.code.java.StringFormat /** * A string constant that contains a prefix whose possible successor strings are returned * by `getAnAppendedExpression`. - * + * * Extend this class to specify prefixes whose successors should be analysed. */ abstract class InterestingPrefix extends CompileTimeConstantExpr { From 3bf9abb4cea0e7c32f9ee862e320b9bfec9e709f Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 19 Oct 2021 11:26:16 +0100 Subject: [PATCH 328/361] Avoid ambiguous term 'successor'. --- java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll index fde9f644217..10dd3a13e60 100644 --- a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll @@ -31,10 +31,10 @@ import semmle.code.java.dataflow.TaintTracking private import semmle.code.java.StringFormat /** - * A string constant that contains a prefix whose possible successor strings are returned - * by `getAnAppendedExpression`. + * A string constant that contains a prefix whose possibly-appended strings are + * returned by `getAnAppendedExpression`. * - * Extend this class to specify prefixes whose successors should be analysed. + * Extend this class to specify prefixes whose possibly-appended strings should be analysed. */ abstract class InterestingPrefix extends CompileTimeConstantExpr { /** From beaa1cffd2cf95af1d11486349fb82914474c0e7 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 19 Oct 2021 11:27:11 +0100 Subject: [PATCH 329/361] Make import private --- java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll index 10dd3a13e60..25ea3730fc4 100644 --- a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll @@ -27,7 +27,7 @@ */ import java -import semmle.code.java.dataflow.TaintTracking +private import semmle.code.java.dataflow.TaintTracking private import semmle.code.java.StringFormat /** From d46b8974929d8a0e73c00e75c73c5a11c738b25d Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 19 Oct 2021 11:32:24 +0100 Subject: [PATCH 330/361] Add explicit `this` --- java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll index 25ea3730fc4..755deaba532 100644 --- a/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/StringPrefixes.qll @@ -114,7 +114,7 @@ private class StringBuilderVarExt extends StringBuilderVar { private StringBuilderAppend getNextAppendIncludingAssignmentChains( StringBuilderConstructorOrAppend prev ) { - result = getNextAssignmentChainedAppend(prev) + result = this.getNextAssignmentChainedAppend(prev) or prev = this.getAnAssignedValue() and result = this.getAFirstAppendAfterAssignment() From c7c35401e03843c464791c44e478d77dd8c211f7 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 19 Oct 2021 12:56:23 +0200 Subject: [PATCH 331/361] C#: Remove cartesian product in stubbing (GeneratedType::getStub) --- csharp/ql/src/Stubs/Stubs.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/src/Stubs/Stubs.qll b/csharp/ql/src/Stubs/Stubs.qll index 766c8fb895c..e0c009b8783 100644 --- a/csharp/ql/src/Stubs/Stubs.qll +++ b/csharp/ql/src/Stubs/Stubs.qll @@ -128,6 +128,7 @@ abstract private class GeneratedType extends Type, GeneratedElement { /** Gets the entire C# stub code for this type. */ pragma[nomagic] final string getStub(Assembly assembly) { + this.isInAssembly(assembly) and if this.isDuplicate(assembly) then result = From 548a344d34c8a1c74ac1900543cd942a52411c0a Mon Sep 17 00:00:00 2001 From: Henry Mercer <henrymercer@github.com> Date: Tue, 19 Oct 2021 12:00:40 +0100 Subject: [PATCH 332/361] JS: Implement suggestions from review Co-authored-by: Andrew Eisenberg <aeisenberg@github.com> --- .../experimental/adaptivethreatmodeling/lib/qlpack.lock.yml | 4 ---- .../src/codeql-suites/javascript-atm-code-scanning.qls | 2 +- .../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 1 + 3 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.lock.yml diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.lock.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.lock.yml deleted file mode 100644 index 06dd07fc7dc..00000000000 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.lock.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -dependencies: {} -compiled: false -lockVersion: 1.0.0 diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls b/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls index fbd966ef5b3..2a5997e9d7a 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls @@ -1,5 +1,5 @@ - description: ATM boosted Code Scanning queries for JavaScript -- qlpack: codeql/javascript-experimental-atm-src +- queries: . - include: id: - adaptive-threat-modeling/js/nosql-injection diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml index 623593c8cec..e0463a62698 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -2,5 +2,6 @@ name: codeql/javascript-experimental-atm-src language: javascript version: 0.0.0 suites: codeql-suites +defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls dependencies: codeql/javascript-experimental-atm-lib: "*" From 70ffbae091d4fc4a832b44c4afbe9641fff091f7 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 19 Oct 2021 13:34:25 +0200 Subject: [PATCH 333/361] Introduce foldable region in CSV coverage PR comments --- misc/scripts/library-coverage/comment-pr.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/misc/scripts/library-coverage/comment-pr.py b/misc/scripts/library-coverage/comment-pr.py index 546e47f6519..28e3855abb2 100644 --- a/misc/scripts/library-coverage/comment-pr.py +++ b/misc/scripts/library-coverage/comment-pr.py @@ -25,16 +25,13 @@ def get_comment_text(output_file, repo, run_id): comment = comment_first_line + \ f"The generated reports are available in the [artifacts of this workflow run](https://github.com/{repo}/actions/runs/{run_id}). " + \ - "The differences will be picked up by the nightly job after the PR gets merged. " + "The differences will be picked up by the nightly job after the PR gets merged.\n\n" - if size < 2000: - print("There's a small change in the CSV framework coverage reports") - comment += "The following differences were found: \n\n" - with open(output_file, 'r') as file: - comment += file.read() - else: - print("There's a large change in the CSV framework coverage reports") - comment += f"The differences can be found in the {comparison_artifact_name} [artifact of this workflow run](https://github.com/{repo}/actions/runs/{run_id})." + comment += "<details><summary>Click to show differences in coverage</summary>\n\n" + with open(output_file, 'r') as file: + comment += file.read() + + comment += "</details>\n" return comment From d0eec1e3813962313f2d417a84196d37ad5da6ed Mon Sep 17 00:00:00 2001 From: haby0 <ha_yub@163.com> Date: Thu, 8 Jul 2021 19:40:42 +0800 Subject: [PATCH 334/361] Add CWE-552-UnsafeUrlForward --- .../semmle/code/java/frameworks/Servlets.qll | 12 +++ .../CWE/CWE-552/UnsafeUrlForward.java | 67 ++++++++++++++++ .../CWE/CWE-552/UnsafeUrlForward.qhelp | 32 ++++++++ .../Security/CWE/CWE-552/UnsafeUrlForward.ql | 44 +++++++++++ .../Security/CWE/CWE-552/UnsafeUrlForward.qll | 76 +++++++++++++++++++ .../CWE-552/UnsafeUrlForward.expected | 30 ++++++++ .../security/CWE-552/UnsafeUrlForward.java | 67 ++++++++++++++++ .../security/CWE-552/UnsafeUrlForward.qlref | 1 + .../query-tests/security/CWE-552/options | 1 + 9 files changed, 330 insertions(+) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.java create mode 100644 java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp create mode 100644 java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql create mode 100644 java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll create mode 100644 java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-552/options diff --git a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll index 1dd4373fb54..f68e606124d 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll @@ -191,6 +191,18 @@ class HttpServletResponseSendErrorMethod extends Method { } } +/** + * The method `getRequestDispatcher(String)` declared in `javax.servlet.http.HttpServletRequest` or `javax.servlet.ServletRequest`. + */ +class ServletRequestGetRequestDispatcherMethod extends Method { + ServletRequestGetRequestDispatcherMethod() { + getDeclaringType() instanceof ServletRequest and + hasName("getRequestDispatcher") and + getNumberOfParameters() = 1 and + getParameter(0).getType() instanceof TypeString + } +} + /** * The method `sendRedirect(String)` declared in `javax.servlet.http.HttpServletResponse`. */ diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.java b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.java new file mode 100644 index 00000000000..1e7ce3a97c5 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.java @@ -0,0 +1,67 @@ +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +public class UnsafeUrlForward { + + @GetMapping("/bad1") + public ModelAndView bad1(String url) { + return new ModelAndView(url); + } + + @GetMapping("/bad2") + public ModelAndView bad2(String url) { + ModelAndView modelAndView = new ModelAndView(); + modelAndView.setViewName(url); + return modelAndView; + } + + @GetMapping("/bad3") + public String bad3(String url) { + return "forward:" + url + "/swagger-ui/index.html"; + } + + @GetMapping("/bad4") + public ModelAndView bad4(String url) { + ModelAndView modelAndView = new ModelAndView("forward:" + url); + return modelAndView; + } + + @GetMapping("/bad5") + public void bad5(String url, HttpServletRequest request, HttpServletResponse response) { + try { + request.getRequestDispatcher(url).include(request, response); + } catch (ServletException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @GetMapping("/bad6") + public void bad6(String url, HttpServletRequest request, HttpServletResponse response) { + try { + request.getRequestDispatcher("/WEB-INF/jsp/" + url + ".jsp").include(request, response); + } catch (ServletException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @GetMapping("/good1") + public void good1(String url, HttpServletRequest request, HttpServletResponse response) { + try { + request.getRequestDispatcher("/index.jsp?token=" + url).forward(request, response); + } catch (ServletException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp new file mode 100644 index 00000000000..b220636885d --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp @@ -0,0 +1,32 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> + + +<overview> +<p>Constructing a server-side redirect path with user input could allow an attacker to download application binaries +(including application classes or jar files) or view arbitrary files within protected directories.</p> + +</overview> +<recommendation> + +<p>In order to prevent untrusted URL forwarding, it is recommended to avoid entering user input directly into the forwarding URL.</p> + +</recommendation> +<example> + +<p>The following examples show the bad case and the good case respectively. +In <code>bad1</code> method and <code>bad2</code> method and <code>bad3</code> method and +<code>bad4</code> method and <code>bad5</code> method and <code>bad6</code> method, shows an HTTP request parameter being used directly in a URL forward +without validating the input, which may cause file leakage. In <code>good1</code> method, +ordinary forwarding requests are shown, which will not cause file leakage. +</p> + +<sample src="UnsafeUrlForward.java" /> + +</example> +<references> +<li>File Disclosure: <a href="https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.file_disclosure_spring">Unsafe Url Forward</a>.</li> +</references> +</qhelp> diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql new file mode 100644 index 00000000000..704d0f92a06 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql @@ -0,0 +1,44 @@ +/** + * @name Unsafe url forward from remote source + * @description URL forward based on unvalidated user-input + * may cause file information disclosure. + * @kind path-problem + * @problem.severity error + * @precision high + * @id java/unsafe-url-forward + * @tags security + * external/cwe-552 + */ + +import java +import UnsafeUrlForward +import semmle.code.java.dataflow.FlowSources +import DataFlow::PathGraph + +class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration { + UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeUrlForwardSink } + + override predicate isSanitizer(DataFlow::Node node) { + node.getType() instanceof BoxedType + or + node.getType() instanceof PrimitiveType + or + exists(AddExpr ae | + ae.getRightOperand() = node.asExpr() and + ( + not ae.getLeftOperand().(CompileTimeConstantExpr).getStringValue().matches("/WEB-INF/%") + and + not ae.getLeftOperand().(CompileTimeConstantExpr).getStringValue() = "forward:" + ) + ) + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeUrlForwardFlowConfig conf +where conf.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Potentially untrusted URL forward due to $@.", + source.getNode(), "user-provided value" diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll new file mode 100644 index 00000000000..fb1136369c0 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll @@ -0,0 +1,76 @@ +import java +import DataFlow +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.frameworks.Servlets + +/** + * A concatenate expression using the string `forward:` on the left. + * + * E.g: `"forward:" + url` + */ +class ForwardBuilderExpr extends AddExpr { + ForwardBuilderExpr() { + this.getLeftOperand().(CompileTimeConstantExpr).getStringValue() = "forward:" + } +} + +/** + * A call to `StringBuilder.append` or `StringBuffer.append` method, and the parameter value is `"forward:"`. + * + * E.g: `StringBuilder.append("forward:")` + */ +class ForwardAppendCall extends MethodAccess { + ForwardAppendCall() { + this.getMethod().hasName("append") and + this.getMethod().getDeclaringType() instanceof StringBuildingType and + this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "forward:" + } +} + +abstract class UnsafeUrlForwardSink extends DataFlow::Node { } + +/** A Unsafe url forward sink from getRequestDispatcher method. */ +private class RequestDispatcherSink extends UnsafeUrlForwardSink { + RequestDispatcherSink() { + exists(MethodAccess ma | + ma.getMethod() instanceof ServletRequestGetRequestDispatcherMethod and + ma.getArgument(0) = this.asExpr() + ) + } +} + +/** A Unsafe url forward sink from spring controller method. */ +private class SpringUrlForwardSink extends UnsafeUrlForwardSink { + SpringUrlForwardSink() { + exists(ForwardBuilderExpr rbe | + rbe.getRightOperand() = this.asExpr() and + any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable()) + ) + or + exists(MethodAccess ma, ForwardAppendCall rac | + DataFlow2::localExprFlow(rac.getQualifier(), ma.getQualifier()) and + ma.getMethod().hasName("append") and + ma.getArgument(0) = this.asExpr() and + any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable()) + ) + or + exists(ClassInstanceExpr cie | + cie.getConstructedType().hasQualifiedName("org.springframework.web.servlet", "ModelAndView") and + ( + exists(ForwardBuilderExpr rbe | + rbe = cie.getArgument(0) and rbe.getRightOperand() = this.asExpr() + ) + or + cie.getArgument(0) = this.asExpr() + ) + ) + or + exists(MethodAccess ma | + ma.getMethod().hasName("setViewName") and + ma.getMethod() + .getDeclaringType() + .hasQualifiedName("org.springframework.web.servlet", "ModelAndView") and + ma.getArgument(0) = this.asExpr() + ) + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected new file mode 100644 index 00000000000..5b9c80ff598 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected @@ -0,0 +1,30 @@ +edges +| UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url | +| UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url | +| UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url | +| UnsafeUrlForward.java:30:27:30:36 | url : String | UnsafeUrlForward.java:31:48:31:63 | ... + ... | +| UnsafeUrlForward.java:30:27:30:36 | url : String | UnsafeUrlForward.java:31:61:31:63 | url | +| UnsafeUrlForward.java:36:19:36:28 | url : String | UnsafeUrlForward.java:38:33:38:35 | url | +| UnsafeUrlForward.java:47:19:47:28 | url : String | UnsafeUrlForward.java:49:33:49:62 | ... + ... | +nodes +| UnsafeUrlForward.java:13:27:13:36 | url : String | semmle.label | url : String | +| UnsafeUrlForward.java:14:27:14:29 | url | semmle.label | url | +| UnsafeUrlForward.java:18:27:18:36 | url : String | semmle.label | url : String | +| UnsafeUrlForward.java:20:28:20:30 | url | semmle.label | url | +| UnsafeUrlForward.java:25:21:25:30 | url : String | semmle.label | url : String | +| UnsafeUrlForward.java:26:23:26:25 | url | semmle.label | url | +| UnsafeUrlForward.java:30:27:30:36 | url : String | semmle.label | url : String | +| UnsafeUrlForward.java:31:48:31:63 | ... + ... | semmle.label | ... + ... | +| UnsafeUrlForward.java:31:61:31:63 | url | semmle.label | url | +| UnsafeUrlForward.java:36:19:36:28 | url : String | semmle.label | url : String | +| UnsafeUrlForward.java:38:33:38:35 | url | semmle.label | url | +| UnsafeUrlForward.java:47:19:47:28 | url : String | semmle.label | url : String | +| UnsafeUrlForward.java:49:33:49:62 | ... + ... | semmle.label | ... + ... | +#select +| UnsafeUrlForward.java:14:27:14:29 | url | UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:13:27:13:36 | url | user-provided value | +| UnsafeUrlForward.java:20:28:20:30 | url | UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:18:27:18:36 | url | user-provided value | +| UnsafeUrlForward.java:26:23:26:25 | url | UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:25:21:25:30 | url | user-provided value | +| UnsafeUrlForward.java:31:48:31:63 | ... + ... | UnsafeUrlForward.java:30:27:30:36 | url : String | UnsafeUrlForward.java:31:48:31:63 | ... + ... | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:30:27:30:36 | url | user-provided value | +| UnsafeUrlForward.java:31:61:31:63 | url | UnsafeUrlForward.java:30:27:30:36 | url : String | UnsafeUrlForward.java:31:61:31:63 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:30:27:30:36 | url | user-provided value | +| UnsafeUrlForward.java:38:33:38:35 | url | UnsafeUrlForward.java:36:19:36:28 | url : String | UnsafeUrlForward.java:38:33:38:35 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:36:19:36:28 | url | user-provided value | +| UnsafeUrlForward.java:49:33:49:62 | ... + ... | UnsafeUrlForward.java:47:19:47:28 | url : String | UnsafeUrlForward.java:49:33:49:62 | ... + ... | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:47:19:47:28 | url | user-provided value | diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.java b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.java new file mode 100644 index 00000000000..1e7ce3a97c5 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.java @@ -0,0 +1,67 @@ +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +public class UnsafeUrlForward { + + @GetMapping("/bad1") + public ModelAndView bad1(String url) { + return new ModelAndView(url); + } + + @GetMapping("/bad2") + public ModelAndView bad2(String url) { + ModelAndView modelAndView = new ModelAndView(); + modelAndView.setViewName(url); + return modelAndView; + } + + @GetMapping("/bad3") + public String bad3(String url) { + return "forward:" + url + "/swagger-ui/index.html"; + } + + @GetMapping("/bad4") + public ModelAndView bad4(String url) { + ModelAndView modelAndView = new ModelAndView("forward:" + url); + return modelAndView; + } + + @GetMapping("/bad5") + public void bad5(String url, HttpServletRequest request, HttpServletResponse response) { + try { + request.getRequestDispatcher(url).include(request, response); + } catch (ServletException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @GetMapping("/bad6") + public void bad6(String url, HttpServletRequest request, HttpServletResponse response) { + try { + request.getRequestDispatcher("/WEB-INF/jsp/" + url + ".jsp").include(request, response); + } catch (ServletException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @GetMapping("/good1") + public void good1(String url, HttpServletRequest request, HttpServletResponse response) { + try { + request.getRequestDispatcher("/index.jsp?token=" + url).forward(request, response); + } catch (ServletException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.qlref b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.qlref new file mode 100644 index 00000000000..2e4cb5e726a --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/options b/java/ql/test/experimental/query-tests/security/CWE-552/options new file mode 100644 index 00000000000..a9289108747 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-552/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/springframework-5.2.3/ \ No newline at end of file From 952b34a163f8bbdc5b5376c937f26e7d17a3fa5f Mon Sep 17 00:00:00 2001 From: haby0 <ha_yub@163.com> Date: Thu, 16 Sep 2021 20:14:12 +0800 Subject: [PATCH 335/361] Eliminate FP --- .../Security/CWE/CWE-552/UnsafeUrlForward.ql | 30 ++++++++++++++++--- .../Security/CWE/CWE-552/UnsafeUrlForward.qll | 12 ++++++-- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql index 704d0f92a06..35d33dc8a84 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql @@ -1,6 +1,6 @@ /** * @name Unsafe url forward from remote source - * @description URL forward based on unvalidated user-input + * @description URL forward based on unvalidated user-input * may cause file information disclosure. * @kind path-problem * @problem.severity error @@ -18,7 +18,16 @@ import DataFlow::PathGraph class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration { UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + override predicate isSource(DataFlow::Node source) { + source instanceof RemoteFlowSource and + not exists(MethodAccess ma | + ma.getMethod().getName() in ["getRequestURI", "getRequestURL", "getPathInfo"] and + ma.getMethod() + .getDeclaringType() + .getASupertype*() + .hasQualifiedName("javax.servlet.http", "HttpServletRequest") + ) + } override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeUrlForwardSink } @@ -30,11 +39,24 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration { exists(AddExpr ae | ae.getRightOperand() = node.asExpr() and ( - not ae.getLeftOperand().(CompileTimeConstantExpr).getStringValue().matches("/WEB-INF/%") - and + not ae.getLeftOperand().(CompileTimeConstantExpr).getStringValue().matches("/WEB-INF/%") and not ae.getLeftOperand().(CompileTimeConstantExpr).getStringValue() = "forward:" ) ) + or + exists(MethodAccess ma, int i | + ma.getMethod().hasName("format") and + ma.getMethod().getDeclaringType() instanceof TypeString and + ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "redirect:" and + ma.getArgument(i) = node.asExpr() and + i != 0 + ) + or + exists(StringBuilderAppendCall ma1, StringBuilderAppendCall ma2 | + DataFlow2::localExprFlow(ma1.getQualifier(), ma2.getQualifier()) and + ma1.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "redirect:" and + ma2.getArgument(0) = node.asExpr() + ) } } diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll index fb1136369c0..019712a69e6 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll @@ -3,6 +3,14 @@ import DataFlow import semmle.code.java.dataflow.FlowSources import semmle.code.java.frameworks.Servlets +/** A call to `StringBuilder.append` method. */ +class StringBuilderAppendCall extends MethodAccess { + StringBuilderAppendCall() { + this.getMethod().hasName("append") and + this.getMethod().getDeclaringType() instanceof StringBuildingType + } +} + /** * A concatenate expression using the string `forward:` on the left. * @@ -19,10 +27,8 @@ class ForwardBuilderExpr extends AddExpr { * * E.g: `StringBuilder.append("forward:")` */ -class ForwardAppendCall extends MethodAccess { +class ForwardAppendCall extends StringBuilderAppendCall { ForwardAppendCall() { - this.getMethod().hasName("append") and - this.getMethod().getDeclaringType() instanceof StringBuildingType and this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "forward:" } } From 679652e63aa55a216770e5c95e86faad12f9d8ff Mon Sep 17 00:00:00 2001 From: haby0 <ha_yub@163.com> Date: Fri, 24 Sep 2021 11:52:50 +0800 Subject: [PATCH 336/361] Modify Sanitizer --- .../Security/CWE/CWE-552/UnsafeUrlForward.ql | 45 +++--- .../Security/CWE/CWE-552/UnsafeUrlForward.qll | 142 +++++++++++++++++- .../CWE-552/UnsafeUrlForward.expected | 1 + .../query-tests/security/CWE-552/options | 2 +- 4 files changed, 156 insertions(+), 34 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql index 35d33dc8a84..6fb5d164ff9 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql @@ -15,6 +15,18 @@ import UnsafeUrlForward import semmle.code.java.dataflow.FlowSources import DataFlow::PathGraph +private class StartsWithSanitizer extends DataFlow::BarrierGuard { + StartsWithSanitizer() { + this.(MethodAccess).getMethod().hasName("startsWith") and + this.(MethodAccess).getMethod().getDeclaringType() instanceof TypeString and + this.(MethodAccess).getMethod().getNumberOfParameters() = 1 + } + + override predicate checks(Expr e, boolean branch) { + e = this.(MethodAccess).getQualifier() and branch = true + } +} + class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration { UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" } @@ -25,39 +37,18 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration { ma.getMethod() .getDeclaringType() .getASupertype*() - .hasQualifiedName("javax.servlet.http", "HttpServletRequest") + .hasQualifiedName("javax.servlet.http", "HttpServletRequest") and + ma = source.asExpr() ) } override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeUrlForwardSink } - override predicate isSanitizer(DataFlow::Node node) { - node.getType() instanceof BoxedType - or - node.getType() instanceof PrimitiveType - or - exists(AddExpr ae | - ae.getRightOperand() = node.asExpr() and - ( - not ae.getLeftOperand().(CompileTimeConstantExpr).getStringValue().matches("/WEB-INF/%") and - not ae.getLeftOperand().(CompileTimeConstantExpr).getStringValue() = "forward:" - ) - ) - or - exists(MethodAccess ma, int i | - ma.getMethod().hasName("format") and - ma.getMethod().getDeclaringType() instanceof TypeString and - ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "redirect:" and - ma.getArgument(i) = node.asExpr() and - i != 0 - ) - or - exists(StringBuilderAppendCall ma1, StringBuilderAppendCall ma2 | - DataFlow2::localExprFlow(ma1.getQualifier(), ma2.getQualifier()) and - ma1.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "redirect:" and - ma2.getArgument(0) = node.asExpr() - ) + override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { + guard instanceof StartsWithSanitizer } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof UnsafeUrlForwardSanitizer } } from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeUrlForwardFlowConfig conf diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll index 019712a69e6..6926518b448 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll @@ -3,11 +3,141 @@ import DataFlow import semmle.code.java.dataflow.FlowSources import semmle.code.java.frameworks.Servlets +/** A sanitizer for unsafe url forward vulnerabilities. */ +abstract class UnsafeUrlForwardSanitizer extends DataFlow::Node { } + +private class PrimitiveSanitizer extends UnsafeUrlForwardSanitizer { + PrimitiveSanitizer() { + this.getType() instanceof PrimitiveType or + this.getType() instanceof BoxedType or + this.getType() instanceof NumberType + } +} + +private class UnsafeUrlForwardSantizer extends UnsafeUrlForwardSanitizer { + UnsafeUrlForwardSantizer() { this.asExpr() instanceof UnsafeUrlForwardSanitizedExpr } +} + +private class UnsafeUrlForwardSanitizingConstantPrefix extends CompileTimeConstantExpr { + UnsafeUrlForwardSanitizingConstantPrefix() { + not this.getStringValue().matches("/WEB-INF/%") and + not this.getStringValue() = "forward:" + } +} + +private Expr getAUnsafeUrlForwardSanitizingPrefix() { + result instanceof UnsafeUrlForwardSanitizingConstantPrefix + or + result.(AddExpr).getAnOperand() = getAUnsafeUrlForwardSanitizingPrefix() +} + /** A call to `StringBuilder.append` method. */ -class StringBuilderAppendCall extends MethodAccess { - StringBuilderAppendCall() { - this.getMethod().hasName("append") and - this.getMethod().getDeclaringType() instanceof StringBuildingType +class StringBuilderAppend extends MethodAccess { + StringBuilderAppend() { + this.getMethod().getDeclaringType() instanceof StringBuildingType and + this.getMethod().hasName("append") + } +} + +private Expr getQualifier(Expr e) { result = e.(MethodAccess).getQualifier() } + +/** + * An extension of `StringBuilderVar` that also accounts for strings appended in StringBuilder/Buffer's constructor + * and in `append` calls chained onto the constructor call. + * + * The original `StringBuilderVar` doesn't care about these because it is designed to model taint, and + * in taint rules terms these are not needed, as the connection between construction, appends and the + * eventual `toString` is more obvious. + */ +private class StringBuilderVarExt extends StringBuilderVar { + /** + * Returns a first assignment after this StringBuilderVar is first assigned. + * + * For example, for `StringBuilder sbv = new StringBuilder("1").append("2"); sbv.append("3").append("4");` + * this returns the append of `"3"`. + */ + private StringBuilderAppend getAFirstAppendAfterAssignment() { + result = this.getAnAppend() and not result = this.getNextAppend(_) + } + + /** + * Gets the next `append` after `prev`, where `prev` is, perhaps after some more `append` or other + * chained calls, assigned to this `StringBuilderVar`. + */ + private StringBuilderAppend getNextAssignmentChainedAppend(StringBuilderConstructorOrAppend prev) { + getQualifier*(result) = this.getAnAssignedValue() and + result.getQualifier() = prev + } + + /** + * Get a constructor call or `append` call that contributes a string to this string builder. + */ + StringBuilderConstructorOrAppend getAConstructorOrAppend() { + exists(this.getNextAssignmentChainedAppend(result)) or + result = this.getAnAssignedValue() or + result = this.getAnAppend() + } + + /** + * Like `StringBuilderVar.getNextAppend`, except including appends and constructors directly + * assigned to this `StringBuilderVar`. + */ + private StringBuilderAppend getNextAppendIncludingAssignmentChains( + StringBuilderConstructorOrAppend prev + ) { + result = getNextAssignmentChainedAppend(prev) + or + prev = this.getAnAssignedValue() and + result = this.getAFirstAppendAfterAssignment() + or + result = this.getNextAppend(prev) + } + + /** + * Implements `StringBuilderVarExt.getNextAppendIncludingAssignmentChains+(prev)`. + */ + pragma[nomagic] + StringBuilderAppend getSubsequentAppendIncludingAssignmentChains( + StringBuilderConstructorOrAppend prev + ) { + result = this.getNextAppendIncludingAssignmentChains(prev) or + result = + this.getSubsequentAppendIncludingAssignmentChains(this.getNextAppendIncludingAssignmentChains(prev)) + } +} + +private class StringBuilderConstructorOrAppend extends Call { + StringBuilderConstructorOrAppend() { + this instanceof StringBuilderAppend or + this.(ClassInstanceExpr).getConstructedType() instanceof StringBuildingType + } +} + +private class UnsafeUrlForwardSanitizedExpr extends Expr { + UnsafeUrlForwardSanitizedExpr() { + // Sanitize expressions that come after a sanitizing prefix in a tree of string additions: + this = + any(AddExpr add | add.getLeftOperand() = getAUnsafeUrlForwardSanitizingPrefix()) + .getRightOperand() + or + // Sanitize expressions that come after a sanitizing prefix in a sequence of StringBuilder operations: + exists( + StringBuilderConstructorOrAppend appendSanitizingConstant, + StringBuilderAppend subsequentAppend, StringBuilderVarExt v + | + appendSanitizingConstant = v.getAConstructorOrAppend() and + appendSanitizingConstant.getArgument(0) = getAUnsafeUrlForwardSanitizingPrefix() and + v.getSubsequentAppendIncludingAssignmentChains(appendSanitizingConstant) = subsequentAppend and + this = subsequentAppend.getArgument(0) + ) + or + exists(MethodAccess ma, int i | + ma.getMethod().hasName("format") and + ma.getMethod().getDeclaringType() instanceof TypeString and + ma.getArgument(0) instanceof UnsafeUrlForwardSanitizingConstantPrefix and + ma.getArgument(i) = this and + i != 0 + ) } } @@ -16,7 +146,7 @@ class StringBuilderAppendCall extends MethodAccess { * * E.g: `"forward:" + url` */ -class ForwardBuilderExpr extends AddExpr { +private class ForwardBuilderExpr extends AddExpr { ForwardBuilderExpr() { this.getLeftOperand().(CompileTimeConstantExpr).getStringValue() = "forward:" } @@ -27,7 +157,7 @@ class ForwardBuilderExpr extends AddExpr { * * E.g: `StringBuilder.append("forward:")` */ -class ForwardAppendCall extends StringBuilderAppendCall { +private class ForwardAppendCall extends StringBuilderAppend { ForwardAppendCall() { this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "forward:" } diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected index 5b9c80ff598..b70a131f93c 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected @@ -20,6 +20,7 @@ nodes | UnsafeUrlForward.java:38:33:38:35 | url | semmle.label | url | | UnsafeUrlForward.java:47:19:47:28 | url : String | semmle.label | url : String | | UnsafeUrlForward.java:49:33:49:62 | ... + ... | semmle.label | ... + ... | +subpaths #select | UnsafeUrlForward.java:14:27:14:29 | url | UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:13:27:13:36 | url | user-provided value | | UnsafeUrlForward.java:20:28:20:30 | url | UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:18:27:18:36 | url | user-provided value | diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/options b/java/ql/test/experimental/query-tests/security/CWE-552/options index a9289108747..ba166b547a0 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-552/options +++ b/java/ql/test/experimental/query-tests/security/CWE-552/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/springframework-5.2.3/ \ No newline at end of file +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/springframework-5.3.8/ \ No newline at end of file From 283376eb199cda013a6023a9edaae8490d0846ae Mon Sep 17 00:00:00 2001 From: haby0 <ha_yub@163.com> Date: Tue, 28 Sep 2021 09:42:21 +0800 Subject: [PATCH 337/361] Modify the model --- .../lib/semmle/code/java/frameworks/Servlets.qll | 10 ++++------ .../Security/CWE/CWE-552/UnsafeUrlForward.ql | 13 +++++++------ .../Security/CWE/CWE-552/UnsafeUrlForward.qll | 15 +++++---------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll index f68e606124d..76c82b37786 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll @@ -74,7 +74,7 @@ library class HttpServletRequestGetQueryStringMethod extends Method { /** * The method `getPathInfo()` declared in `javax.servlet.http.HttpServletRequest`. */ -library class HttpServletRequestGetPathMethod extends Method { +class HttpServletRequestGetPathMethod extends Method { HttpServletRequestGetPathMethod() { getDeclaringType() instanceof HttpServletRequest and hasName("getPathInfo") and @@ -120,7 +120,7 @@ library class HttpServletRequestGetHeaderNamesMethod extends Method { /** * The method `getRequestURL()` declared in `javax.servlet.http.HttpServletRequest`. */ -library class HttpServletRequestGetRequestURLMethod extends Method { +class HttpServletRequestGetRequestURLMethod extends Method { HttpServletRequestGetRequestURLMethod() { getDeclaringType() instanceof HttpServletRequest and hasName("getRequestURL") and @@ -131,7 +131,7 @@ library class HttpServletRequestGetRequestURLMethod extends Method { /** * The method `getRequestURI()` declared in `javax.servlet.http.HttpServletRequest`. */ -library class HttpServletRequestGetRequestURIMethod extends Method { +class HttpServletRequestGetRequestURIMethod extends Method { HttpServletRequestGetRequestURIMethod() { getDeclaringType() instanceof HttpServletRequest and hasName("getRequestURI") and @@ -197,9 +197,7 @@ class HttpServletResponseSendErrorMethod extends Method { class ServletRequestGetRequestDispatcherMethod extends Method { ServletRequestGetRequestDispatcherMethod() { getDeclaringType() instanceof ServletRequest and - hasName("getRequestDispatcher") and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + hasName("getRequestDispatcher") } } diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql index 6fb5d164ff9..f9f13f72886 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql @@ -13,6 +13,7 @@ import java import UnsafeUrlForward import semmle.code.java.dataflow.FlowSources +import semmle.code.java.frameworks.Servlets import DataFlow::PathGraph private class StartsWithSanitizer extends DataFlow::BarrierGuard { @@ -32,12 +33,12 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource and - not exists(MethodAccess ma | - ma.getMethod().getName() in ["getRequestURI", "getRequestURL", "getPathInfo"] and - ma.getMethod() - .getDeclaringType() - .getASupertype*() - .hasQualifiedName("javax.servlet.http", "HttpServletRequest") and + not exists(MethodAccess ma, Method m | ma.getMethod() = m | + ( + m instanceof HttpServletRequestGetRequestURIMethod or + m instanceof HttpServletRequestGetRequestURLMethod or + m instanceof HttpServletRequestGetPathMethod + ) and ma = source.asExpr() ) } diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll index 6926518b448..d092c488833 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll @@ -2,6 +2,7 @@ import java import DataFlow import semmle.code.java.dataflow.FlowSources import semmle.code.java.frameworks.Servlets +import semmle.code.java.frameworks.spring.SpringWeb /** A sanitizer for unsafe url forward vulnerabilities. */ abstract class UnsafeUrlForwardSanitizer extends DataFlow::Node { } @@ -144,7 +145,7 @@ private class UnsafeUrlForwardSanitizedExpr extends Expr { /** * A concatenate expression using the string `forward:` on the left. * - * E.g: `"forward:" + url` + * For example, `"forward:" + url`. */ private class ForwardBuilderExpr extends AddExpr { ForwardBuilderExpr() { @@ -155,7 +156,7 @@ private class ForwardBuilderExpr extends AddExpr { /** * A call to `StringBuilder.append` or `StringBuffer.append` method, and the parameter value is `"forward:"`. * - * E.g: `StringBuilder.append("forward:")` + * For example, `StringBuilder.append("forward:")`. */ private class ForwardAppendCall extends StringBuilderAppend { ForwardAppendCall() { @@ -191,7 +192,7 @@ private class SpringUrlForwardSink extends UnsafeUrlForwardSink { ) or exists(ClassInstanceExpr cie | - cie.getConstructedType().hasQualifiedName("org.springframework.web.servlet", "ModelAndView") and + cie.getConstructedType() instanceof ModelAndView and ( exists(ForwardBuilderExpr rbe | rbe = cie.getArgument(0) and rbe.getRightOperand() = this.asExpr() @@ -201,12 +202,6 @@ private class SpringUrlForwardSink extends UnsafeUrlForwardSink { ) ) or - exists(MethodAccess ma | - ma.getMethod().hasName("setViewName") and - ma.getMethod() - .getDeclaringType() - .hasQualifiedName("org.springframework.web.servlet", "ModelAndView") and - ma.getArgument(0) = this.asExpr() - ) + exists(SpringModelAndViewSetViewNameCall smavsvnc | smavsvnc.getArgument(0) = this.asExpr()) } } From 9d9a7abd0635a83c2264cc3aceea8d001d3d562b Mon Sep 17 00:00:00 2001 From: haby0 <ha_yub@163.com> Date: Fri, 8 Oct 2021 12:12:21 +0800 Subject: [PATCH 338/361] Fix --- .../CWE/CWE-552/UnsafeUrlForward.java | 31 +------ .../CWE/CWE-552/UnsafeUrlForward.qhelp | 3 +- .../Security/CWE/CWE-552/UnsafeUrlForward.qll | 83 +------------------ 3 files changed, 3 insertions(+), 114 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.java b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.java index 1e7ce3a97c5..d159c405736 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.java +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.java @@ -15,36 +15,7 @@ public class UnsafeUrlForward { } @GetMapping("/bad2") - public ModelAndView bad2(String url) { - ModelAndView modelAndView = new ModelAndView(); - modelAndView.setViewName(url); - return modelAndView; - } - - @GetMapping("/bad3") - public String bad3(String url) { - return "forward:" + url + "/swagger-ui/index.html"; - } - - @GetMapping("/bad4") - public ModelAndView bad4(String url) { - ModelAndView modelAndView = new ModelAndView("forward:" + url); - return modelAndView; - } - - @GetMapping("/bad5") - public void bad5(String url, HttpServletRequest request, HttpServletResponse response) { - try { - request.getRequestDispatcher(url).include(request, response); - } catch (ServletException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @GetMapping("/bad6") - public void bad6(String url, HttpServletRequest request, HttpServletResponse response) { + public void bad2(String url, HttpServletRequest request, HttpServletResponse response) { try { request.getRequestDispatcher("/WEB-INF/jsp/" + url + ".jsp").include(request, response); } catch (ServletException e) { diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp index b220636885d..d3cd0297fdd 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp @@ -17,8 +17,7 @@ <example> <p>The following examples show the bad case and the good case respectively. -In <code>bad1</code> method and <code>bad2</code> method and <code>bad3</code> method and -<code>bad4</code> method and <code>bad5</code> method and <code>bad6</code> method, shows an HTTP request parameter being used directly in a URL forward +The <code>bad</code> methods show an HTTP request parameter being used directly in a URL forward without validating the input, which may cause file leakage. In <code>good1</code> method, ordinary forwarding requests are shown, which will not cause file leakage. </p> diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll index d092c488833..d125d79aa2f 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll @@ -3,6 +3,7 @@ import DataFlow import semmle.code.java.dataflow.FlowSources import semmle.code.java.frameworks.Servlets import semmle.code.java.frameworks.spring.SpringWeb +import semmle.code.java.security.RequestForgery /** A sanitizer for unsafe url forward vulnerabilities. */ abstract class UnsafeUrlForwardSanitizer extends DataFlow::Node { } @@ -32,88 +33,6 @@ private Expr getAUnsafeUrlForwardSanitizingPrefix() { result.(AddExpr).getAnOperand() = getAUnsafeUrlForwardSanitizingPrefix() } -/** A call to `StringBuilder.append` method. */ -class StringBuilderAppend extends MethodAccess { - StringBuilderAppend() { - this.getMethod().getDeclaringType() instanceof StringBuildingType and - this.getMethod().hasName("append") - } -} - -private Expr getQualifier(Expr e) { result = e.(MethodAccess).getQualifier() } - -/** - * An extension of `StringBuilderVar` that also accounts for strings appended in StringBuilder/Buffer's constructor - * and in `append` calls chained onto the constructor call. - * - * The original `StringBuilderVar` doesn't care about these because it is designed to model taint, and - * in taint rules terms these are not needed, as the connection between construction, appends and the - * eventual `toString` is more obvious. - */ -private class StringBuilderVarExt extends StringBuilderVar { - /** - * Returns a first assignment after this StringBuilderVar is first assigned. - * - * For example, for `StringBuilder sbv = new StringBuilder("1").append("2"); sbv.append("3").append("4");` - * this returns the append of `"3"`. - */ - private StringBuilderAppend getAFirstAppendAfterAssignment() { - result = this.getAnAppend() and not result = this.getNextAppend(_) - } - - /** - * Gets the next `append` after `prev`, where `prev` is, perhaps after some more `append` or other - * chained calls, assigned to this `StringBuilderVar`. - */ - private StringBuilderAppend getNextAssignmentChainedAppend(StringBuilderConstructorOrAppend prev) { - getQualifier*(result) = this.getAnAssignedValue() and - result.getQualifier() = prev - } - - /** - * Get a constructor call or `append` call that contributes a string to this string builder. - */ - StringBuilderConstructorOrAppend getAConstructorOrAppend() { - exists(this.getNextAssignmentChainedAppend(result)) or - result = this.getAnAssignedValue() or - result = this.getAnAppend() - } - - /** - * Like `StringBuilderVar.getNextAppend`, except including appends and constructors directly - * assigned to this `StringBuilderVar`. - */ - private StringBuilderAppend getNextAppendIncludingAssignmentChains( - StringBuilderConstructorOrAppend prev - ) { - result = getNextAssignmentChainedAppend(prev) - or - prev = this.getAnAssignedValue() and - result = this.getAFirstAppendAfterAssignment() - or - result = this.getNextAppend(prev) - } - - /** - * Implements `StringBuilderVarExt.getNextAppendIncludingAssignmentChains+(prev)`. - */ - pragma[nomagic] - StringBuilderAppend getSubsequentAppendIncludingAssignmentChains( - StringBuilderConstructorOrAppend prev - ) { - result = this.getNextAppendIncludingAssignmentChains(prev) or - result = - this.getSubsequentAppendIncludingAssignmentChains(this.getNextAppendIncludingAssignmentChains(prev)) - } -} - -private class StringBuilderConstructorOrAppend extends Call { - StringBuilderConstructorOrAppend() { - this instanceof StringBuilderAppend or - this.(ClassInstanceExpr).getConstructedType() instanceof StringBuildingType - } -} - private class UnsafeUrlForwardSanitizedExpr extends Expr { UnsafeUrlForwardSanitizedExpr() { // Sanitize expressions that come after a sanitizing prefix in a tree of string additions: From 8a4fa0a7e2259bcac75fed23637b9c8b09af2a12 Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 12 Oct 2021 15:33:59 +0100 Subject: [PATCH 339/361] Copyedit --- .../experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp index d3cd0297fdd..572b14bb02f 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp @@ -11,7 +11,7 @@ </overview> <recommendation> -<p>In order to prevent untrusted URL forwarding, it is recommended to avoid entering user input directly into the forwarding URL.</p> +<p>In order to prevent untrusted URL forwarding, it is recommended to avoid concatenating user input directly into the forwarding URL.</p> </recommendation> <example> From 057d0fb7e0d2cc0577a779c0c9f160083789868a Mon Sep 17 00:00:00 2001 From: Chris Smowton <smowton@github.com> Date: Tue, 19 Oct 2021 14:45:38 +0100 Subject: [PATCH 340/361] Rewrite query to use shared StringPrefixes library --- .../Security/CWE/CWE-552/UnsafeUrlForward.qll | 112 +++++------------- 1 file changed, 29 insertions(+), 83 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll index d125d79aa2f..f2656316203 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll @@ -4,6 +4,7 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.frameworks.Servlets import semmle.code.java.frameworks.spring.SpringWeb import semmle.code.java.security.RequestForgery +private import semmle.code.java.dataflow.StringPrefixes /** A sanitizer for unsafe url forward vulnerabilities. */ abstract class UnsafeUrlForwardSanitizer extends DataFlow::Node { } @@ -16,76 +17,22 @@ private class PrimitiveSanitizer extends UnsafeUrlForwardSanitizer { } } -private class UnsafeUrlForwardSantizer extends UnsafeUrlForwardSanitizer { - UnsafeUrlForwardSantizer() { this.asExpr() instanceof UnsafeUrlForwardSanitizedExpr } -} - -private class UnsafeUrlForwardSanitizingConstantPrefix extends CompileTimeConstantExpr { - UnsafeUrlForwardSanitizingConstantPrefix() { +private class SanitizingPrefix extends InterestingPrefix { + SanitizingPrefix() { not this.getStringValue().matches("/WEB-INF/%") and not this.getStringValue() = "forward:" } + + override int getOffset() { result = 0 } } -private Expr getAUnsafeUrlForwardSanitizingPrefix() { - result instanceof UnsafeUrlForwardSanitizingConstantPrefix - or - result.(AddExpr).getAnOperand() = getAUnsafeUrlForwardSanitizingPrefix() -} - -private class UnsafeUrlForwardSanitizedExpr extends Expr { - UnsafeUrlForwardSanitizedExpr() { - // Sanitize expressions that come after a sanitizing prefix in a tree of string additions: - this = - any(AddExpr add | add.getLeftOperand() = getAUnsafeUrlForwardSanitizingPrefix()) - .getRightOperand() - or - // Sanitize expressions that come after a sanitizing prefix in a sequence of StringBuilder operations: - exists( - StringBuilderConstructorOrAppend appendSanitizingConstant, - StringBuilderAppend subsequentAppend, StringBuilderVarExt v - | - appendSanitizingConstant = v.getAConstructorOrAppend() and - appendSanitizingConstant.getArgument(0) = getAUnsafeUrlForwardSanitizingPrefix() and - v.getSubsequentAppendIncludingAssignmentChains(appendSanitizingConstant) = subsequentAppend and - this = subsequentAppend.getArgument(0) - ) - or - exists(MethodAccess ma, int i | - ma.getMethod().hasName("format") and - ma.getMethod().getDeclaringType() instanceof TypeString and - ma.getArgument(0) instanceof UnsafeUrlForwardSanitizingConstantPrefix and - ma.getArgument(i) = this and - i != 0 - ) - } -} - -/** - * A concatenate expression using the string `forward:` on the left. - * - * For example, `"forward:" + url`. - */ -private class ForwardBuilderExpr extends AddExpr { - ForwardBuilderExpr() { - this.getLeftOperand().(CompileTimeConstantExpr).getStringValue() = "forward:" - } -} - -/** - * A call to `StringBuilder.append` or `StringBuffer.append` method, and the parameter value is `"forward:"`. - * - * For example, `StringBuilder.append("forward:")`. - */ -private class ForwardAppendCall extends StringBuilderAppend { - ForwardAppendCall() { - this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "forward:" - } +private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer { + FollowsSanitizingPrefix() { this.asExpr() = any(SanitizingPrefix fp).getAnAppendedExpression() } } abstract class UnsafeUrlForwardSink extends DataFlow::Node { } -/** A Unsafe url forward sink from getRequestDispatcher method. */ +/** An argument to `ServletRequest.getRequestDispatcher`. */ private class RequestDispatcherSink extends UnsafeUrlForwardSink { RequestDispatcherSink() { exists(MethodAccess ma | @@ -95,32 +42,31 @@ private class RequestDispatcherSink extends UnsafeUrlForwardSink { } } -/** A Unsafe url forward sink from spring controller method. */ -private class SpringUrlForwardSink extends UnsafeUrlForwardSink { - SpringUrlForwardSink() { - exists(ForwardBuilderExpr rbe | - rbe.getRightOperand() = this.asExpr() and - any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable()) - ) - or - exists(MethodAccess ma, ForwardAppendCall rac | - DataFlow2::localExprFlow(rac.getQualifier(), ma.getQualifier()) and - ma.getMethod().hasName("append") and - ma.getArgument(0) = this.asExpr() and - any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable()) - ) - or +/** An argument to `new ModelAndView` or `ModelAndView.setViewName`. */ +private class SpringModelAndViewSink extends UnsafeUrlForwardSink { + SpringModelAndViewSink() { exists(ClassInstanceExpr cie | cie.getConstructedType() instanceof ModelAndView and - ( - exists(ForwardBuilderExpr rbe | - rbe = cie.getArgument(0) and rbe.getRightOperand() = this.asExpr() - ) - or - cie.getArgument(0) = this.asExpr() - ) + cie.getArgument(0) = this.asExpr() ) or exists(SpringModelAndViewSetViewNameCall smavsvnc | smavsvnc.getArgument(0) = this.asExpr()) } } + +private class ForwardPrefix extends InterestingPrefix { + ForwardPrefix() { this.getStringValue() = "forward:" } + + override int getOffset() { result = 0 } +} + +/** + * An expression appended (perhaps indirectly) to `"forward:"`, and which + * is reachable from a Spring entry point. + */ +private class SpringUrlForwardSink extends UnsafeUrlForwardSink { + SpringUrlForwardSink() { + any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable()) and + this.asExpr() = any(ForwardPrefix fp).getAnAppendedExpression() + } +} From 38257a58f04276bacd8065e219a2f665294a44da Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 19 Oct 2021 15:01:32 +0100 Subject: [PATCH 341/361] C++: Fix unbound variables in PrivateCleartextWrite.qll. --- .../semmle/code/cpp/security/PrivateCleartextWrite.qll | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll b/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll index 922dadaa20e..5438722fd08 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll @@ -52,11 +52,8 @@ module PrivateCleartextWrite { class WriteSink extends Sink { WriteSink() { - exists(FileWrite f, BufferWrite b | - this.asExpr() = f.getASource() - or - this.asExpr() = b.getAChild() - ) + this.asExpr() = any(FileWrite f).getASource() or + this.asExpr() = any(BufferWrite b).getAChild() } } } From 112d408fb94207a037507b87ef2e8d4a4313f7ae Mon Sep 17 00:00:00 2001 From: Calum Grant <calumgrant@github.com> Date: Tue, 19 Oct 2021 16:30:54 +0100 Subject: [PATCH 342/361] Address review comments. --- .../codeql-language-guides/basic-query-for-ruby-code.rst | 6 ++---- .../codeql-language-guides/codeql-library-for-ruby.rst | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst index d30064c1ec9..7f0e6c79b12 100644 --- a/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst @@ -108,14 +108,12 @@ Browsing the results of our basic query shows that it could be improved. Among t .. code-block:: ruby - if ... - ... - elsif option == "-verbose" + if option == "-verbose" # nothing to do - handled earlier else error "unrecognized option" -In this case, identifying the ``if`` statement with the empty ``then`` branch as redundant is a false positive. One solution to this is to modify the query to ignore empty ``then`` branches if the ``if`` statement has an ``else`` branch. +In this case, identifying the ``if`` statement with the empty ``then`` branch as redundant is a false positive. One solution to this is to modify the query to select ``if`` statements where both the ``then`` and ``else`` branches are missing. To exclude ``if`` statements that have an ``else`` branch: diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index 1119159314f..ede3182fd56 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -73,7 +73,7 @@ The CodeQL examples in this article are only excerpts and are not meant to repre Abstract syntax --------------- -The abstract syntax tree (AST) represents the elements of the source code organized into a tree. The AST viewer +The abstract syntax tree (AST) represents the elements of the source code organized into a tree. The `AST viewer <https://codeql.github.com/docs/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code/>`__ in Visual Studio Code shows the AST nodes, including the relevant CodeQL classes and predicates. All CodeQL AST classes inherit from the `AstNode` class, which provides the following member predicates From d4b18fe6a3d85fcb15a926c7d787bbef75a4e18e Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com> Date: Tue, 19 Oct 2021 15:57:58 -0400 Subject: [PATCH 343/361] [Java] JDK Collection lambda models Adds support for data flow tracking through simple JDK collection functional APIs. - `Iterable::forEach` - `Iterator::forEachRemaining` - `Map::forEach` Replaces #5871 Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com> --- .../java/dataflow/internal/ContainerFlow.qll | 4 ++ .../dataflow/collections/Test.java | 52 +++++++++++++++++++ .../dataflow/collections/flow.expected | 9 ++++ 3 files changed, 65 insertions(+) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/ContainerFlow.qll b/java/ql/lib/semmle/code/java/dataflow/internal/ContainerFlow.qll index 6c72bbd451b..79fea09de4c 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/ContainerFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/ContainerFlow.qll @@ -104,7 +104,9 @@ private class ContainerFlowSummaries extends SummaryModelCsv { "java.util;Map$Entry;true;setValue;;;Argument[0];MapValue of Argument[-1];value", "java.lang;Iterable;true;iterator;();;Element of Argument[-1];Element of ReturnValue;value", "java.lang;Iterable;true;spliterator;();;Element of Argument[-1];Element of ReturnValue;value", + "java.lang;Iterable;true;forEach;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", "java.util;Iterator;true;next;;;Element of Argument[-1];ReturnValue;value", + "java.util;Iterator;true;forEachRemaining;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value", "java.util;ListIterator;true;previous;;;Element of Argument[-1];ReturnValue;value", "java.util;ListIterator;true;add;(Object);;Argument[0];Element of Argument[-1];value", "java.util;ListIterator;true;set;(Object);;Argument[0];Element of Argument[-1];value", @@ -135,6 +137,8 @@ private class ContainerFlowSummaries extends SummaryModelCsv { "java.util;Map;true;merge;(Object,Object,BiFunction);;Argument[1];MapValue of Argument[-1];value", "java.util;Map;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", "java.util;Map;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value", + "java.util;Map;true;forEach;(BiConsumer);;MapKey of Argument[-1];Parameter[0] of Argument[0];value", + "java.util;Map;true;forEach;(BiConsumer);;MapValue of Argument[-1];Parameter[1] of Argument[0];value", "java.util;Collection;true;parallelStream;();;Element of Argument[-1];Element of ReturnValue;value", "java.util;Collection;true;stream;();;Element of Argument[-1];Element of ReturnValue;value", "java.util;Collection;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", diff --git a/java/ql/test/library-tests/dataflow/collections/Test.java b/java/ql/test/library-tests/dataflow/collections/Test.java index 8557c13b1ec..216f373ca8c 100644 --- a/java/ql/test/library-tests/dataflow/collections/Test.java +++ b/java/ql/test/library-tests/dataflow/collections/Test.java @@ -25,5 +25,57 @@ public class Test { Iterator<String> it = m.values().iterator(); String x5 = it.next(); sink(x5); // Flow + + it.forEachRemaining(x6 -> { + sink(x6); // Flow + }); + + m.forEach((x7_k, x8_v) -> { + sink(x7_k); // No flow + sink(x8_v); // Flow + }); + + m.entrySet().forEach(entry -> { + String x9 = entry.getKey(); + String x10 = entry.getValue(); + sink(x9); // No flow + sink(x10); // Flow + }); + } + + public void run2() { + HashMap<String, String> m = new HashMap<>(); + + m.put(tainted, tainted); + + m.forEach((x11_k, x12_v) -> { + sink(x11_k); // Flow + sink(x12_v); // Flow + }); + + m.entrySet().forEach(entry -> { + String x13 = entry.getKey(); + String x14 = entry.getValue(); + sink(x13); // Flow + sink(x14); // Flow + }); + } + + public void run3() { + Set<String> s = new HashSet<>(); + String x15 = s.iterator().next(); + sink(x15); // No flow + + s.forEach(x16 -> { + sink(x16); // No flow + }); + + s.add(tainted); + String x17 = s.iterator().next(); + sink(x17); // Flow + + s.forEach(x18 -> { + sink(x18); // Flow + }); } } diff --git a/java/ql/test/library-tests/dataflow/collections/flow.expected b/java/ql/test/library-tests/dataflow/collections/flow.expected index e2ccd7702b3..1a4bed0a6e7 100644 --- a/java/ql/test/library-tests/dataflow/collections/flow.expected +++ b/java/ql/test/library-tests/dataflow/collections/flow.expected @@ -2,3 +2,12 @@ | Test.java:13:18:13:24 | tainted | Test.java:18:10:18:11 | x3 | | Test.java:13:18:13:24 | tainted | Test.java:22:12:22:13 | x4 | | Test.java:13:18:13:24 | tainted | Test.java:27:10:27:11 | x5 | +| Test.java:13:18:13:24 | tainted | Test.java:30:12:30:13 | x6 | +| Test.java:13:18:13:24 | tainted | Test.java:35:12:35:15 | x8_v | +| Test.java:13:18:13:24 | tainted | Test.java:42:12:42:14 | x10 | +| Test.java:49:11:49:17 | tainted | Test.java:52:12:52:16 | x11_k | +| Test.java:49:11:49:17 | tainted | Test.java:59:12:59:14 | x13 | +| Test.java:49:20:49:26 | tainted | Test.java:53:12:53:16 | x12_v | +| Test.java:49:20:49:26 | tainted | Test.java:60:12:60:14 | x14 | +| Test.java:73:11:73:17 | tainted | Test.java:75:10:75:12 | x17 | +| Test.java:73:11:73:17 | tainted | Test.java:78:12:78:14 | x18 | From 1196d0c62498672ca53bfc1cd33b9ea3d1e292cf Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 29 Sep 2021 19:48:48 +0200 Subject: [PATCH 344/361] C#: Rework `SummarizedCallable::clearsContent/2` --- .../code/csharp/dataflow/FlowSummary.qll | 17 +++ .../csharp/dataflow/internal/DataFlowImpl.qll | 52 ++++++--- .../dataflow/internal/DataFlowImplCommon.qll | 3 + .../internal/DataFlowImplConsistency.qll | 1 + .../dataflow/internal/DataFlowPrivate.qll | 40 +++++-- .../dataflow/internal/FlowSummaryImpl.qll | 103 +++++++++++++----- .../dataflow/external-models/steps.expected | 2 + 7 files changed, 168 insertions(+), 50 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll index a20c3876050..1feffa452b1 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll @@ -78,4 +78,21 @@ module SummaryComponentStack { class SummarizedCallable = Impl::Public::SummarizedCallable; +private class SummarizedCallableDefaultClearsContent extends Impl::Public::SummarizedCallable { + SummarizedCallable c; + + SummarizedCallableDefaultClearsContent() { this = c } + + // By default, we assume that all stores into arguments are definite + override predicate clearsContent(int i, DataFlow::Content content) { + exists(SummaryComponentStack output | + c.propagatesFlow(_, output, _) and + output.drop(_) = + SummaryComponentStack::push(SummaryComponent::content(content), + SummaryComponentStack::argument(i)) and + not content instanceof DataFlow::ElementContent + ) + } +} + class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack; 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 626584efcbc..457cb21c361 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } 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 494780d2e1b..13a8b3180a7 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -801,6 +801,9 @@ private module Cached { exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call)) } + cached + predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + cached newtype TCallContext = TAnyCallContext() or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll index a55e65a81f6..dd64fc70039 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll @@ -175,6 +175,7 @@ module Consistency { query predicate postWithInFlow(Node n, string msg) { isPostUpdateNode(n) and + not clearsContent(n, _) and simpleLocalFlowStep(_, n) and msg = "PostUpdateNode should not be the target of local flow." } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 6776025d172..3f50a203f22 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -310,6 +310,18 @@ module LocalFlow { result = n.(ExplicitParameterNode).getSsaDefinition() } + /** + * Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo` + * involving SSA definition `def`. + */ + predicate localSsaFlowStepUseUse(Ssa::Definition def, Node nodeFrom, Node nodeTo) { + exists(ControlFlow::Node cfnFrom, ControlFlow::Node cfnTo | + SsaImpl::adjacentReadPairSameVar(def, cfnFrom, cfnTo) and + nodeTo = TExprNode(cfnTo) and + nodeFrom = TExprNode(cfnFrom) + ) + } + /** * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving * SSA definition `def. @@ -322,14 +334,7 @@ module LocalFlow { ) or // Flow from read to next read - exists(ControlFlow::Node cfnFrom, ControlFlow::Node cfnTo | - SsaImpl::adjacentReadPairSameVar(def, cfnFrom, cfnTo) and - nodeTo = TExprNode(cfnTo) - | - nodeFrom = TExprNode(cfnFrom) - or - cfnFrom = nodeFrom.(PostUpdateNode).getPreUpdateNode().getControlFlowNode() - ) + localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo) or // Flow into phi node exists(Ssa::PhiNode phi | @@ -399,6 +404,12 @@ module LocalFlow { predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { LocalFlow::localFlowStepCommon(nodeFrom, nodeTo) or + exists(Ssa::Definition def | + LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and + not FlowSummaryImpl::Private::Steps::summaryClearsContentArg(nodeFrom, _) and + not LocalFlow::usesInstanceField(def) + ) + or LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo) or FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true) @@ -716,6 +727,8 @@ private module Cached { predicate localFlowStepImpl(Node nodeFrom, Node nodeTo) { LocalFlow::localFlowStepCommon(nodeFrom, nodeTo) or + LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo) + or exists(Ssa::Definition def | LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo) and LocalFlow::usesInstanceField(def) @@ -1691,9 +1704,6 @@ predicate clearsContent(Node n, Content c) { or fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false) or - FlowSummaryImpl::Private::Steps::summaryStoresIntoArg(c, n) and - not c instanceof ElementContent - or FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c) or exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f | @@ -2003,3 +2013,11 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves preservesValue = false ) } + +/** + * Holds if flow is allowed to pass from a parameter `p`, to return + * node `ret`, and back out to `p`. + */ +predicate allowFlowThroughParameter(ReturnNodeExt ret) { + FlowSummaryImpl::Private::summaryAllowFlowThroughParameter(ret) +} diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 83076558ec4..8cc49ace88b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -261,7 +261,10 @@ module Private { private newtype TSummaryNodeState = TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or - TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } + TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } or + TSummaryNodeClearsContentState(int i, boolean post) { + any(SummarizedCallable sc).clearsContent(i, _) and post in [false, true] + } /** * A state used to break up (complex) flow summaries into atomic flow steps. @@ -308,6 +311,12 @@ module Private { this = TSummaryNodeOutputState(s) and result = "to write: " + s ) + or + exists(int i, boolean post, string postStr | + this = TSummaryNodeClearsContentState(i, post) and + (if post = true then postStr = " (post)" else postStr = "") and + result = "clear: " + i + postStr + ) } } @@ -329,6 +338,11 @@ module Private { not parameterReadState(c, state, _) or state.isOutputState(c, _) + or + exists(int i | + c.clearsContent(i, _) and + state = TSummaryNodeClearsContentState(i, _) + ) } pragma[noinline] @@ -364,6 +378,8 @@ module Private { parameterReadState(c, _, i) or isParameterPostUpdate(_, c, i) + or + c.clearsContent(i, _) } private predicate callbackOutput( @@ -436,6 +452,12 @@ module Private { ) ) ) + or + exists(SummarizedCallable c, int i, ParamNode p | + n = summaryNode(c, TSummaryNodeClearsContentState(i, false)) and + p.isParameterOf(c, i) and + result = getNodeType(p) + ) } /** Holds if summary node `out` contains output of kind `rk` from call `c`. */ @@ -461,6 +483,9 @@ module Private { exists(SummarizedCallable c, int i | isParameterPostUpdate(post, c, i) and pre.(ParamNode).isParameterOf(c, i) + or + pre = summaryNode(c, TSummaryNodeClearsContentState(i, false)) and + post = summaryNode(c, TSummaryNodeClearsContentState(i, true)) ) or exists(SummarizedCallable callable, SummaryComponentStack s | @@ -478,6 +503,14 @@ module Private { ) } + /** + * Holds if flow is allowed to pass from a parameter `p`, to return + * node `ret`, and back out to `p`. + */ + predicate summaryAllowFlowThroughParameter(ReturnNodeExt ret) { + ret = summaryNode(_, TSummaryNodeClearsContentState(_, true)) + } + /** Provides a compilation of flow summaries to atomic data-flow steps. */ module Steps { /** @@ -504,11 +537,21 @@ module Private { // for `StringBuilder.append(x)` with a specified value flow from qualifier to // return value and taint flow from argument 0 to the qualifier, then this // allows us to infer taint flow from argument 0 to the return value. - succ instanceof ParamNode and summaryPostUpdateNode(pred, succ) and preservesValue = true + succ instanceof ParamNode and + summaryPostUpdateNode(pred, succ) and + preservesValue = true or // Similarly we would like to chain together summaries where values get passed // into callbacks along the way. - pred instanceof ArgNode and summaryPostUpdateNode(succ, pred) and preservesValue = true + pred instanceof ArgNode and + summaryPostUpdateNode(succ, pred) and + preservesValue = true + or + exists(SummarizedCallable c, int i | + pred.(ParamNode).isParameterOf(c, i) and + succ = summaryNode(c, TSummaryNodeClearsContentState(i, _)) and + preservesValue = true + ) } /** @@ -536,10 +579,39 @@ module Private { } /** - * Holds if values stored inside content `c` are cleared when passed as - * input of type `input` in `call`. + * Holds if values stored inside content `c` are cleared at `n`. `n` is a + * synthesized summary node, so in order for values to be cleared at calls + * to the relevant method, it is important that flow does not pass over + * the argument, either via use-use flow or def-use flow. + * + * Example: + * + * ``` + * a.b = taint; + * a.clearB(); // assume we have a flow summary for `clearB` that clears `b` on the qualifier + * sink(a.b); + * ``` + * + * In the above, flow should not pass from `a` on the first line (or the second + * line) to `a` on the third line. Instead, there will be synthesized flow from + * `a` on line 2 to the post-update node for `a` on that line (via an intermediate + * node where field `b` is cleared). */ - predicate summaryClearsContent(ArgNode arg, Content c) { + predicate summaryClearsContent(Node n, Content c) { + exists(SummarizedCallable sc, int i | + n = summaryNode(sc, TSummaryNodeClearsContentState(i, true)) and + sc.clearsContent(i, c) + ) + } + + /** + * Holds if values stored inside content `c` are cleared inside a + * callable to which `arg` is an argument. + * + * In such cases, it is important to prevent use-use flow out of + * `arg` (see comment for `summaryClearsContent`). + */ + predicate summaryClearsContentArg(ArgNode arg, Content c) { exists(DataFlowCall call, int i | viableCallable(call).(SummarizedCallable).clearsContent(i, c) and arg.argumentOf(call, i) @@ -599,25 +671,6 @@ module Private { ret.getKind() = rk ) } - - /** - * Holds if data is written into content `c` of argument `arg` using a flow summary. - * - * Depending on the type of `c`, this predicate may be relevant to include in the - * definition of `clearsContent()`. - */ - predicate summaryStoresIntoArg(Content c, Node arg) { - exists(ParamUpdateReturnKind rk, ReturnNodeExt ret, PostUpdateNode out | - exists(DataFlowCall call, SummarizedCallable callable | - getNodeEnclosingCallable(ret) = callable and - viableCallable(call) = callable and - summaryStoreStep(_, c, ret) and - ret.getKind() = pragma[only_bind_into](rk) and - out = rk.getAnOutNode(call) and - arg = out.getPreUpdateNode() - ) - ) - } } /** diff --git a/csharp/ql/test/library-tests/dataflow/external-models/steps.expected b/csharp/ql/test/library-tests/dataflow/external-models/steps.expected index f73872ed9be..46e9b3a628d 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/steps.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/steps.expected @@ -8,6 +8,8 @@ summaryThroughStep | Steps.cs:22:13:22:16 | this access | Steps.cs:22:13:22:30 | call to method StepQualRes | false | | Steps.cs:23:13:23:25 | this access | Steps.cs:23:13:23:25 | call to method StepQualRes | false | | Steps.cs:26:13:26:31 | this access | Steps.cs:26:25:26:30 | [post] access to local variable argOut | false | +| Steps.cs:30:13:30:16 | this access | Steps.cs:30:13:30:16 | [post] this access | true | +| Steps.cs:34:13:34:16 | this access | Steps.cs:34:13:34:16 | [post] this access | true | | Steps.cs:41:29:41:29 | 0 | Steps.cs:41:13:41:30 | call to method StepGeneric | true | | Steps.cs:42:30:42:34 | false | Steps.cs:42:13:42:35 | call to method StepGeneric2<Boolean> | true | | Steps.cs:44:36:44:43 | "string" | Steps.cs:44:13:44:44 | call to method StepOverride | true | From a1511e13d85a2e481cdd838f73dcf278522ba41b Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 29 Sep 2021 20:08:45 +0200 Subject: [PATCH 345/361] Data flow: Sync files --- .../cpp/dataflow/internal/DataFlowImpl.qll | 52 ++++++--- .../cpp/dataflow/internal/DataFlowImpl2.qll | 52 ++++++--- .../cpp/dataflow/internal/DataFlowImpl3.qll | 52 ++++++--- .../cpp/dataflow/internal/DataFlowImpl4.qll | 52 ++++++--- .../dataflow/internal/DataFlowImplCommon.qll | 3 + .../internal/DataFlowImplConsistency.qll | 1 + .../dataflow/internal/DataFlowImplLocal.qll | 52 ++++++--- .../cpp/dataflow/internal/DataFlowPrivate.qll | 3 + .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 52 ++++++--- .../ir/dataflow/internal/DataFlowImpl2.qll | 52 ++++++--- .../ir/dataflow/internal/DataFlowImpl3.qll | 52 ++++++--- .../ir/dataflow/internal/DataFlowImpl4.qll | 52 ++++++--- .../dataflow/internal/DataFlowImplCommon.qll | 3 + .../internal/DataFlowImplConsistency.qll | 1 + .../ir/dataflow/internal/DataFlowPrivate.qll | 3 + .../dataflow/internal/DataFlowImpl2.qll | 52 ++++++--- .../dataflow/internal/DataFlowImpl3.qll | 52 ++++++--- .../dataflow/internal/DataFlowImpl4.qll | 52 ++++++--- .../dataflow/internal/DataFlowImpl5.qll | 52 ++++++--- .../java/dataflow/internal/DataFlowImpl.qll | 52 ++++++--- .../java/dataflow/internal/DataFlowImpl2.qll | 52 ++++++--- .../java/dataflow/internal/DataFlowImpl3.qll | 52 ++++++--- .../java/dataflow/internal/DataFlowImpl4.qll | 52 ++++++--- .../java/dataflow/internal/DataFlowImpl5.qll | 52 ++++++--- .../java/dataflow/internal/DataFlowImpl6.qll | 52 ++++++--- .../dataflow/internal/DataFlowImplCommon.qll | 3 + .../internal/DataFlowImplConsistency.qll | 1 + .../DataFlowImplForSerializability.qll | 52 ++++++--- .../dataflow/internal/DataFlowPrivate.qll | 8 ++ .../dataflow/internal/FlowSummaryImpl.qll | 103 +++++++++++++----- .../dataflow/new/internal/DataFlowImpl.qll | 52 ++++++--- .../dataflow/new/internal/DataFlowImpl2.qll | 52 ++++++--- .../dataflow/new/internal/DataFlowImpl3.qll | 52 ++++++--- .../dataflow/new/internal/DataFlowImpl4.qll | 52 ++++++--- .../new/internal/DataFlowImplCommon.qll | 3 + .../new/internal/DataFlowImplConsistency.qll | 1 + .../dataflow/new/internal/DataFlowPrivate.qll | 3 + 37 files changed, 1023 insertions(+), 361 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 626584efcbc..457cb21c361 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 626584efcbc..457cb21c361 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 626584efcbc..457cb21c361 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 626584efcbc..457cb21c361 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } 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 494780d2e1b..13a8b3180a7 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -801,6 +801,9 @@ private module Cached { exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call)) } + cached + predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + cached newtype TCallContext = TAnyCallContext() or diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll index a55e65a81f6..dd64fc70039 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll @@ -175,6 +175,7 @@ module Consistency { query predicate postWithInFlow(Node n, string msg) { isPostUpdateNode(n) and + not clearsContent(n, _) and simpleLocalFlowStep(_, n) and msg = "PostUpdateNode should not be the target of local flow." } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 626584efcbc..457cb21c361 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 7767b644cbd..f68c00a72a5 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -287,3 +287,6 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } + +/** Holds if flow is allowed to pass into `p` and back out again. */ +predicate allowFlowThroughParameter(ParameterNode p) { none() } 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 626584efcbc..457cb21c361 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 @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 626584efcbc..457cb21c361 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 626584efcbc..457cb21c361 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 626584efcbc..457cb21c361 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } 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 494780d2e1b..13a8b3180a7 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 @@ -801,6 +801,9 @@ private module Cached { exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call)) } + cached + predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + cached newtype TCallContext = TAnyCallContext() or diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll index a55e65a81f6..dd64fc70039 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -175,6 +175,7 @@ module Consistency { query predicate postWithInFlow(Node n, string msg) { isPostUpdateNode(n) and + not clearsContent(n, _) and simpleLocalFlowStep(_, n) and msg = "PostUpdateNode should not be the target of local flow." } 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 00996a6ebfc..b7ecbaad6c6 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 @@ -507,3 +507,6 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } + +/** Holds if flow is allowed to pass into `p` and back out again. */ +predicate allowFlowThroughParameter(ParameterNode p) { none() } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 626584efcbc..457cb21c361 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 626584efcbc..457cb21c361 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 626584efcbc..457cb21c361 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 626584efcbc..457cb21c361 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } 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 626584efcbc..457cb21c361 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 626584efcbc..457cb21c361 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 626584efcbc..457cb21c361 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 626584efcbc..457cb21c361 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 626584efcbc..457cb21c361 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 626584efcbc..457cb21c361 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } 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 494780d2e1b..13a8b3180a7 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -801,6 +801,9 @@ private module Cached { exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call)) } + cached + predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + cached newtype TCallContext = TAnyCallContext() or diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll index a55e65a81f6..dd64fc70039 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -175,6 +175,7 @@ module Consistency { query predicate postWithInFlow(Node n, string msg) { isPostUpdateNode(n) and + not clearsContent(n, _) and simpleLocalFlowStep(_, n) and msg = "PostUpdateNode should not be the target of local flow." } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index 626584efcbc..457cb21c361 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index d35610ecf4a..89f81149640 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -369,3 +369,11 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } + +/** + * Holds if flow is allowed to pass from a parameter `p`, to return + * node `ret`, and back out to `p`. + */ +predicate allowFlowThroughParameter(ReturnNodeExt ret) { + FlowSummaryImpl::Private::summaryAllowFlowThroughParameter(ret) +} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 83076558ec4..8cc49ace88b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -261,7 +261,10 @@ module Private { private newtype TSummaryNodeState = TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or - TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } + TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } or + TSummaryNodeClearsContentState(int i, boolean post) { + any(SummarizedCallable sc).clearsContent(i, _) and post in [false, true] + } /** * A state used to break up (complex) flow summaries into atomic flow steps. @@ -308,6 +311,12 @@ module Private { this = TSummaryNodeOutputState(s) and result = "to write: " + s ) + or + exists(int i, boolean post, string postStr | + this = TSummaryNodeClearsContentState(i, post) and + (if post = true then postStr = " (post)" else postStr = "") and + result = "clear: " + i + postStr + ) } } @@ -329,6 +338,11 @@ module Private { not parameterReadState(c, state, _) or state.isOutputState(c, _) + or + exists(int i | + c.clearsContent(i, _) and + state = TSummaryNodeClearsContentState(i, _) + ) } pragma[noinline] @@ -364,6 +378,8 @@ module Private { parameterReadState(c, _, i) or isParameterPostUpdate(_, c, i) + or + c.clearsContent(i, _) } private predicate callbackOutput( @@ -436,6 +452,12 @@ module Private { ) ) ) + or + exists(SummarizedCallable c, int i, ParamNode p | + n = summaryNode(c, TSummaryNodeClearsContentState(i, false)) and + p.isParameterOf(c, i) and + result = getNodeType(p) + ) } /** Holds if summary node `out` contains output of kind `rk` from call `c`. */ @@ -461,6 +483,9 @@ module Private { exists(SummarizedCallable c, int i | isParameterPostUpdate(post, c, i) and pre.(ParamNode).isParameterOf(c, i) + or + pre = summaryNode(c, TSummaryNodeClearsContentState(i, false)) and + post = summaryNode(c, TSummaryNodeClearsContentState(i, true)) ) or exists(SummarizedCallable callable, SummaryComponentStack s | @@ -478,6 +503,14 @@ module Private { ) } + /** + * Holds if flow is allowed to pass from a parameter `p`, to return + * node `ret`, and back out to `p`. + */ + predicate summaryAllowFlowThroughParameter(ReturnNodeExt ret) { + ret = summaryNode(_, TSummaryNodeClearsContentState(_, true)) + } + /** Provides a compilation of flow summaries to atomic data-flow steps. */ module Steps { /** @@ -504,11 +537,21 @@ module Private { // for `StringBuilder.append(x)` with a specified value flow from qualifier to // return value and taint flow from argument 0 to the qualifier, then this // allows us to infer taint flow from argument 0 to the return value. - succ instanceof ParamNode and summaryPostUpdateNode(pred, succ) and preservesValue = true + succ instanceof ParamNode and + summaryPostUpdateNode(pred, succ) and + preservesValue = true or // Similarly we would like to chain together summaries where values get passed // into callbacks along the way. - pred instanceof ArgNode and summaryPostUpdateNode(succ, pred) and preservesValue = true + pred instanceof ArgNode and + summaryPostUpdateNode(succ, pred) and + preservesValue = true + or + exists(SummarizedCallable c, int i | + pred.(ParamNode).isParameterOf(c, i) and + succ = summaryNode(c, TSummaryNodeClearsContentState(i, _)) and + preservesValue = true + ) } /** @@ -536,10 +579,39 @@ module Private { } /** - * Holds if values stored inside content `c` are cleared when passed as - * input of type `input` in `call`. + * Holds if values stored inside content `c` are cleared at `n`. `n` is a + * synthesized summary node, so in order for values to be cleared at calls + * to the relevant method, it is important that flow does not pass over + * the argument, either via use-use flow or def-use flow. + * + * Example: + * + * ``` + * a.b = taint; + * a.clearB(); // assume we have a flow summary for `clearB` that clears `b` on the qualifier + * sink(a.b); + * ``` + * + * In the above, flow should not pass from `a` on the first line (or the second + * line) to `a` on the third line. Instead, there will be synthesized flow from + * `a` on line 2 to the post-update node for `a` on that line (via an intermediate + * node where field `b` is cleared). */ - predicate summaryClearsContent(ArgNode arg, Content c) { + predicate summaryClearsContent(Node n, Content c) { + exists(SummarizedCallable sc, int i | + n = summaryNode(sc, TSummaryNodeClearsContentState(i, true)) and + sc.clearsContent(i, c) + ) + } + + /** + * Holds if values stored inside content `c` are cleared inside a + * callable to which `arg` is an argument. + * + * In such cases, it is important to prevent use-use flow out of + * `arg` (see comment for `summaryClearsContent`). + */ + predicate summaryClearsContentArg(ArgNode arg, Content c) { exists(DataFlowCall call, int i | viableCallable(call).(SummarizedCallable).clearsContent(i, c) and arg.argumentOf(call, i) @@ -599,25 +671,6 @@ module Private { ret.getKind() = rk ) } - - /** - * Holds if data is written into content `c` of argument `arg` using a flow summary. - * - * Depending on the type of `c`, this predicate may be relevant to include in the - * definition of `clearsContent()`. - */ - predicate summaryStoresIntoArg(Content c, Node arg) { - exists(ParamUpdateReturnKind rk, ReturnNodeExt ret, PostUpdateNode out | - exists(DataFlowCall call, SummarizedCallable callable | - getNodeEnclosingCallable(ret) = callable and - viableCallable(call) = callable and - summaryStoreStep(_, c, ret) and - ret.getKind() = pragma[only_bind_into](rk) and - out = rk.getAnOutNode(call) and - arg = out.getPreUpdateNode() - ) - ) - } } /** 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 626584efcbc..457cb21c361 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 626584efcbc..457cb21c361 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 626584efcbc..457cb21c361 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 626584efcbc..457cb21c361 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -252,6 +252,8 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + + predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -725,12 +727,16 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config + DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, + Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() + kind = ret.getKind() and + if ret.allowFlowThroughParameter() + then allowFlowThroughParameter = true + else allowFlowThroughParameter = false ) } @@ -739,13 +745,16 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind | + exists(ReturnKindExt kind, boolean allowFlowThroughParameter | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and + returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and p.getEnclosingCallable() = c and - exists(ap) and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then allowFlowThroughParameter = true + else any() + ) and + exists(ap) ) } @@ -1394,8 +1403,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2083,8 +2095,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2843,8 +2858,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and - // we don't expect a parameter to return stored in itself - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + then ret.allowFlowThroughParameter() + else any() + ) ) } @@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } + ParameterNode getParameterNode() { result = p.asNode() } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -3617,7 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and - not kind.(ParamUpdateReturnKind).getPosition() = pos + ( + if kind.(ParamUpdateReturnKind).getPosition() = pos + then ret.allowFlowThroughParameter() + else any() + ) ) } 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 494780d2e1b..13a8b3180a7 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -801,6 +801,9 @@ private module Cached { exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call)) } + cached + predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + cached newtype TCallContext = TAnyCallContext() or diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll index a55e65a81f6..dd64fc70039 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll @@ -175,6 +175,7 @@ module Consistency { query predicate postWithInFlow(Node n, string msg) { isPostUpdateNode(n) and + not clearsContent(n, _) and simpleLocalFlowStep(_, n) and msg = "PostUpdateNode should not be the target of local flow." } 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 b41edd28898..34c8cbc4287 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1664,3 +1664,6 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } + +/** Holds if flow is allowed to pass into `p` and back out again. */ +predicate allowFlowThroughParameter(ParameterNode p) { none() } From ec5d8ab2dbb3c2b38252cddb88808936225eae75 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 29 Sep 2021 20:22:21 +0200 Subject: [PATCH 346/361] Java: Restrict use-use flow --- .../semmle/code/java/dataflow/internal/DataFlowPrivate.qll | 6 +----- .../lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll | 5 ++++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 89f81149640..387cab61704 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -139,11 +139,7 @@ predicate readStep(Node node1, Content f, Node node2) { */ predicate clearsContent(Node n, Content c) { c instanceof FieldContent and - ( - n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode() - or - FlowSummaryImpl::Private::Steps::summaryStoresIntoArg(c, n) - ) + n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode() or FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll index 462430b2b5a..8146e8ddc29 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll @@ -101,6 +101,8 @@ predicate hasNonlocalValue(FieldRead fr) { predicate localFlowStep(Node node1, Node node2) { simpleLocalFlowStep(node1, node2) or + adjacentUseUse(node1.asExpr(), node2.asExpr()) + or // Simple flow through library code is included in the exposed local // step relation, even though flow is technically inter-procedural FlowSummaryImpl::Private::Steps::summaryThroughStep(node1, node2, true) @@ -131,7 +133,8 @@ predicate simpleLocalFlowStep(Node node1, Node node2) { adjacentUseUse(node1.asExpr(), node2.asExpr()) and not exists(FieldRead fr | hasNonlocalValue(fr) and fr.getField().isStatic() and fr = node1.asExpr() - ) + ) and + not FlowSummaryImpl::Private::Steps::summaryClearsContentArg(node1, _) or ThisFlow::adjacentThisRefs(node1, node2) or From dd138b04294e7681b6b41b4bf951ff1df2baf67b Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 19 Oct 2021 15:33:25 +0200 Subject: [PATCH 347/361] Address review comments --- .../cpp/dataflow/internal/DataFlowImpl.qll | 57 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl2.qll | 57 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl3.qll | 57 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl4.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowImplCommon.qll | 2 +- .../dataflow/internal/DataFlowImplLocal.qll | 57 ++++++++++--------- .../cpp/dataflow/internal/DataFlowPrivate.qll | 7 ++- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 57 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl2.qll | 57 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl3.qll | 57 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl4.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowImplCommon.qll | 2 +- .../ir/dataflow/internal/DataFlowPrivate.qll | 7 ++- .../csharp/dataflow/internal/DataFlowImpl.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowImpl2.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowImpl3.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowImpl4.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowImpl5.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowImplCommon.qll | 2 +- .../dataflow/internal/DataFlowPrivate.qll | 8 +-- .../dataflow/internal/FlowSummaryImpl.qll | 11 ++-- .../java/dataflow/internal/DataFlowImpl.qll | 57 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl2.qll | 57 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl3.qll | 57 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl4.qll | 57 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl5.qll | 57 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl6.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowImplCommon.qll | 2 +- .../DataFlowImplForSerializability.qll | 57 ++++++++++--------- .../dataflow/internal/DataFlowPrivate.qll | 8 +-- .../dataflow/internal/FlowSummaryImpl.qll | 11 ++-- .../dataflow/new/internal/DataFlowImpl.qll | 57 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl2.qll | 57 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl3.qll | 57 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl4.qll | 57 ++++++++++--------- .../new/internal/DataFlowImplCommon.qll | 2 +- .../dataflow/new/internal/DataFlowPrivate.qll | 7 ++- 37 files changed, 767 insertions(+), 727 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 457cb21c361..b3d03ea4e26 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 457cb21c361..b3d03ea4e26 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 457cb21c361..b3d03ea4e26 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 457cb21c361..b3d03ea4e26 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } 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 13a8b3180a7..e11244c42b0 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -802,7 +802,7 @@ private module Cached { } cached - predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) } cached newtype TCallContext = diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 457cb21c361..b3d03ea4e26 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index f68c00a72a5..d970e31e129 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -288,5 +288,8 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } -/** Holds if flow is allowed to pass into `p` and back out again. */ -predicate allowFlowThroughParameter(ParameterNode p) { none() } +/** + * Holds if flow is allowed to pass from parameter `p`, to a return + * node, and back out to `p`. + */ +predicate allowParameterReturnInSelf(ParameterNode p) { none() } 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 457cb21c361..b3d03ea4e26 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 @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 457cb21c361..b3d03ea4e26 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 457cb21c361..b3d03ea4e26 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 457cb21c361..b3d03ea4e26 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } 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 13a8b3180a7..e11244c42b0 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 @@ -802,7 +802,7 @@ private module Cached { } cached - predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) } cached newtype TCallContext = 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 b7ecbaad6c6..6f6f5407b14 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 @@ -508,5 +508,8 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } -/** Holds if flow is allowed to pass into `p` and back out again. */ -predicate allowFlowThroughParameter(ParameterNode p) { none() } +/** + * Holds if flow is allowed to pass from parameter `p`, to a return + * node, and back out to `p`. + */ +predicate allowParameterReturnInSelf(ParameterNode p) { none() } 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 457cb21c361..b3d03ea4e26 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 457cb21c361..b3d03ea4e26 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 457cb21c361..b3d03ea4e26 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 457cb21c361..b3d03ea4e26 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 457cb21c361..b3d03ea4e26 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } 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 13a8b3180a7..e11244c42b0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -802,7 +802,7 @@ private module Cached { } cached - predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) } cached newtype TCallContext = diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 3f50a203f22..ad190c127db 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -2015,9 +2015,9 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves } /** - * Holds if flow is allowed to pass from a parameter `p`, to return - * node `ret`, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p`, to a return + * node, and back out to `p`. */ -predicate allowFlowThroughParameter(ReturnNodeExt ret) { - FlowSummaryImpl::Private::summaryAllowFlowThroughParameter(ret) +predicate allowParameterReturnInSelf(ParameterNode p) { + FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(p) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 8cc49ace88b..5955285bd6f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -504,11 +504,14 @@ module Private { } /** - * Holds if flow is allowed to pass from a parameter `p`, to return - * node `ret`, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p`, to a return + * node, and back out to `p`. */ - predicate summaryAllowFlowThroughParameter(ReturnNodeExt ret) { - ret = summaryNode(_, TSummaryNodeClearsContentState(_, true)) + predicate summaryAllowParameterReturnInSelf(ParamNode p) { + exists(SummarizedCallable c, int i | + c.clearsContent(i, _) and + p.isParameterOf(c, i) + ) } /** Provides a compilation of flow summaries to atomic data-flow steps. */ 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 457cb21c361..b3d03ea4e26 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 457cb21c361..b3d03ea4e26 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 457cb21c361..b3d03ea4e26 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 457cb21c361..b3d03ea4e26 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 457cb21c361..b3d03ea4e26 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 457cb21c361..b3d03ea4e26 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } 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 13a8b3180a7..e11244c42b0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -802,7 +802,7 @@ private module Cached { } cached - predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) } cached newtype TCallContext = diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index 457cb21c361..b3d03ea4e26 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 387cab61704..8cac4d44443 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -367,9 +367,9 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } /** - * Holds if flow is allowed to pass from a parameter `p`, to return - * node `ret`, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p`, to a return + * node, and back out to `p`. */ -predicate allowFlowThroughParameter(ReturnNodeExt ret) { - FlowSummaryImpl::Private::summaryAllowFlowThroughParameter(ret) +predicate allowParameterReturnInSelf(ParameterNode p) { + FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(p) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 8cc49ace88b..5955285bd6f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -504,11 +504,14 @@ module Private { } /** - * Holds if flow is allowed to pass from a parameter `p`, to return - * node `ret`, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p`, to a return + * node, and back out to `p`. */ - predicate summaryAllowFlowThroughParameter(ReturnNodeExt ret) { - ret = summaryNode(_, TSummaryNodeClearsContentState(_, true)) + predicate summaryAllowParameterReturnInSelf(ParamNode p) { + exists(SummarizedCallable c, int i | + c.clearsContent(i, _) and + p.isParameterOf(c, i) + ) } /** Provides a compilation of flow summaries to atomic data-flow steps. */ 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 457cb21c361..b3d03ea4e26 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 457cb21c361..b3d03ea4e26 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 457cb21c361..b3d03ea4e26 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 457cb21c361..b3d03ea4e26 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx { } int getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } } private class RetNodeEx extends NodeEx { @@ -252,8 +254,6 @@ private class RetNodeEx extends NodeEx { ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } - - predicate allowFlowThroughParameter() { allowFlowThroughParameterCached(this.asNode()) } } private predicate inBarrier(NodeEx node, Configuration config) { @@ -727,16 +727,12 @@ private module Stage1 { /** Holds if flow may return from `callable`. */ pragma[nomagic] private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, boolean allowFlowThroughParameter, - Configuration config + DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { exists(RetNodeEx ret | throughFlowNodeCand(ret, config) and callable = ret.getEnclosingCallable() and - kind = ret.getKind() and - if ret.allowFlowThroughParameter() - then allowFlowThroughParameter = true - else allowFlowThroughParameter = false + kind = ret.getKind() ) } @@ -745,16 +741,17 @@ private module Stage1 { * candidate for the origin of a summary. */ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { - exists(ReturnKindExt kind, boolean allowFlowThroughParameter | + exists(ReturnKindExt kind | throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, allowFlowThroughParameter, config) and + returnFlowCallableNodeCand(c, kind, config) and p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then allowFlowThroughParameter = true - else any() - ) and - exists(ap) + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) ) } @@ -1403,10 +1400,11 @@ private module Stage2 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2095,10 +2093,11 @@ private module Stage3 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2858,10 +2857,11 @@ private module Stage4 { fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and kind = ret.getKind() and p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() ) ) } @@ -2935,7 +2935,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { int getParameterPos() { p.isParameterOf(_, result) } - ParameterNode getParameterNode() { result = p.asNode() } + ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -3637,10 +3637,11 @@ private predicate paramFlowsThrough( ap = mid.getAp() and apa = ap.getApprox() and pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed ( - if kind.(ParamUpdateReturnKind).getPosition() = pos - then ret.allowFlowThroughParameter() - else any() + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() ) ) } 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 13a8b3180a7..e11244c42b0 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -802,7 +802,7 @@ private module Cached { } cached - predicate allowFlowThroughParameterCached(Node ret) { allowFlowThroughParameter(ret) } + predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) } cached newtype TCallContext = 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 34c8cbc4287..76edf182968 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1665,5 +1665,8 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } -/** Holds if flow is allowed to pass into `p` and back out again. */ -predicate allowFlowThroughParameter(ParameterNode p) { none() } +/** + * Holds if flow is allowed to pass from parameter `p`, to a return + * node, and back out to `p`. + */ +predicate allowParameterReturnInSelf(ParameterNode p) { none() } From 53d4d72fe54b81f73901f245429c434fef779dad Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 20 Oct 2021 10:47:47 +0200 Subject: [PATCH 348/361] C#: Simplify `SummarizedCallableDefaultClearsContent` --- csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll | 8 ++++---- .../library-tests/dataflow/external-models/steps.expected | 3 +++ .../test/library-tests/dataflow/external-models/steps.ql | 6 ++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll index 1feffa452b1..3e5c8e51ba5 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll @@ -79,14 +79,14 @@ module SummaryComponentStack { class SummarizedCallable = Impl::Public::SummarizedCallable; private class SummarizedCallableDefaultClearsContent extends Impl::Public::SummarizedCallable { - SummarizedCallable c; - - SummarizedCallableDefaultClearsContent() { this = c } + SummarizedCallableDefaultClearsContent() { + this instanceof Impl::Public::SummarizedCallable or none() + } // By default, we assume that all stores into arguments are definite override predicate clearsContent(int i, DataFlow::Content content) { exists(SummaryComponentStack output | - c.propagatesFlow(_, output, _) and + this.propagatesFlow(_, output, _) and output.drop(_) = SummaryComponentStack::push(SummaryComponent::content(content), SummaryComponentStack::argument(i)) and diff --git a/csharp/ql/test/library-tests/dataflow/external-models/steps.expected b/csharp/ql/test/library-tests/dataflow/external-models/steps.expected index 46e9b3a628d..84e3026c74f 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/steps.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/steps.expected @@ -21,3 +21,6 @@ summarySetterStep | Steps.cs:30:34:30:34 | 0 | Steps.cs:30:13:30:16 | [post] this access | Steps.cs:57:13:57:17 | field Field | | Steps.cs:34:37:34:37 | 0 | Steps.cs:34:13:34:16 | [post] this access | Steps.cs:63:13:63:20 | property Property | | Steps.cs:38:36:38:36 | 0 | Steps.cs:38:13:38:16 | [post] this access | file://:0:0:0:0 | element | +clearsContent +| Steps.cs:61:14:61:28 | StepFieldSetter | Steps.cs:57:13:57:17 | field Field | -1 | +| Steps.cs:67:14:67:31 | StepPropertySetter | Steps.cs:63:13:63:20 | property Property | -1 | diff --git a/csharp/ql/test/library-tests/dataflow/external-models/steps.ql b/csharp/ql/test/library-tests/dataflow/external-models/steps.ql index b5643d27ca5..cab4c292a40 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/steps.ql +++ b/csharp/ql/test/library-tests/dataflow/external-models/steps.ql @@ -1,6 +1,7 @@ import csharp import DataFlow import semmle.code.csharp.dataflow.ExternalFlow +import semmle.code.csharp.dataflow.FlowSummary import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import CsvValidation @@ -40,3 +41,8 @@ query predicate summaryGetterStep(DataFlow::Node arg, DataFlow::Node out, Conten query predicate summarySetterStep(DataFlow::Node arg, DataFlow::Node out, Content c) { FlowSummaryImpl::Private::Steps::summarySetterStep(arg, c, out) } + +query predicate clearsContent(SummarizedCallable c, DataFlow::Content k, int i) { + c.clearsContent(i, k) and + c.fromSource() +} From 0bf5238f39aaa1d4fa5e97d05ee504c39ae74efc Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 20 Oct 2021 11:03:13 +0200 Subject: [PATCH 349/361] Update QL doc for `allowParameterReturnInSelf` --- .../semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll | 7 +++++-- .../code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 7 +++++-- .../code/csharp/dataflow/internal/DataFlowPrivate.qll | 7 +++++-- .../semmle/code/java/dataflow/internal/DataFlowPrivate.qll | 7 +++++-- .../python/dataflow/new/internal/DataFlowPrivate.qll | 7 +++++-- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index d970e31e129..0eecf7a6040 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -289,7 +289,10 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } /** - * Holds if flow is allowed to pass from parameter `p`, to a return - * node, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p` and back to itself as a + * side-effect, resulting in a summary from `p` to itself. + * + * One example would be to allow flow like `p.foo = p.bar;`, which is disallowed + * by default as a heuristic. */ predicate allowParameterReturnInSelf(ParameterNode p) { none() } 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 6f6f5407b14..3f215883df3 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 @@ -509,7 +509,10 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } /** - * Holds if flow is allowed to pass from parameter `p`, to a return - * node, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p` and back to itself as a + * side-effect, resulting in a summary from `p` to itself. + * + * One example would be to allow flow like `p.foo = p.bar;`, which is disallowed + * by default as a heuristic. */ predicate allowParameterReturnInSelf(ParameterNode p) { none() } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index ad190c127db..d47cfd95d8f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -2015,8 +2015,11 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves } /** - * Holds if flow is allowed to pass from parameter `p`, to a return - * node, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p` and back to itself as a + * side-effect, resulting in a summary from `p` to itself. + * + * One example would be to allow flow like `p.foo = p.bar;`, which is disallowed + * by default as a heuristic. */ predicate allowParameterReturnInSelf(ParameterNode p) { FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(p) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 8cac4d44443..d0df4c33cf5 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -367,8 +367,11 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } /** - * Holds if flow is allowed to pass from parameter `p`, to a return - * node, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p` and back to itself as a + * side-effect, resulting in a summary from `p` to itself. + * + * One example would be to allow flow like `p.foo = p.bar;`, which is disallowed + * by default as a heuristic. */ predicate allowParameterReturnInSelf(ParameterNode p) { FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(p) 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 76edf182968..b1a9ea7aa3a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1666,7 +1666,10 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } /** - * Holds if flow is allowed to pass from parameter `p`, to a return - * node, and back out to `p`. + * Holds if flow is allowed to pass from parameter `p` and back to itself as a + * side-effect, resulting in a summary from `p` to itself. + * + * One example would be to allow flow like `p.foo = p.bar;`, which is disallowed + * by default as a heuristic. */ predicate allowParameterReturnInSelf(ParameterNode p) { none() } From 29cdc8a49a0d56e0a26ebd5aa93263a96e4c8e98 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 20 Oct 2021 12:11:59 +0200 Subject: [PATCH 350/361] Java: Update expected test output after rebase --- java/ql/test/library-tests/dataflow/callback-dispatch/A.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java index 193e67fd38f..680badfe604 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java @@ -175,7 +175,7 @@ public class A { // con.eat(a2.field2); } - static void wrapSinkToAvoidFieldSsa(A a) { sink(a.field1); } + static void wrapSinkToAvoidFieldSsa(A a) { sink(a.field1); } // $ flow=20 void foo3() { A a1 = new A(); @@ -184,7 +184,7 @@ public class A { applyConsumer1Field1Field2(a1, a2, p -> { sink(p); // MISSING FLOW }); - wrapSinkToAvoidFieldSsa(a1); // MISSING FLOW + wrapSinkToAvoidFieldSsa(a1); sink(a2.field2); } From f9fb046e9f3c790b911ad2812fc4eab26d5ef026 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 20 Oct 2021 12:15:27 +0200 Subject: [PATCH 351/361] C#: Update expected test output after rebase --- .../dataflow/external-models/ExternalFlow.cs | 6 ++-- .../external-models/ExternalFlow.expected | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs index 6fd40ec90b6..4125866a549 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs @@ -99,10 +99,10 @@ namespace My.Qltest var d2 = new D(); Apply2(d => { - Sink(d); // MISSING FLOW + Sink(d); }, d1, d2); - Sink(d1.Field); // MISSING FLOW - Sink(d2.Field2); + Sink(d1.Field); + Sink(d2.Field2); // SPURIOUS FLOW } object StepArgRes(object x) { return null; } diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected index 10cd840a286..5a1c6b31a97 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected @@ -43,11 +43,29 @@ edges | ExternalFlow.cs:90:21:90:34 | object creation of type String : String | ExternalFlow.cs:91:19:91:19 | access to local variable s : String | | ExternalFlow.cs:91:19:91:19 | access to local variable s : String | ExternalFlow.cs:91:30:91:30 | SSA def(i) : Int32 | | ExternalFlow.cs:91:30:91:30 | SSA def(i) : Int32 | ExternalFlow.cs:92:18:92:18 | (...) ... | +| ExternalFlow.cs:98:13:98:14 | [post] access to local variable d1 [field Field] : Object | ExternalFlow.cs:103:16:103:17 | access to local variable d1 [field Field] : Object | +| ExternalFlow.cs:98:13:98:14 | [post] access to local variable d1 [field Field] : Object | ExternalFlow.cs:104:18:104:19 | access to local variable d1 [field Field] : Object | +| ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | ExternalFlow.cs:98:13:98:14 | [post] access to local variable d1 [field Field] : Object | +| ExternalFlow.cs:100:20:100:20 | d : Object | ExternalFlow.cs:102:22:102:22 | access to parameter d | +| ExternalFlow.cs:103:16:103:17 | access to local variable d1 [field Field] : Object | ExternalFlow.cs:103:20:103:21 | [post] access to local variable d2 [field Field2] : Object | +| ExternalFlow.cs:103:16:103:17 | access to local variable d1 [field Field] : Object | ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | +| ExternalFlow.cs:103:20:103:21 | [post] access to local variable d2 [field Field2] : Object | ExternalFlow.cs:105:18:105:19 | access to local variable d2 [field Field2] : Object | +| ExternalFlow.cs:104:18:104:19 | access to local variable d1 [field Field] : Object | ExternalFlow.cs:104:18:104:25 | access to field Field | +| ExternalFlow.cs:105:18:105:19 | access to local variable d2 [field Field2] : Object | ExternalFlow.cs:105:18:105:26 | access to field Field2 | | ExternalFlow.cs:135:46:135:46 | s : Object | ExternalFlow.cs:60:35:60:35 | o : Object | | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | ExternalFlow.cs:72:23:72:23 | o : Object | | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | ExternalFlow.cs:72:23:72:23 | o : Object | | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | +| ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | ExternalFlow.cs:100:20:100:20 | d : Object | +| ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | ExternalFlow.cs:100:20:100:20 | d : Object | +| ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | +| ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | +| ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | ExternalFlow.cs:139:52:139:53 | s2 [field Field2] : Object | +| ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | ExternalFlow.cs:139:52:139:53 | s2 [field Field2] : Object | +| ExternalFlow.cs:139:52:139:53 | s2 [field Field2] : Object | ExternalFlow.cs:100:20:100:20 | d : Object | +| ExternalFlow.cs:139:52:139:53 | s2 [field Field2] : Object | ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | +| ExternalFlow.cs:139:52:139:53 | s2 [field Field2] : Object | ExternalFlow.cs:139:52:139:53 | s2 [field Field2] : Object | nodes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | semmle.label | call to method StepArgRes | @@ -107,9 +125,22 @@ nodes | ExternalFlow.cs:91:19:91:19 | access to local variable s : String | semmle.label | access to local variable s : String | | ExternalFlow.cs:91:30:91:30 | SSA def(i) : Int32 | semmle.label | SSA def(i) : Int32 | | ExternalFlow.cs:92:18:92:18 | (...) ... | semmle.label | (...) ... | +| ExternalFlow.cs:98:13:98:14 | [post] access to local variable d1 [field Field] : Object | semmle.label | [post] access to local variable d1 [field Field] : Object | +| ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| ExternalFlow.cs:100:20:100:20 | d : Object | semmle.label | d : Object | +| ExternalFlow.cs:102:22:102:22 | access to parameter d | semmle.label | access to parameter d | +| ExternalFlow.cs:103:16:103:17 | access to local variable d1 [field Field] : Object | semmle.label | access to local variable d1 [field Field] : Object | +| ExternalFlow.cs:103:20:103:21 | [post] access to local variable d2 [field Field2] : Object | semmle.label | [post] access to local variable d2 [field Field2] : Object | +| ExternalFlow.cs:104:18:104:19 | access to local variable d1 [field Field] : Object | semmle.label | access to local variable d1 [field Field] : Object | +| ExternalFlow.cs:104:18:104:25 | access to field Field | semmle.label | access to field Field | +| ExternalFlow.cs:105:18:105:19 | access to local variable d2 [field Field2] : Object | semmle.label | access to local variable d2 [field Field2] : Object | +| ExternalFlow.cs:105:18:105:26 | access to field Field2 | semmle.label | access to field Field2 | | ExternalFlow.cs:135:46:135:46 | s : Object | semmle.label | s : Object | | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | semmle.label | elements [element] : Object | | ExternalFlow.cs:137:34:137:41 | elements [element] : Object | semmle.label | elements [element] : Object | +| ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | semmle.label | s1 [field Field] : Object | +| ExternalFlow.cs:139:46:139:47 | s1 [field Field] : Object | semmle.label | s1 [field Field] : Object | +| ExternalFlow.cs:139:52:139:53 | s2 [field Field2] : Object | semmle.label | s2 [field Field2] : Object | subpaths invalidModelRow #select @@ -128,3 +159,6 @@ invalidModelRow | ExternalFlow.cs:78:18:78:24 | (...) ... | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | ExternalFlow.cs:78:18:78:24 | (...) ... | $@ | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:85:18:85:25 | access to array element | ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | ExternalFlow.cs:85:18:85:25 | access to array element | $@ | ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:92:18:92:18 | (...) ... | ExternalFlow.cs:90:21:90:34 | object creation of type String : String | ExternalFlow.cs:92:18:92:18 | (...) ... | $@ | ExternalFlow.cs:90:21:90:34 | object creation of type String : String | object creation of type String : String | +| ExternalFlow.cs:102:22:102:22 | access to parameter d | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | ExternalFlow.cs:102:22:102:22 | access to parameter d | $@ | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | object creation of type Object : Object | +| ExternalFlow.cs:104:18:104:25 | access to field Field | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | ExternalFlow.cs:104:18:104:25 | access to field Field | $@ | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | object creation of type Object : Object | +| ExternalFlow.cs:105:18:105:26 | access to field Field2 | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | ExternalFlow.cs:105:18:105:26 | access to field Field2 | $@ | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | object creation of type Object : Object | From aaa5046533cf6abb59e8fb9edc44bd579fe17929 Mon Sep 17 00:00:00 2001 From: hubwriter <hubwriter@github.com> Date: Wed, 20 Oct 2021 11:17:38 +0100 Subject: [PATCH 352/361] Add beta note to page Calum added --- docs/codeql/codeql-language-guides/codeql-for-ruby.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/codeql/codeql-language-guides/codeql-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-for-ruby.rst index eaf5e8c94e1..bfb29a012ef 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-ruby.rst @@ -14,3 +14,5 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Basic query for Ruby code <basic-query-for-ruby-code>`: Learn to write and run a simple CodeQL query using LGTM. - :doc:`CodeQL library for Ruby <codeql-library-for-ruby>`: When you're analyzing a Ruby program, you can make use of the large collection of classes in the CodeQL library for Ruby. + +.. include:: ../reusables/ruby-beta-note.rst From 8f15dc4bd03c4f9ecde974f40c715715d1778ada Mon Sep 17 00:00:00 2001 From: hubwriter <hubwriter@github.com> Date: Wed, 20 Oct 2021 12:48:20 +0100 Subject: [PATCH 353/361] Add 'requires glibc 2.17' in supported languages table --- docs/codeql/support/reusables/versions-compilers.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst index 8726d878bf9..62678e16f05 100644 --- a/docs/codeql/support/reusables/versions-compilers.rst +++ b/docs/codeql/support/reusables/versions-compilers.rst @@ -22,8 +22,8 @@ Eclipse compiler for Java (ECJ) [5]_",``.java`` JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9",Not applicable,``.py`` - Ruby,"up to 3.02",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" - TypeScript [7]_,"2.6-4.4",Standard TypeScript compiler,"``.ts``, ``.tsx``" + Ruby [7]_,"up to 3.02",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" + TypeScript [8]_,"2.6-4.4",Standard TypeScript compiler,"``.ts``, ``.tsx``" .. container:: footnote-group @@ -33,4 +33,5 @@ .. [4] Builds that execute on Java 7 to 16 can be analyzed. The analysis understands Java 16 standard language features. .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. .. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. - .. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. + .. [7] Requires glibc 2.17. + .. [8] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. From da412178ce687a24eeb45a575c3bdfc239faa783 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 20 Oct 2021 13:46:26 +0100 Subject: [PATCH 354/361] C++: Use set literals (more). --- .../Memory Management/NtohlArrayNoBound.qll | 8 +- .../Security/CWE/CWE-497/ExposedSystemData.ql | 121 +++++------------- .../CWE-273/PrivilegeDroppingOutoforder.ql | 15 +-- .../src/jsf/4.28 Portable Code/AV Rule 209.ql | 8 +- 4 files changed, 43 insertions(+), 109 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll index 9606fb968ec..37d5a5e5c1b 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll +++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll @@ -126,13 +126,7 @@ class MallocSizeExpr extends BufferAccess, FunctionCall { } class NetworkFunctionCall extends FunctionCall { - NetworkFunctionCall() { - getTarget().hasName("ntohd") or - getTarget().hasName("ntohf") or - getTarget().hasName("ntohl") or - getTarget().hasName("ntohll") or - getTarget().hasName("ntohs") - } + NetworkFunctionCall() { getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) } } class NetworkToBufferSizeConfiguration extends DataFlow::Configuration { diff --git a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql index bbe3b0805e1..8d016751f39 100644 --- a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql +++ b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql @@ -103,12 +103,7 @@ private predicate posixSystemInfo(FunctionCall source, Element use) { // - various filesystem parameters // int uname(struct utsname *buf) // - OS name and version - ( - source.getTarget().hasName("confstr") or - source.getTarget().hasName("statvfs") or - source.getTarget().hasName("fstatvfs") or - source.getTarget().hasName("uname") - ) and + source.getTarget().hasName(["confstr", "statvfs", "fstatvfs", "uname"]) and use = source.getArgument(1) } @@ -128,14 +123,9 @@ private predicate posixPWInfo(FunctionCall source, Element use) { // struct group *getgrnam(const char *name); // struct group *getgrgid(gid_t); // struct group *getgrent(void); - ( - source.getTarget().hasName("getpwnam") or - source.getTarget().hasName("getpwuid") or - source.getTarget().hasName("getpwent") or - source.getTarget().hasName("getgrnam") or - source.getTarget().hasName("getgrgid") or - source.getTarget().hasName("getgrent") - ) and + source + .getTarget() + .hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and use = source or // int getpwnam_r(const char *name, struct passwd *pwd, @@ -146,31 +136,15 @@ private predicate posixPWInfo(FunctionCall source, Element use) { // char *buf, size_t buflen, struct group **result); // int getgrnam_r(const char *name, struct group *grp, // char *buf, size_t buflen, struct group **result); - ( - source.getTarget().hasName("getpwnam_r") or - source.getTarget().hasName("getpwuid_r") or - source.getTarget().hasName("getgrgid_r") or - source.getTarget().hasName("getgrnam_r") - ) and - ( - use = source.getArgument(1) or - use = source.getArgument(2) or - use = source.getArgument(4) - ) + source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and + use = source.getArgument([1, 2, 4]) or // int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize, // struct passwd **result); // int getgrent_r(struct group *gbuf, char *buf, // size_t buflen, struct group **gbufp); - ( - source.getTarget().hasName("getpwent_r") or - source.getTarget().hasName("getgrent_r") - ) and - ( - use = source.getArgument(0) or - use = source.getArgument(1) or - use = source.getArgument(3) - ) + source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and + use = source.getArgument([0, 1, 3]) } /** @@ -190,13 +164,11 @@ private predicate windowsSystemInfo(FunctionCall source, Element use) { // BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo); // void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); // void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); - ( - source.getTarget().hasGlobalName("GetVersionEx") or - source.getTarget().hasGlobalName("GetVersionExA") or - source.getTarget().hasGlobalName("GetVersionExW") or - source.getTarget().hasGlobalName("GetSystemInfo") or - source.getTarget().hasGlobalName("GetNativeSystemInfo") - ) and + source + .getTarget() + .hasGlobalName([ + "GetVersionEx", "GetVersionExA", "GetVersionExW", "GetSystemInfo", "GetNativeSystemInfo" + ]) and use = source.getArgument(0) } @@ -216,11 +188,11 @@ private predicate windowsFolderPath(FunctionCall source, Element use) { // _In_ int csidl, // _In_ BOOL fCreate // ); - ( - source.getTarget().hasGlobalName("SHGetSpecialFolderPath") or - source.getTarget().hasGlobalName("SHGetSpecialFolderPathA") or - source.getTarget().hasGlobalName("SHGetSpecialFolderPathW") - ) and + source + .getTarget() + .hasGlobalName([ + "SHGetSpecialFolderPath", "SHGetSpecialFolderPathA", "SHGetSpecialFolderPathW" + ]) and use = source.getArgument(1) or // HRESULT SHGetKnownFolderPath( @@ -239,11 +211,7 @@ private predicate windowsFolderPath(FunctionCall source, Element use) { // _In_ DWORD dwFlags, // _Out_ LPTSTR pszPath // ); - ( - source.getTarget().hasGlobalName("SHGetFolderPath") or - source.getTarget().hasGlobalName("SHGetFolderPathA") or - source.getTarget().hasGlobalName("SHGetFolderPathW") - ) and + source.getTarget().hasGlobalName(["SHGetFolderPath", "SHGetFolderPathA", "SHGetFolderPathW"]) and use = source.getArgument(4) or // HRESULT SHGetFolderPathAndSubDir( @@ -254,11 +222,11 @@ private predicate windowsFolderPath(FunctionCall source, Element use) { // _In_ LPCTSTR pszSubDir, // _Out_ LPTSTR pszPath // ); - ( - source.getTarget().hasGlobalName("SHGetFolderPathAndSubDir") or - source.getTarget().hasGlobalName("SHGetFolderPathAndSubDirA") or - source.getTarget().hasGlobalName("SHGetFolderPathAndSubDirW") - ) and + source + .getTarget() + .hasGlobalName([ + "SHGetFolderPathAndSubDir", "SHGetFolderPathAndSubDirA", "SHGetFolderPathAndSubDirW" + ]) and use = source.getArgument(5) } @@ -273,11 +241,7 @@ class WindowsFolderPath extends SystemData { } private predicate logonUser(FunctionCall source, VariableAccess use) { - ( - source.getTarget().hasGlobalName("LogonUser") or - source.getTarget().hasGlobalName("LogonUserW") or - source.getTarget().hasGlobalName("LogonUserA") - ) and + source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and use = source.getAnArgument() } @@ -297,11 +261,7 @@ private predicate regQuery(FunctionCall source, VariableAccess use) { // _Out_opt_ LPTSTR lpValue, // _Inout_opt_ PLONG lpcbValue // ); - ( - source.getTarget().hasGlobalName("RegQueryValue") or - source.getTarget().hasGlobalName("RegQueryValueA") or - source.getTarget().hasGlobalName("RegQueryValueW") - ) and + source.getTarget().hasGlobalName(["RegQueryValue", "RegQueryValueA", "RegQueryValueW"]) and use = source.getArgument(2) or // LONG WINAPI RegQueryMultipleValues( @@ -311,11 +271,11 @@ private predicate regQuery(FunctionCall source, VariableAccess use) { // _Out_opt_ LPTSTR lpValueBuf, // _Inout_opt_ LPDWORD ldwTotsize // ); - ( - source.getTarget().hasGlobalName("RegQueryMultipleValues") or - source.getTarget().hasGlobalName("RegQueryMultipleValuesA") or - source.getTarget().hasGlobalName("RegQueryMultipleValuesW") - ) and + source + .getTarget() + .hasGlobalName([ + "RegQueryMultipleValues", "RegQueryMultipleValuesA", "RegQueryMultipleValuesW" + ]) and use = source.getArgument(3) or // LONG WINAPI RegQueryValueEx( @@ -326,11 +286,7 @@ private predicate regQuery(FunctionCall source, VariableAccess use) { // _Out_opt_ LPBYTE lpData, // _Inout_opt_ LPDWORD lpcbData // ); - ( - source.getTarget().hasGlobalName("RegQueryValueEx") or - source.getTarget().hasGlobalName("RegQueryValueExA") or - source.getTarget().hasGlobalName("RegQueryValueExW") - ) and + source.getTarget().hasGlobalName(["RegQueryValueEx", "RegQueryValueExA", "RegQueryValueExW"]) and use = source.getArgument(4) or // LONG WINAPI RegGetValue( @@ -342,11 +298,7 @@ private predicate regQuery(FunctionCall source, VariableAccess use) { // _Out_opt_ PVOID pvData, // _Inout_opt_ LPDWORD pcbData // ); - ( - source.getTarget().hasGlobalName("RegGetValue") or - source.getTarget().hasGlobalName("RegGetValueA") or - source.getTarget().hasGlobalName("RegGetValueW") - ) and + source.getTarget().hasGlobalName(["RegGetValue", "RegGetValueA", "RegGetValueW"]) and use = source.getArgument(5) } @@ -408,12 +360,7 @@ private predicate socketOutput(FunctionCall call, Expr data) { // const struct sockaddr *dest_addr, socklen_t addrlen); // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); // int write(int handle, void *buffer, int nbyte); - ( - call.getTarget().hasGlobalName("send") or - call.getTarget().hasGlobalName("sendto") or - call.getTarget().hasGlobalName("sendmsg") or - call.getTarget().hasGlobalName("write") - ) and + call.getTarget().hasGlobalName(["send", "sendto", "sendmsg", "write"]) and data = call.getArgument(1) and socketFileDescriptor(call.getArgument(0)) ) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql b/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql index 7798203205a..9d2faf793c5 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql @@ -44,14 +44,13 @@ class SetuidLikeWrapperCall extends FunctionCall { class CallBeforeSetuidFunctionCall extends FunctionCall { CallBeforeSetuidFunctionCall() { - ( - getTarget().hasGlobalName("setgid") or - getTarget().hasGlobalName("setresgid") or - // Compatibility may require skipping initgroups and setgroups return checks. - // A stricter best practice is to check the result and errnor for EPERM. - getTarget().hasGlobalName("initgroups") or - getTarget().hasGlobalName("setgroups") - ) and + getTarget() + .hasGlobalName([ + "setgid", "setresgid", + // Compatibility may require skipping initgroups and setgroups return checks. + // A stricter best practice is to check the result and errnor for EPERM. + "initgroups", "setgroups" + ]) and // setgid/setresgid/etc with the root group are false positives. not argumentMayBeRoot(getArgument(0)) } diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql index b881c5ed601..64a130f46e0 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql @@ -15,13 +15,7 @@ import cpp from Element u, ArithmeticType at where - ( - at.hasName("int") or - at.hasName("short") or - at.hasName("long") or - at.hasName("float") or - at.hasName("double") - ) and + at.hasName(["int", "short", "long", "float", "double"]) and u = at.getATypeNameUse() and not at instanceof WideCharType select u, "AV Rule 209: The basic types of int, short, long, float and double shall not be used." From 605494c3d1c70ff48dd50253329ba54a451fa546 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 20 Oct 2021 16:55:34 +0200 Subject: [PATCH 355/361] Python: Treat SyntaxErrors as warnings in diagnostics Rename going to happen in second commit, so git doesn't get too confused I don't actually recall where to lookup that warning is 1, and error is 2, but I took this from https://github.com/github/codeql/pull/6830/files#diff-460fc20823ced3b074784db804f2d4d6cfcad4f23fe5d264dc7496c782629a2eR121-R123 --- python/ql/src/Diagnostics/ExtractionErrors.ql | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/python/ql/src/Diagnostics/ExtractionErrors.ql b/python/ql/src/Diagnostics/ExtractionErrors.ql index 5d9ddee6eb7..ec3c1e1eadc 100644 --- a/python/ql/src/Diagnostics/ExtractionErrors.ql +++ b/python/ql/src/Diagnostics/ExtractionErrors.ql @@ -1,23 +1,36 @@ /** - * @name Python extraction errors - * @description List all extraction errors for Python files in the source code directory. + * @name Python extraction warnings + * @description List all extraction warnings for Python files in the source code directory. * @kind diagnostic - * @id py/diagnostics/extraction-errors + * @id py/diagnostics/extraction-warnings */ import python /** - * Gets the SARIF severity for errors. + * Gets the SARIF severity for warnings. * - * See point 3.27.10 in https://docs.oasis-open.org/sarif/sarif/v2.0/sarif-v2.0.html for - * what error means. + * See https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10541338 */ -int getErrorSeverity() { result = 2 } +int getWarningSeverity() { result = 1 } +// The spec +// https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10541338 +// defines error and warning as: +// +// "error": A serious problem was found. The condition encountered by the tool resulted +// in the analysis being halted or caused the results to be incorrect or incomplete. +// +// "warning": A problem that is not considered serious was found. The condition +// encountered by the tool is such that it is uncertain whether a problem occurred, or +// is such that the analysis might be incomplete but the results that were generated are +// probably valid. +// +// so SyntaxErrors are reported at the warning level, since analysis might be incomplete +// but the results that were generated are probably valid. from SyntaxError error, File file where file = error.getFile() and exists(file.getRelativePath()) select error, "Extraction failed in " + file + " with error " + error.getMessage(), - getErrorSeverity() + getWarningSeverity() From 8f28684d10e625c56c2f83db6027b7ed3b2030c3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 20 Oct 2021 17:01:33 +0200 Subject: [PATCH 356/361] Python: Rename `ExtractionErrors.ql` -> `ExtractionWarnings.ql` --- .../Diagnostics/{ExtractionErrors.ql => ExtractionWarnings.ql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/ql/src/Diagnostics/{ExtractionErrors.ql => ExtractionWarnings.ql} (100%) diff --git a/python/ql/src/Diagnostics/ExtractionErrors.ql b/python/ql/src/Diagnostics/ExtractionWarnings.ql similarity index 100% rename from python/ql/src/Diagnostics/ExtractionErrors.ql rename to python/ql/src/Diagnostics/ExtractionWarnings.ql From d0fd907582f6774c95b2a4b3876d2fbebd15270e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 20 Oct 2021 17:03:34 +0200 Subject: [PATCH 357/361] Python: Add change-note I reworded this slightly from what was done in C++, such that I can completely stand behind what it says. --- python/change-notes/2021-10-20-extraction-errors-as-warnings.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 python/change-notes/2021-10-20-extraction-errors-as-warnings.md diff --git a/python/change-notes/2021-10-20-extraction-errors-as-warnings.md b/python/change-notes/2021-10-20-extraction-errors-as-warnings.md new file mode 100644 index 00000000000..698435a2e3c --- /dev/null +++ b/python/change-notes/2021-10-20-extraction-errors-as-warnings.md @@ -0,0 +1,2 @@ +codescanning +* Problems with extraction that in most cases won't completely break the analysis are now reported as warnings rather than errors. From 8167e83ae51002237bca5a8b3217c38962dbf3e3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 20 Oct 2021 17:58:03 +0200 Subject: [PATCH 358/361] Python: Fix tests --- python/ql/test/query-tests/Diagnostics/ExtractionErrors.qlref | 1 - ...{ExtractionErrors.expected => ExtractionWarnings.expected} | 4 ++-- .../ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 python/ql/test/query-tests/Diagnostics/ExtractionErrors.qlref rename python/ql/test/query-tests/Diagnostics/{ExtractionErrors.expected => ExtractionWarnings.expected} (67%) create mode 100644 python/ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref diff --git a/python/ql/test/query-tests/Diagnostics/ExtractionErrors.qlref b/python/ql/test/query-tests/Diagnostics/ExtractionErrors.qlref deleted file mode 100644 index 488db09ab05..00000000000 --- a/python/ql/test/query-tests/Diagnostics/ExtractionErrors.qlref +++ /dev/null @@ -1 +0,0 @@ -Diagnostics/ExtractionErrors.ql diff --git a/python/ql/test/query-tests/Diagnostics/ExtractionErrors.expected b/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.expected similarity index 67% rename from python/ql/test/query-tests/Diagnostics/ExtractionErrors.expected rename to python/ql/test/query-tests/Diagnostics/ExtractionWarnings.expected index 4103e4d0cdc..026fbf9aa88 100644 --- a/python/ql/test/query-tests/Diagnostics/ExtractionErrors.expected +++ b/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.expected @@ -1,2 +1,2 @@ -| bad_encoding.py:2:11:2:11 | Encoding Error | Extraction failed in bad_encoding.py with error 'utf-8' codec can't decode byte 0x9d in position 87: invalid start byte | 2 | -| syntax_error.py:1:31:1:31 | Syntax Error | Extraction failed in syntax_error.py with error Syntax Error | 2 | +| bad_encoding.py:2:11:2:11 | Encoding Error | Extraction failed in bad_encoding.py with error 'utf-8' codec can't decode byte 0x9d in position 87: invalid start byte | 1 | +| syntax_error.py:1:31:1:31 | Syntax Error | Extraction failed in syntax_error.py with error Syntax Error | 1 | diff --git a/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref b/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref new file mode 100644 index 00000000000..2df3d933e8a --- /dev/null +++ b/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref @@ -0,0 +1 @@ +Diagnostics/ExtractionWarnings.ql From a1ce81c3d7e23fcd5e9f5e4e8f092b3e2956e553 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Wed, 20 Oct 2021 23:00:46 +0200 Subject: [PATCH 359/361] Update creating-codeql-databases.rst --- docs/codeql/codeql-cli/creating-codeql-databases.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index 52bd076e636..cfde8adb3db 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -116,6 +116,8 @@ Here, we have specified a ``--source-root`` path, which is the location where database creation is executed, but is not necessarily the checkout root of the codebase. +By default, files in ``node_modules`` and ``bower_components`` directories are not extracted. + Python ~~~~~~ From 852e9875bd0bbf4ba8d73c62c7ba05278bdfd7ca Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 21 Oct 2021 10:24:34 +0200 Subject: [PATCH 360/361] Python: Apply suggestions from code review Co-authored-by: Taus <tausbn@github.com> --- python/ql/src/Diagnostics/ExtractionWarnings.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/Diagnostics/ExtractionWarnings.ql b/python/ql/src/Diagnostics/ExtractionWarnings.ql index ec3c1e1eadc..553798a546e 100644 --- a/python/ql/src/Diagnostics/ExtractionWarnings.ql +++ b/python/ql/src/Diagnostics/ExtractionWarnings.ql @@ -26,7 +26,7 @@ int getWarningSeverity() { result = 1 } // is such that the analysis might be incomplete but the results that were generated are // probably valid. // -// so SyntaxErrors are reported at the warning level, since analysis might be incomplete +// So SyntaxErrors are reported at the warning level, since analysis might be incomplete // but the results that were generated are probably valid. from SyntaxError error, File file where From 4e40337d02d9118d5adeaacfe4309786346941bf Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 22 Oct 2021 10:12:18 +0200 Subject: [PATCH 361/361] C#: Improve join-order in `defaultDelegateConversion` --- csharp/ql/lib/semmle/code/csharp/Conversion.qll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/csharp/ql/lib/semmle/code/csharp/Conversion.qll b/csharp/ql/lib/semmle/code/csharp/Conversion.qll index 0c560d1d86f..d62055b6a17 100644 --- a/csharp/ql/lib/semmle/code/csharp/Conversion.qll +++ b/csharp/ql/lib/semmle/code/csharp/Conversion.qll @@ -552,11 +552,16 @@ private predicate defaultDynamicConversion(Type fromType, Type toType) { fromType instanceof RefType and toType instanceof DynamicType } +pragma[noinline] +private predicate systemDelegateBaseType(RefType t) { + t = any(SystemDelegateClass c).getABaseType*() +} + // This is a deliberate, small cartesian product, so we have manually lifted it to force the // evaluator to evaluate it in its entirety, rather than trying to optimize it in context. pragma[noinline] private predicate defaultDelegateConversion(RefType fromType, RefType toType) { - fromType instanceof DelegateType and toType = any(SystemDelegateClass c).getABaseType*() + fromType instanceof DelegateType and systemDelegateBaseType(toType) } private predicate convRefTypeRefType(RefType fromType, RefType toType) {