From b95566b02ae1a87f90b5cebf01ecda2d7b66359e Mon Sep 17 00:00:00 2001 From: tyage Date: Thu, 29 Sep 2022 17:44:00 +0900 Subject: [PATCH 001/107] make json stringify tainted with arg's property --- .../javascript/dataflow/TaintTracking.qll | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index 5147bcf7f2a..4b6a9d2fc16 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -716,11 +716,40 @@ module TaintTracking { */ private class JsonStringifyTaintStep extends SharedTaintStep { override predicate serializeStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(JsonStringifyCall call | - pred = call.getArgument(0) and + exists(JsonStringifyCall call, DataFlow::Node arg | + arg = call.getArgument(0) and + ( + pred = arg or + findInObject(arg.asExpr(), pred.asExpr()) + ) and succ = call ) } + + // find target in root object recursively + private predicate findInObject(Expr root, Expr target) { + // when root is Object + exists(ObjectExpr object, Property property, Expr propertyVal | + object = root and + property = object.getAProperty() and + propertyVal = property.getInit() and + ( + target = property.getNameExpr() or + target = propertyVal or + findInObject(propertyVal, target) + ) + ) + or + // when root is Array + exists(ArrayExpr array, Expr child | + array = root and + child = array.getAChildExpr() and + ( + target = child or + findInObject(child, target) + ) + ) + } } /** From 0cb8e121e97f6039554ad5e56fcbb8e28a0754a7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 29 Sep 2022 17:41:21 +0200 Subject: [PATCH 002/107] Python: Fix flask request modeling This takes us part of the way. We still get multiple paths for the same alert, but that will be fixed in a different PR. --- python/ql/lib/semmle/python/frameworks/Flask.qll | 8 +------- .../src/change-notes/2022-09-29-flask-source-modeling.md | 4 ++++ 2 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 python/ql/src/change-notes/2022-09-29-flask-source-modeling.md diff --git a/python/ql/lib/semmle/python/frameworks/Flask.qll b/python/ql/lib/semmle/python/frameworks/Flask.qll index 2f272723182..a8291826577 100644 --- a/python/ql/lib/semmle/python/frameworks/Flask.qll +++ b/python/ql/lib/semmle/python/frameworks/Flask.qll @@ -354,13 +354,7 @@ module Flask { * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Request */ private class FlaskRequestSource extends RemoteFlowSource::Range { - FlaskRequestSource() { - this = request().getAValueReachableFromSource() and - not any(Import imp).contains(this.asExpr()) and - not exists(ControlFlowNode def | this.asVar().getSourceVariable().hasDefiningNode(def) | - any(Import imp).contains(def.getNode()) - ) - } + FlaskRequestSource() { this = request().asSource() } override string getSourceType() { result = "flask.request" } } diff --git a/python/ql/src/change-notes/2022-09-29-flask-source-modeling.md b/python/ql/src/change-notes/2022-09-29-flask-source-modeling.md new file mode 100644 index 00000000000..59774242825 --- /dev/null +++ b/python/ql/src/change-notes/2022-09-29-flask-source-modeling.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed how `flask.request` is modeled as a RemoteFlowSource, such that we show fewer duplicated alert messages for Code Scanning alerts. The import, such as `from flask import request`, will now be shown as the first step in a path explanation. From a5998fbe4d6588a558eed4e8fedfdd9c96ed670a Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Fri, 2 Sep 2022 12:30:35 +1200 Subject: [PATCH 003/107] Ruby: Model ActionController::Parameters Add flow summaries for methods on ActionController::Parameters, which mostly propagate taint from receiver to return value. --- .../ruby/frameworks/ActionController.qll | 120 ++++++++++++ .../frameworks/ActionController.expected | 118 ++++++++++++ .../action_controller/params-flow.expected | 175 ++++++++++++++++++ .../action_controller/params-flow.ql | 16 ++ .../action_controller/params_flow.rb | 151 +++++++++++++++ .../security/cwe-601/UrlRedirect.expected | 3 + 6 files changed, 583 insertions(+) create mode 100644 ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected create mode 100644 ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql create mode 100644 ruby/ql/test/library-tests/frameworks/action_controller/params_flow.rb diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll index 2e1c11e3251..88c8f75bc3b 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll @@ -374,3 +374,123 @@ private class SendFile extends FileSystemAccess::Range, DataFlow::CallNode { override DataFlow::Node getAPathArgument() { result = this.getArgument(0) } } + +private module ParamsSummaries { + private import codeql.ruby.dataflow.FlowSummary + + /** + * An instance of `ActionController::Parameters`, including those returned + * from method calls on other instances. + */ + private class ParamsInstance extends DataFlow::Node { + ParamsInstance() { + this.asExpr().getExpr() instanceof ParamsCall + or + exists(DataFlow::CallNode call | call = this | + call.getReceiver() instanceof ParamsInstance and + call.getMethodName() = paramsMethodReturningParamsInstance() + ) + or + exists(DataFlow::LocalSourceNode prev | prev.flowsTo(this)) + } + } + + /** + * Methods on `ActionController::Parameters` that return an instance of + * `ActionController::Parameters`. + */ + string paramsMethodReturningParamsInstance() { + result = + [ + "concat", "concat!", "compact_blank", "deep_dup", "deep_transform_keys", "delete_if", + // dig doesn't always return a Parameters instance, but it will if the + // given key refers to a nested hash parameter. + "dig", "each", "each_key", "each_pair", "each_value", "except", "keep_if", "merge", + "merge!", "permit", "reject", "reject!", "reverse_merge", "reverse_merge!", "select", + "select!", "slice", "slice!", "transform_keys", "transform_keys!", "transform_values", + "transform_values!", "with_defaults", "with_defaults!" + ] + } + + /** + * Methods on `ActionController::Parameters` that propagate taint from + * receiver to return value. + */ + string methodReturnsTaintFromSelf() { + result = + [ + "as_json", "permit", "require", "required", "deep_dup", "deep_transform_keys", + "deep_transform_keys!", "delete_if", "extract!", "keep_if", "select", "select!", "reject", + "reject!", "to_h", "to_hash", "to_query", "to_param", "to_unsafe_h", "to_unsafe_hash", + "transform_keys", "transform_keys!", "transform_values", "transform_values!", "values_at" + ] + } + + /** + * Methods on `ActionController::Parameters` which propagate taint from + * receiver to return value. + */ + private class TaintReturnFromSelf extends SummarizedCallable { + // TODO: better name? + TaintReturnFromSelf() { this = "ActionController::Parameters#" } + + override MethodCall getACall() { + any(ParamsInstance i).asExpr().getExpr() = result.getReceiver() and + result.getMethodName() = methodReturnsTaintFromSelf() + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + input = "Argument[self]" and + output = "ReturnValue" and + preservesValue = false + } + } + + /** + * `#merge` + * Returns a new ActionController::Parameters with all keys from other_hash merged into current hash. + * `#reverse_merge` + * `#with_defaults` + * Returns a new ActionController::Parameters with all keys from current hash merged into other_hash. + */ + private class MergeSummary extends SummarizedCallable { + MergeSummary() { this = "ActionController::Parameters#merge" } + + override MethodCall getACall() { + result.getMethodName() = ["merge", "reverse_merge", "with_defaults"] and + exists(ParamsInstance i | + i.asExpr().getExpr() = [result.getReceiver(), result.getArgument(0)] + ) + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + input = ["Argument[self]", "Argument[0]"] and + output = "ReturnValue" and + preservesValue = false + } + } + + /** + * `#merge!` + * Returns current ActionController::Parameters instance with current hash merged into other_hash. + * `#reverse_merge!` + * `#with_defaults!` + * Returns a new ActionController::Parameters with all keys from current hash merged into other_hash. + */ + private class MergeBangSummary extends SummarizedCallable { + MergeBangSummary() { this = "ActionController::Parameters#merge!" } + + override MethodCall getACall() { + result.getMethodName() = ["merge!", "reverse_merge!", "with_defaults!"] and + exists(ParamsInstance i | + i.asExpr().getExpr() = [result.getReceiver(), result.getArgument(0)] + ) + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + input = ["Argument[self]", "Argument[0]"] and + output = ["ReturnValue", "Argument[self]"] and + preservesValue = false + } + } +} diff --git a/ruby/ql/test/library-tests/frameworks/ActionController.expected b/ruby/ql/test/library-tests/frameworks/ActionController.expected index f91583f29af..f5a5f703abf 100644 --- a/ruby/ql/test/library-tests/frameworks/ActionController.expected +++ b/ruby/ql/test/library-tests/frameworks/ActionController.expected @@ -1,4 +1,5 @@ actionControllerControllerClasses +| action_controller/params_flow.rb:1:1:151:3 | MyController | | active_record/ActiveRecord.rb:23:1:39:3 | FooController | | active_record/ActiveRecord.rb:41:1:64:3 | BarController | | active_record/ActiveRecord.rb:66:1:98:3 | BazController | @@ -11,6 +12,39 @@ actionControllerControllerClasses | app/controllers/tags_controller.rb:1:1:2:3 | TagsController | | app/controllers/users/notifications_controller.rb:2:3:5:5 | NotificationsController | actionControllerActionMethods +| action_controller/params_flow.rb:2:3:4:5 | m1 | +| action_controller/params_flow.rb:6:3:8:5 | m2 | +| action_controller/params_flow.rb:10:3:12:5 | m2 | +| action_controller/params_flow.rb:14:3:16:5 | m3 | +| action_controller/params_flow.rb:18:3:20:5 | m4 | +| action_controller/params_flow.rb:22:3:24:5 | m5 | +| action_controller/params_flow.rb:26:3:28:5 | m6 | +| action_controller/params_flow.rb:30:3:32:5 | m7 | +| action_controller/params_flow.rb:34:3:36:5 | m8 | +| action_controller/params_flow.rb:38:3:40:5 | m9 | +| action_controller/params_flow.rb:42:3:44:5 | m10 | +| action_controller/params_flow.rb:46:3:48:5 | m11 | +| action_controller/params_flow.rb:50:3:52:5 | m12 | +| action_controller/params_flow.rb:54:3:56:5 | m13 | +| action_controller/params_flow.rb:58:3:60:5 | m14 | +| action_controller/params_flow.rb:62:3:64:5 | m15 | +| action_controller/params_flow.rb:66:3:68:5 | m16 | +| action_controller/params_flow.rb:70:3:72:5 | m17 | +| action_controller/params_flow.rb:74:3:76:5 | m18 | +| action_controller/params_flow.rb:78:3:80:5 | m19 | +| action_controller/params_flow.rb:82:3:84:5 | m20 | +| action_controller/params_flow.rb:86:3:88:5 | m21 | +| action_controller/params_flow.rb:90:3:92:5 | m22 | +| action_controller/params_flow.rb:94:3:96:5 | m23 | +| action_controller/params_flow.rb:98:3:100:5 | m24 | +| action_controller/params_flow.rb:102:3:104:5 | m25 | +| action_controller/params_flow.rb:106:3:108:5 | m26 | +| action_controller/params_flow.rb:110:3:113:5 | m27 | +| action_controller/params_flow.rb:115:3:118:5 | m28 | +| action_controller/params_flow.rb:120:3:123:5 | m29 | +| action_controller/params_flow.rb:125:3:132:5 | m30 | +| action_controller/params_flow.rb:134:3:141:5 | m31 | +| action_controller/params_flow.rb:143:3:150:5 | m32 | | active_record/ActiveRecord.rb:27:3:38:5 | some_request_handler | | active_record/ActiveRecord.rb:42:3:47:5 | some_other_request_handler | | active_record/ActiveRecord.rb:49:3:63:5 | safe_paths | @@ -39,6 +73,48 @@ actionControllerActionMethods | app/controllers/posts_controller.rb:8:3:9:5 | upvote | | app/controllers/users/notifications_controller.rb:3:5:4:7 | mark_as_read | paramsCalls +| action_controller/params_flow.rb:3:10:3:15 | call to params | +| action_controller/params_flow.rb:7:10:7:15 | call to params | +| action_controller/params_flow.rb:11:10:11:15 | call to params | +| action_controller/params_flow.rb:15:10:15:15 | call to params | +| action_controller/params_flow.rb:19:10:19:15 | call to params | +| action_controller/params_flow.rb:23:10:23:15 | call to params | +| action_controller/params_flow.rb:27:10:27:15 | call to params | +| action_controller/params_flow.rb:31:10:31:15 | call to params | +| action_controller/params_flow.rb:35:10:35:15 | call to params | +| action_controller/params_flow.rb:39:10:39:15 | call to params | +| action_controller/params_flow.rb:43:10:43:15 | call to params | +| action_controller/params_flow.rb:47:10:47:15 | call to params | +| action_controller/params_flow.rb:51:10:51:15 | call to params | +| action_controller/params_flow.rb:55:10:55:15 | call to params | +| action_controller/params_flow.rb:59:10:59:15 | call to params | +| action_controller/params_flow.rb:63:10:63:15 | call to params | +| action_controller/params_flow.rb:67:10:67:15 | call to params | +| action_controller/params_flow.rb:71:10:71:15 | call to params | +| action_controller/params_flow.rb:75:10:75:15 | call to params | +| action_controller/params_flow.rb:79:10:79:15 | call to params | +| action_controller/params_flow.rb:83:10:83:15 | call to params | +| action_controller/params_flow.rb:87:10:87:15 | call to params | +| action_controller/params_flow.rb:91:10:91:15 | call to params | +| action_controller/params_flow.rb:95:10:95:15 | call to params | +| action_controller/params_flow.rb:99:10:99:15 | call to params | +| action_controller/params_flow.rb:103:10:103:15 | call to params | +| action_controller/params_flow.rb:107:10:107:15 | call to params | +| action_controller/params_flow.rb:111:10:111:15 | call to params | +| action_controller/params_flow.rb:112:23:112:28 | call to params | +| action_controller/params_flow.rb:116:10:116:15 | call to params | +| action_controller/params_flow.rb:117:31:117:36 | call to params | +| action_controller/params_flow.rb:121:10:121:15 | call to params | +| action_controller/params_flow.rb:122:31:122:36 | call to params | +| action_controller/params_flow.rb:126:10:126:15 | call to params | +| action_controller/params_flow.rb:127:24:127:29 | call to params | +| action_controller/params_flow.rb:130:14:130:19 | call to params | +| action_controller/params_flow.rb:135:10:135:15 | call to params | +| action_controller/params_flow.rb:136:32:136:37 | call to params | +| action_controller/params_flow.rb:139:22:139:27 | call to params | +| action_controller/params_flow.rb:144:10:144:15 | call to params | +| action_controller/params_flow.rb:145:32:145:37 | call to params | +| action_controller/params_flow.rb:148:22:148:27 | call to params | | active_record/ActiveRecord.rb:28:30:28:35 | call to params | | active_record/ActiveRecord.rb:29:29:29:34 | call to params | | active_record/ActiveRecord.rb:30:31:30:36 | call to params | @@ -71,6 +147,48 @@ paramsCalls | app/controllers/foo/bars_controller.rb:22:10:22:15 | call to params | | app/views/foo/bars/show.html.erb:5:9:5:14 | call to params | paramsSources +| action_controller/params_flow.rb:3:10:3:15 | call to params | +| action_controller/params_flow.rb:7:10:7:15 | call to params | +| action_controller/params_flow.rb:11:10:11:15 | call to params | +| action_controller/params_flow.rb:15:10:15:15 | call to params | +| action_controller/params_flow.rb:19:10:19:15 | call to params | +| action_controller/params_flow.rb:23:10:23:15 | call to params | +| action_controller/params_flow.rb:27:10:27:15 | call to params | +| action_controller/params_flow.rb:31:10:31:15 | call to params | +| action_controller/params_flow.rb:35:10:35:15 | call to params | +| action_controller/params_flow.rb:39:10:39:15 | call to params | +| action_controller/params_flow.rb:43:10:43:15 | call to params | +| action_controller/params_flow.rb:47:10:47:15 | call to params | +| action_controller/params_flow.rb:51:10:51:15 | call to params | +| action_controller/params_flow.rb:55:10:55:15 | call to params | +| action_controller/params_flow.rb:59:10:59:15 | call to params | +| action_controller/params_flow.rb:63:10:63:15 | call to params | +| action_controller/params_flow.rb:67:10:67:15 | call to params | +| action_controller/params_flow.rb:71:10:71:15 | call to params | +| action_controller/params_flow.rb:75:10:75:15 | call to params | +| action_controller/params_flow.rb:79:10:79:15 | call to params | +| action_controller/params_flow.rb:83:10:83:15 | call to params | +| action_controller/params_flow.rb:87:10:87:15 | call to params | +| action_controller/params_flow.rb:91:10:91:15 | call to params | +| action_controller/params_flow.rb:95:10:95:15 | call to params | +| action_controller/params_flow.rb:99:10:99:15 | call to params | +| action_controller/params_flow.rb:103:10:103:15 | call to params | +| action_controller/params_flow.rb:107:10:107:15 | call to params | +| action_controller/params_flow.rb:111:10:111:15 | call to params | +| action_controller/params_flow.rb:112:23:112:28 | call to params | +| action_controller/params_flow.rb:116:10:116:15 | call to params | +| action_controller/params_flow.rb:117:31:117:36 | call to params | +| action_controller/params_flow.rb:121:10:121:15 | call to params | +| action_controller/params_flow.rb:122:31:122:36 | call to params | +| action_controller/params_flow.rb:126:10:126:15 | call to params | +| action_controller/params_flow.rb:127:24:127:29 | call to params | +| action_controller/params_flow.rb:130:14:130:19 | call to params | +| action_controller/params_flow.rb:135:10:135:15 | call to params | +| action_controller/params_flow.rb:136:32:136:37 | call to params | +| action_controller/params_flow.rb:139:22:139:27 | call to params | +| action_controller/params_flow.rb:144:10:144:15 | call to params | +| action_controller/params_flow.rb:145:32:145:37 | call to params | +| action_controller/params_flow.rb:148:22:148:27 | call to params | | active_record/ActiveRecord.rb:28:30:28:35 | call to params | | active_record/ActiveRecord.rb:29:29:29:34 | call to params | | active_record/ActiveRecord.rb:30:31:30:36 | call to params | diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected new file mode 100644 index 00000000000..d06e3862b30 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected @@ -0,0 +1,175 @@ +failures +edges +| params_flow.rb:3:10:3:15 | call to params : | params_flow.rb:3:10:3:19 | ...[...] | +| params_flow.rb:7:10:7:15 | call to params : | params_flow.rb:7:10:7:23 | call to as_json | +| params_flow.rb:15:10:15:15 | call to params : | params_flow.rb:15:10:15:33 | call to permit | +| params_flow.rb:19:10:19:15 | call to params : | params_flow.rb:19:10:19:34 | call to require | +| params_flow.rb:23:10:23:15 | call to params : | params_flow.rb:23:10:23:35 | call to required | +| params_flow.rb:27:10:27:15 | call to params : | params_flow.rb:27:10:27:24 | call to deep_dup | +| params_flow.rb:31:10:31:15 | call to params : | params_flow.rb:31:10:31:45 | call to deep_transform_keys | +| params_flow.rb:35:10:35:15 | call to params : | params_flow.rb:35:10:35:46 | call to deep_transform_keys! | +| params_flow.rb:39:10:39:15 | call to params : | params_flow.rb:39:10:39:48 | call to delete_if | +| params_flow.rb:43:10:43:15 | call to params : | params_flow.rb:43:10:43:32 | call to extract! | +| params_flow.rb:47:10:47:15 | call to params : | params_flow.rb:47:10:47:46 | call to keep_if | +| params_flow.rb:51:10:51:15 | call to params : | params_flow.rb:51:10:51:45 | call to select | +| params_flow.rb:55:10:55:15 | call to params : | params_flow.rb:55:10:55:46 | call to select! | +| params_flow.rb:59:10:59:15 | call to params : | params_flow.rb:59:10:59:45 | call to reject | +| params_flow.rb:63:10:63:15 | call to params : | params_flow.rb:63:10:63:46 | call to reject! | +| params_flow.rb:67:10:67:15 | call to params : | params_flow.rb:67:10:67:20 | call to to_h | +| params_flow.rb:71:10:71:15 | call to params : | params_flow.rb:71:10:71:23 | call to to_hash | +| params_flow.rb:75:10:75:15 | call to params : | params_flow.rb:75:10:75:24 | call to to_query | +| params_flow.rb:79:10:79:15 | call to params : | params_flow.rb:79:10:79:24 | call to to_param | +| params_flow.rb:83:10:83:15 | call to params : | params_flow.rb:83:10:83:27 | call to to_unsafe_h | +| params_flow.rb:87:10:87:15 | call to params : | params_flow.rb:87:10:87:30 | call to to_unsafe_hash | +| params_flow.rb:91:10:91:15 | call to params : | params_flow.rb:91:10:91:40 | call to transform_keys | +| params_flow.rb:95:10:95:15 | call to params : | params_flow.rb:95:10:95:41 | call to transform_keys! | +| params_flow.rb:99:10:99:15 | call to params : | params_flow.rb:99:10:99:42 | call to transform_values | +| params_flow.rb:103:10:103:15 | call to params : | params_flow.rb:103:10:103:43 | call to transform_values! | +| params_flow.rb:107:10:107:15 | call to params : | params_flow.rb:107:10:107:33 | call to values_at | +| params_flow.rb:111:10:111:15 | call to params : | params_flow.rb:111:10:111:29 | call to merge | +| params_flow.rb:112:23:112:28 | call to params : | params_flow.rb:112:10:112:29 | call to merge | +| params_flow.rb:116:10:116:15 | call to params : | params_flow.rb:116:10:116:37 | call to reverse_merge | +| params_flow.rb:117:31:117:36 | call to params : | params_flow.rb:117:10:117:37 | call to reverse_merge | +| params_flow.rb:121:10:121:15 | call to params : | params_flow.rb:121:10:121:43 | call to with_defaults | +| params_flow.rb:122:31:122:36 | call to params : | params_flow.rb:122:10:122:37 | call to with_defaults | +| params_flow.rb:126:10:126:15 | call to params : | params_flow.rb:126:10:126:30 | call to merge! | +| params_flow.rb:127:24:127:29 | call to params : | params_flow.rb:127:10:127:30 | call to merge! | +| params_flow.rb:130:5:130:5 | [post] p : | params_flow.rb:131:10:131:10 | p | +| params_flow.rb:130:14:130:19 | call to params : | params_flow.rb:130:5:130:5 | [post] p : | +| params_flow.rb:135:10:135:15 | call to params : | params_flow.rb:135:10:135:38 | call to reverse_merge! | +| params_flow.rb:136:32:136:37 | call to params : | params_flow.rb:136:10:136:38 | call to reverse_merge! | +| params_flow.rb:139:5:139:5 | [post] p : | params_flow.rb:140:10:140:10 | p | +| params_flow.rb:139:22:139:27 | call to params : | params_flow.rb:139:5:139:5 | [post] p : | +| params_flow.rb:144:10:144:15 | call to params : | params_flow.rb:144:10:144:44 | call to with_defaults! | +| params_flow.rb:145:32:145:37 | call to params : | params_flow.rb:145:10:145:38 | call to with_defaults! | +| params_flow.rb:148:5:148:5 | [post] p : | params_flow.rb:149:10:149:10 | p | +| params_flow.rb:148:22:148:27 | call to params : | params_flow.rb:148:5:148:5 | [post] p : | +nodes +| params_flow.rb:3:10:3:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:3:10:3:19 | ...[...] | semmle.label | ...[...] | +| params_flow.rb:7:10:7:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:7:10:7:23 | call to as_json | semmle.label | call to as_json | +| params_flow.rb:15:10:15:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:15:10:15:33 | call to permit | semmle.label | call to permit | +| params_flow.rb:19:10:19:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:19:10:19:34 | call to require | semmle.label | call to require | +| params_flow.rb:23:10:23:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:23:10:23:35 | call to required | semmle.label | call to required | +| params_flow.rb:27:10:27:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:27:10:27:24 | call to deep_dup | semmle.label | call to deep_dup | +| params_flow.rb:31:10:31:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:31:10:31:45 | call to deep_transform_keys | semmle.label | call to deep_transform_keys | +| params_flow.rb:35:10:35:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:35:10:35:46 | call to deep_transform_keys! | semmle.label | call to deep_transform_keys! | +| params_flow.rb:39:10:39:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:39:10:39:48 | call to delete_if | semmle.label | call to delete_if | +| params_flow.rb:43:10:43:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:43:10:43:32 | call to extract! | semmle.label | call to extract! | +| params_flow.rb:47:10:47:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:47:10:47:46 | call to keep_if | semmle.label | call to keep_if | +| params_flow.rb:51:10:51:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:51:10:51:45 | call to select | semmle.label | call to select | +| params_flow.rb:55:10:55:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:55:10:55:46 | call to select! | semmle.label | call to select! | +| params_flow.rb:59:10:59:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:59:10:59:45 | call to reject | semmle.label | call to reject | +| params_flow.rb:63:10:63:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:63:10:63:46 | call to reject! | semmle.label | call to reject! | +| params_flow.rb:67:10:67:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:67:10:67:20 | call to to_h | semmle.label | call to to_h | +| params_flow.rb:71:10:71:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:71:10:71:23 | call to to_hash | semmle.label | call to to_hash | +| params_flow.rb:75:10:75:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:75:10:75:24 | call to to_query | semmle.label | call to to_query | +| params_flow.rb:79:10:79:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:79:10:79:24 | call to to_param | semmle.label | call to to_param | +| params_flow.rb:83:10:83:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:83:10:83:27 | call to to_unsafe_h | semmle.label | call to to_unsafe_h | +| params_flow.rb:87:10:87:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:87:10:87:30 | call to to_unsafe_hash | semmle.label | call to to_unsafe_hash | +| params_flow.rb:91:10:91:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:91:10:91:40 | call to transform_keys | semmle.label | call to transform_keys | +| params_flow.rb:95:10:95:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:95:10:95:41 | call to transform_keys! | semmle.label | call to transform_keys! | +| params_flow.rb:99:10:99:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:99:10:99:42 | call to transform_values | semmle.label | call to transform_values | +| params_flow.rb:103:10:103:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:103:10:103:43 | call to transform_values! | semmle.label | call to transform_values! | +| params_flow.rb:107:10:107:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:107:10:107:33 | call to values_at | semmle.label | call to values_at | +| params_flow.rb:111:10:111:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:111:10:111:29 | call to merge | semmle.label | call to merge | +| params_flow.rb:112:10:112:29 | call to merge | semmle.label | call to merge | +| params_flow.rb:112:23:112:28 | call to params : | semmle.label | call to params : | +| params_flow.rb:116:10:116:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:116:10:116:37 | call to reverse_merge | semmle.label | call to reverse_merge | +| params_flow.rb:117:10:117:37 | call to reverse_merge | semmle.label | call to reverse_merge | +| params_flow.rb:117:31:117:36 | call to params : | semmle.label | call to params : | +| params_flow.rb:121:10:121:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:121:10:121:43 | call to with_defaults | semmle.label | call to with_defaults | +| params_flow.rb:122:10:122:37 | call to with_defaults | semmle.label | call to with_defaults | +| params_flow.rb:122:31:122:36 | call to params : | semmle.label | call to params : | +| params_flow.rb:126:10:126:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:126:10:126:30 | call to merge! | semmle.label | call to merge! | +| params_flow.rb:127:10:127:30 | call to merge! | semmle.label | call to merge! | +| params_flow.rb:127:24:127:29 | call to params : | semmle.label | call to params : | +| params_flow.rb:130:5:130:5 | [post] p : | semmle.label | [post] p : | +| params_flow.rb:130:14:130:19 | call to params : | semmle.label | call to params : | +| params_flow.rb:131:10:131:10 | p | semmle.label | p | +| params_flow.rb:135:10:135:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:135:10:135:38 | call to reverse_merge! | semmle.label | call to reverse_merge! | +| params_flow.rb:136:10:136:38 | call to reverse_merge! | semmle.label | call to reverse_merge! | +| params_flow.rb:136:32:136:37 | call to params : | semmle.label | call to params : | +| params_flow.rb:139:5:139:5 | [post] p : | semmle.label | [post] p : | +| params_flow.rb:139:22:139:27 | call to params : | semmle.label | call to params : | +| params_flow.rb:140:10:140:10 | p | semmle.label | p | +| params_flow.rb:144:10:144:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:144:10:144:44 | call to with_defaults! | semmle.label | call to with_defaults! | +| params_flow.rb:145:10:145:38 | call to with_defaults! | semmle.label | call to with_defaults! | +| params_flow.rb:145:32:145:37 | call to params : | semmle.label | call to params : | +| params_flow.rb:148:5:148:5 | [post] p : | semmle.label | [post] p : | +| params_flow.rb:148:22:148:27 | call to params : | semmle.label | call to params : | +| params_flow.rb:149:10:149:10 | p | semmle.label | p | +subpaths +#select +| params_flow.rb:3:10:3:19 | ...[...] | params_flow.rb:3:10:3:15 | call to params : | params_flow.rb:3:10:3:19 | ...[...] | $@ | params_flow.rb:3:10:3:15 | call to params : | call to params : | +| params_flow.rb:7:10:7:23 | call to as_json | params_flow.rb:7:10:7:15 | call to params : | params_flow.rb:7:10:7:23 | call to as_json | $@ | params_flow.rb:7:10:7:15 | call to params : | call to params : | +| params_flow.rb:15:10:15:33 | call to permit | params_flow.rb:15:10:15:15 | call to params : | params_flow.rb:15:10:15:33 | call to permit | $@ | params_flow.rb:15:10:15:15 | call to params : | call to params : | +| params_flow.rb:19:10:19:34 | call to require | params_flow.rb:19:10:19:15 | call to params : | params_flow.rb:19:10:19:34 | call to require | $@ | params_flow.rb:19:10:19:15 | call to params : | call to params : | +| params_flow.rb:23:10:23:35 | call to required | params_flow.rb:23:10:23:15 | call to params : | params_flow.rb:23:10:23:35 | call to required | $@ | params_flow.rb:23:10:23:15 | call to params : | call to params : | +| params_flow.rb:27:10:27:24 | call to deep_dup | params_flow.rb:27:10:27:15 | call to params : | params_flow.rb:27:10:27:24 | call to deep_dup | $@ | params_flow.rb:27:10:27:15 | call to params : | call to params : | +| params_flow.rb:31:10:31:45 | call to deep_transform_keys | params_flow.rb:31:10:31:15 | call to params : | params_flow.rb:31:10:31:45 | call to deep_transform_keys | $@ | params_flow.rb:31:10:31:15 | call to params : | call to params : | +| params_flow.rb:35:10:35:46 | call to deep_transform_keys! | params_flow.rb:35:10:35:15 | call to params : | params_flow.rb:35:10:35:46 | call to deep_transform_keys! | $@ | params_flow.rb:35:10:35:15 | call to params : | call to params : | +| params_flow.rb:39:10:39:48 | call to delete_if | params_flow.rb:39:10:39:15 | call to params : | params_flow.rb:39:10:39:48 | call to delete_if | $@ | params_flow.rb:39:10:39:15 | call to params : | call to params : | +| params_flow.rb:43:10:43:32 | call to extract! | params_flow.rb:43:10:43:15 | call to params : | params_flow.rb:43:10:43:32 | call to extract! | $@ | params_flow.rb:43:10:43:15 | call to params : | call to params : | +| params_flow.rb:47:10:47:46 | call to keep_if | params_flow.rb:47:10:47:15 | call to params : | params_flow.rb:47:10:47:46 | call to keep_if | $@ | params_flow.rb:47:10:47:15 | call to params : | call to params : | +| params_flow.rb:51:10:51:45 | call to select | params_flow.rb:51:10:51:15 | call to params : | params_flow.rb:51:10:51:45 | call to select | $@ | params_flow.rb:51:10:51:15 | call to params : | call to params : | +| params_flow.rb:55:10:55:46 | call to select! | params_flow.rb:55:10:55:15 | call to params : | params_flow.rb:55:10:55:46 | call to select! | $@ | params_flow.rb:55:10:55:15 | call to params : | call to params : | +| params_flow.rb:59:10:59:45 | call to reject | params_flow.rb:59:10:59:15 | call to params : | params_flow.rb:59:10:59:45 | call to reject | $@ | params_flow.rb:59:10:59:15 | call to params : | call to params : | +| params_flow.rb:63:10:63:46 | call to reject! | params_flow.rb:63:10:63:15 | call to params : | params_flow.rb:63:10:63:46 | call to reject! | $@ | params_flow.rb:63:10:63:15 | call to params : | call to params : | +| params_flow.rb:67:10:67:20 | call to to_h | params_flow.rb:67:10:67:15 | call to params : | params_flow.rb:67:10:67:20 | call to to_h | $@ | params_flow.rb:67:10:67:15 | call to params : | call to params : | +| params_flow.rb:71:10:71:23 | call to to_hash | params_flow.rb:71:10:71:15 | call to params : | params_flow.rb:71:10:71:23 | call to to_hash | $@ | params_flow.rb:71:10:71:15 | call to params : | call to params : | +| params_flow.rb:75:10:75:24 | call to to_query | params_flow.rb:75:10:75:15 | call to params : | params_flow.rb:75:10:75:24 | call to to_query | $@ | params_flow.rb:75:10:75:15 | call to params : | call to params : | +| params_flow.rb:79:10:79:24 | call to to_param | params_flow.rb:79:10:79:15 | call to params : | params_flow.rb:79:10:79:24 | call to to_param | $@ | params_flow.rb:79:10:79:15 | call to params : | call to params : | +| params_flow.rb:83:10:83:27 | call to to_unsafe_h | params_flow.rb:83:10:83:15 | call to params : | params_flow.rb:83:10:83:27 | call to to_unsafe_h | $@ | params_flow.rb:83:10:83:15 | call to params : | call to params : | +| params_flow.rb:87:10:87:30 | call to to_unsafe_hash | params_flow.rb:87:10:87:15 | call to params : | params_flow.rb:87:10:87:30 | call to to_unsafe_hash | $@ | params_flow.rb:87:10:87:15 | call to params : | call to params : | +| params_flow.rb:91:10:91:40 | call to transform_keys | params_flow.rb:91:10:91:15 | call to params : | params_flow.rb:91:10:91:40 | call to transform_keys | $@ | params_flow.rb:91:10:91:15 | call to params : | call to params : | +| params_flow.rb:95:10:95:41 | call to transform_keys! | params_flow.rb:95:10:95:15 | call to params : | params_flow.rb:95:10:95:41 | call to transform_keys! | $@ | params_flow.rb:95:10:95:15 | call to params : | call to params : | +| params_flow.rb:99:10:99:42 | call to transform_values | params_flow.rb:99:10:99:15 | call to params : | params_flow.rb:99:10:99:42 | call to transform_values | $@ | params_flow.rb:99:10:99:15 | call to params : | call to params : | +| params_flow.rb:103:10:103:43 | call to transform_values! | params_flow.rb:103:10:103:15 | call to params : | params_flow.rb:103:10:103:43 | call to transform_values! | $@ | params_flow.rb:103:10:103:15 | call to params : | call to params : | +| params_flow.rb:107:10:107:33 | call to values_at | params_flow.rb:107:10:107:15 | call to params : | params_flow.rb:107:10:107:33 | call to values_at | $@ | params_flow.rb:107:10:107:15 | call to params : | call to params : | +| params_flow.rb:111:10:111:29 | call to merge | params_flow.rb:111:10:111:15 | call to params : | params_flow.rb:111:10:111:29 | call to merge | $@ | params_flow.rb:111:10:111:15 | call to params : | call to params : | +| params_flow.rb:112:10:112:29 | call to merge | params_flow.rb:112:23:112:28 | call to params : | params_flow.rb:112:10:112:29 | call to merge | $@ | params_flow.rb:112:23:112:28 | call to params : | call to params : | +| params_flow.rb:116:10:116:37 | call to reverse_merge | params_flow.rb:116:10:116:15 | call to params : | params_flow.rb:116:10:116:37 | call to reverse_merge | $@ | params_flow.rb:116:10:116:15 | call to params : | call to params : | +| params_flow.rb:117:10:117:37 | call to reverse_merge | params_flow.rb:117:31:117:36 | call to params : | params_flow.rb:117:10:117:37 | call to reverse_merge | $@ | params_flow.rb:117:31:117:36 | call to params : | call to params : | +| params_flow.rb:121:10:121:43 | call to with_defaults | params_flow.rb:121:10:121:15 | call to params : | params_flow.rb:121:10:121:43 | call to with_defaults | $@ | params_flow.rb:121:10:121:15 | call to params : | call to params : | +| params_flow.rb:122:10:122:37 | call to with_defaults | params_flow.rb:122:31:122:36 | call to params : | params_flow.rb:122:10:122:37 | call to with_defaults | $@ | params_flow.rb:122:31:122:36 | call to params : | call to params : | +| params_flow.rb:126:10:126:30 | call to merge! | params_flow.rb:126:10:126:15 | call to params : | params_flow.rb:126:10:126:30 | call to merge! | $@ | params_flow.rb:126:10:126:15 | call to params : | call to params : | +| params_flow.rb:127:10:127:30 | call to merge! | params_flow.rb:127:24:127:29 | call to params : | params_flow.rb:127:10:127:30 | call to merge! | $@ | params_flow.rb:127:24:127:29 | call to params : | call to params : | +| params_flow.rb:131:10:131:10 | p | params_flow.rb:130:14:130:19 | call to params : | params_flow.rb:131:10:131:10 | p | $@ | params_flow.rb:130:14:130:19 | call to params : | call to params : | +| params_flow.rb:135:10:135:38 | call to reverse_merge! | params_flow.rb:135:10:135:15 | call to params : | params_flow.rb:135:10:135:38 | call to reverse_merge! | $@ | params_flow.rb:135:10:135:15 | call to params : | call to params : | +| params_flow.rb:136:10:136:38 | call to reverse_merge! | params_flow.rb:136:32:136:37 | call to params : | params_flow.rb:136:10:136:38 | call to reverse_merge! | $@ | params_flow.rb:136:32:136:37 | call to params : | call to params : | +| params_flow.rb:140:10:140:10 | p | params_flow.rb:139:22:139:27 | call to params : | params_flow.rb:140:10:140:10 | p | $@ | params_flow.rb:139:22:139:27 | call to params : | call to params : | +| params_flow.rb:144:10:144:44 | call to with_defaults! | params_flow.rb:144:10:144:15 | call to params : | params_flow.rb:144:10:144:44 | call to with_defaults! | $@ | params_flow.rb:144:10:144:15 | call to params : | call to params : | +| params_flow.rb:145:10:145:38 | call to with_defaults! | params_flow.rb:145:32:145:37 | call to params : | params_flow.rb:145:10:145:38 | call to with_defaults! | $@ | params_flow.rb:145:32:145:37 | call to params : | call to params : | +| params_flow.rb:149:10:149:10 | p | params_flow.rb:148:22:148:27 | call to params : | params_flow.rb:149:10:149:10 | p | $@ | params_flow.rb:148:22:148:27 | call to params : | call to params : | diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql new file mode 100644 index 00000000000..3121b1e71ef --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql @@ -0,0 +1,16 @@ +/** + * @kind path-problem + */ + +import ruby +import TestUtilities.InlineFlowTest +import PathGraph +import codeql.ruby.frameworks.ActionController + +class ParamsTaintFlowConf extends DefaultTaintFlowConf { + override predicate isSource(DataFlow::Node n) { n.asExpr().getExpr() instanceof ParamsCall } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, ParamsTaintFlowConf conf +where conf.hasFlowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/params_flow.rb b/ruby/ql/test/library-tests/frameworks/action_controller/params_flow.rb new file mode 100644 index 00000000000..7b4dc634720 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_controller/params_flow.rb @@ -0,0 +1,151 @@ +class MyController < ActionController::Base + def m1 + sink params[:a] # $hasTaintFlow + end + + def m2 + sink params.as_json # $hasTaintFlow + end + + def m2 + sink params.not_a_method + end + + def m3 + sink params.permit(:some_key) # $hasTaintFlow + end + + def m4 + sink params.require(:some_key) # $hasTaintFlow + end + + def m5 + sink params.required(:some_key) # $hasTaintFlow + end + + def m6 + sink params.deep_dup # $hasTaintFlow + end + + def m7 + sink params.deep_transform_keys(&:upcase) # $hasTaintFlow + end + + def m8 + sink params.deep_transform_keys!(&:upcase) # $hasTaintFlow + end + + def m9 + sink params.delete_if { |v| v.match? regex } # $hasTaintFlow + end + + def m10 + sink params.extract!(:a, :b) # $hasTaintFlow + end + + def m11 + sink params.keep_if { |v| v.match? regex } # $hasTaintFlow + end + + def m12 + sink params.select { |v| v.match? regex } # $hasTaintFlow + end + + def m13 + sink params.select! { |v| v.match? regex } # $hasTaintFlow + end + + def m14 + sink params.reject { |v| v.match? regex } # $hasTaintFlow + end + + def m15 + sink params.reject! { |v| v.match? regex } # $hasTaintFlow + end + + def m16 + sink params.to_h # $hasTaintFlow + end + + def m17 + sink params.to_hash # $hasTaintFlow + end + + def m18 + sink params.to_query # $hasTaintFlow + end + + def m19 + sink params.to_param # $hasTaintFlow + end + + def m20 + sink params.to_unsafe_h # $hasTaintFlow + end + + def m21 + sink params.to_unsafe_hash # $hasTaintFlow + end + + def m22 + sink params.transform_keys(&:upcase) # $hasTaintFlow + end + + def m23 + sink params.transform_keys!(&:upcase) # $hasTaintFlow + end + + def m24 + sink params.transform_values(&:upcase) # $hasTaintFlow + end + + def m25 + sink params.transform_values!(&:upcase) # $hasTaintFlow + end + + def m26 + sink params.values_at(:a, :b) # $hasTaintFlow + end + + def m27 + sink params.merge({a: 1}) # $hasTaintFlow + sink {a: 1}.merge(params) # $hasTaintFlow + end + + def m28 + sink params.reverse_merge({a: 1}) # $hasTaintFlow + sink {a: 1}.reverse_merge(params) # $hasTaintFlow + end + + def m29 + sink params.with_defaults({a: 1, b: 2}) # $hasTaintFlow + sink {a: 1}.with_defaults(params) # $hasTaintFlow + end + + def m30 + sink params.merge!({a: 1}) # $hasTaintFlow + sink {a: 1}.merge!(params) # $hasTaintFlow + + p = {a: 1} + p.merge!(params) + sink p # $hasTaintFlow + end + + def m31 + sink params.reverse_merge!({a: 1}) # $hasTaintFlow + sink {a: 1}.reverse_merge!(params) # $hasTaintFlow + + p = {a: 1} + p.reverse_merge!(params) + sink p # $hasTaintFlow + end + + def m32 + sink params.with_defaults!({a: 1, b: 2}) # $hasTaintFlow + sink {a: 1}.with_defaults!(params) # $hasTaintFlow + + p = {a: 1} + p.with_defaults!(params) + sink p # $hasTaintFlow + end +end diff --git a/ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected b/ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected index 29daf82d53d..f4f5d4f3c62 100644 --- a/ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected +++ b/ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected @@ -10,7 +10,9 @@ edges | UrlRedirect.rb:63:38:63:43 | call to params : | UrlRedirect.rb:63:38:63:49 | ...[...] | | UrlRedirect.rb:68:38:68:43 | call to params : | UrlRedirect.rb:68:38:68:49 | ...[...] | | UrlRedirect.rb:73:25:73:30 | call to params : | UrlRedirect.rb:73:25:73:36 | ...[...] | +| UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:16 | input_params : | | UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : | +| UrlRedirect.rb:89:5:89:16 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : | nodes | UrlRedirect.rb:4:17:4:22 | call to params | semmle.label | call to params | | UrlRedirect.rb:9:17:9:22 | call to params : | semmle.label | call to params : | @@ -33,6 +35,7 @@ nodes | UrlRedirect.rb:73:25:73:30 | call to params : | semmle.label | call to params : | | UrlRedirect.rb:73:25:73:36 | ...[...] | semmle.label | ...[...] | | UrlRedirect.rb:88:21:88:32 | input_params : | semmle.label | input_params : | +| UrlRedirect.rb:89:5:89:16 | input_params : | semmle.label | input_params : | | UrlRedirect.rb:89:5:89:29 | call to permit : | semmle.label | call to permit : | subpaths | UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : | UrlRedirect.rb:24:17:24:37 | call to filter_params | From fa1ae26fab83ba4c789ed85a8dc2d7dd3481f797 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Tue, 27 Sep 2022 10:34:53 +1300 Subject: [PATCH 004/107] Add change note --- .../change-notes/2022-11-27-actioncontroller-parameters.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ruby/ql/lib/change-notes/2022-11-27-actioncontroller-parameters.md diff --git a/ruby/ql/lib/change-notes/2022-11-27-actioncontroller-parameters.md b/ruby/ql/lib/change-notes/2022-11-27-actioncontroller-parameters.md new file mode 100644 index 00000000000..e0c2597ec90 --- /dev/null +++ b/ruby/ql/lib/change-notes/2022-11-27-actioncontroller-parameters.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Taint flow through `ActionController::Parameters` is tracked more accurately. From 5c20039e09a4a7ea2a58915040fa1cdb57be23c4 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Tue, 27 Sep 2022 13:35:17 +1300 Subject: [PATCH 005/107] Ruby: Slightly improve class name --- ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll index 88c8f75bc3b..26fefef6081 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll @@ -427,12 +427,11 @@ private module ParamsSummaries { } /** - * Methods on `ActionController::Parameters` which propagate taint from - * receiver to return value. + * A flow summary for methods on `ActionController::Parameters` which + * propagate taint from receiver to return value. */ - private class TaintReturnFromSelf extends SummarizedCallable { - // TODO: better name? - TaintReturnFromSelf() { this = "ActionController::Parameters#" } + private class MethodsReturningParamsInstanceSummary extends SummarizedCallable { + MethodsReturningParamsInstanceSummary() { this = "ActionController::Parameters#" } override MethodCall getACall() { any(ParamsInstance i).asExpr().getExpr() = result.getReceiver() and From 32baf67b0762cd450b426bd9811b8237d5ba2530 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Tue, 27 Sep 2022 15:21:59 +1300 Subject: [PATCH 006/107] Fix change note month --- ...er-parameters.md => 2022-09-27-actioncontroller-parameters.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ruby/ql/lib/change-notes/{2022-11-27-actioncontroller-parameters.md => 2022-09-27-actioncontroller-parameters.md} (100%) diff --git a/ruby/ql/lib/change-notes/2022-11-27-actioncontroller-parameters.md b/ruby/ql/lib/change-notes/2022-09-27-actioncontroller-parameters.md similarity index 100% rename from ruby/ql/lib/change-notes/2022-11-27-actioncontroller-parameters.md rename to ruby/ql/lib/change-notes/2022-09-27-actioncontroller-parameters.md From 236b628ee207ca64522762f7cc97931c4c187624 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Mon, 3 Oct 2022 14:06:06 +1300 Subject: [PATCH 007/107] Ruby: Constrain parameters flow properly --- .../lib/codeql/ruby/frameworks/ActionController.qll | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll index 26fefef6081..df14e8f23a6 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll @@ -386,12 +386,13 @@ private module ParamsSummaries { ParamsInstance() { this.asExpr().getExpr() instanceof ParamsCall or - exists(DataFlow::CallNode call | call = this | - call.getReceiver() instanceof ParamsInstance and - call.getMethodName() = paramsMethodReturningParamsInstance() - ) + this = + any(DataFlow::CallNode call | + call.getReceiver() instanceof ParamsInstance and + call.getMethodName() = paramsMethodReturningParamsInstance() + ) or - exists(DataFlow::LocalSourceNode prev | prev.flowsTo(this)) + exists(ParamsInstance prev | prev.(DataFlow::LocalSourceNode).flowsTo(this)) } } From eaf6eb009b20fd97bb76c23f96b962ddc337db44 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Mon, 3 Oct 2022 17:17:58 +1300 Subject: [PATCH 008/107] Update tests --- ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected | 3 --- 1 file changed, 3 deletions(-) diff --git a/ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected b/ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected index f4f5d4f3c62..29daf82d53d 100644 --- a/ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected +++ b/ruby/ql/test/query-tests/security/cwe-601/UrlRedirect.expected @@ -10,9 +10,7 @@ edges | UrlRedirect.rb:63:38:63:43 | call to params : | UrlRedirect.rb:63:38:63:49 | ...[...] | | UrlRedirect.rb:68:38:68:43 | call to params : | UrlRedirect.rb:68:38:68:49 | ...[...] | | UrlRedirect.rb:73:25:73:30 | call to params : | UrlRedirect.rb:73:25:73:36 | ...[...] | -| UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:16 | input_params : | | UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : | -| UrlRedirect.rb:89:5:89:16 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : | nodes | UrlRedirect.rb:4:17:4:22 | call to params | semmle.label | call to params | | UrlRedirect.rb:9:17:9:22 | call to params : | semmle.label | call to params : | @@ -35,7 +33,6 @@ nodes | UrlRedirect.rb:73:25:73:30 | call to params : | semmle.label | call to params : | | UrlRedirect.rb:73:25:73:36 | ...[...] | semmle.label | ...[...] | | UrlRedirect.rb:88:21:88:32 | input_params : | semmle.label | input_params : | -| UrlRedirect.rb:89:5:89:16 | input_params : | semmle.label | input_params : | | UrlRedirect.rb:89:5:89:29 | call to permit : | semmle.label | call to permit : | subpaths | UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : | UrlRedirect.rb:24:17:24:37 | call to filter_params | From b01a0ae6969fafe4c0165909401d26ea80cf67b8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 3 Oct 2022 20:35:49 +0200 Subject: [PATCH 009/107] Python: Adjust `.expected` after flask source change It's really hard to audit that this is all good.. I tried my best with `icdiff` though -- and there is a problem with ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql that needs to be fixed in the next commit --- .../Security/CWE-079/ReflectedXSS.expected | 62 +++++++++--- .../Security/CWE-113/HeaderInjection.expected | 17 +++- .../Security/CWE-1236/CsvInjection.expected | 13 ++- ...ientSuppliedIpUsedInSecurityCheck.expected | 8 -- .../CWE-522/LDAPInsecureAuth.expected | 8 +- .../Security/CWE-614/CookieInjection.expected | 33 ++++--- .../Security/CWE-943/NoSQLInjection.expected | 56 ++++++++--- .../UntrustedDataToExternalAPI.expected | 8 +- .../PathInjection.expected | 60 ++++++++---- .../CommandInjection.expected | 24 +++-- .../CommandInjection.expected | 39 +++++--- .../ReflectedXss.expected | 14 ++- .../LdapInjection.expected | 60 +++++++++--- .../CodeInjection.expected | 15 ++- .../LogInjection.expected | 17 +++- .../UnsafeDeserialization.expected | 14 ++- .../CWE-601-UrlRedirect/UrlRedirect.expected | 29 ++++-- .../Security/CWE-611-Xxe/Xxe.expected | 11 ++- .../XpathInjection.expected | 20 +++- .../PolynomialReDoS.expected | 10 +- .../RegexInjection.expected | 14 ++- .../Security/CWE-776-XmlBomb/XmlBomb.expected | 8 +- .../FullServerSideRequestForgery.expected | 95 +++++++++++++++---- .../PartialServerSideRequestForgery.expected | 85 +++++++++++++---- 24 files changed, 533 insertions(+), 187 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected b/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected index f787dfa43fc..77dafce4a10 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected @@ -1,4 +1,9 @@ edges +| flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | flask_mail.py:13:22:13:28 | ControlFlowNode for request | +| flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | flask_mail.py:18:14:18:20 | ControlFlowNode for request | +| flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | flask_mail.py:31:24:31:30 | ControlFlowNode for request | +| flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:1:19:1:25 | GSSA Variable request | +| flask_mail.py:1:19:1:25 | GSSA Variable request | flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | | flask_mail.py:13:22:13:28 | ControlFlowNode for request | flask_mail.py:13:22:13:33 | ControlFlowNode for Attribute | | flask_mail.py:13:22:13:28 | ControlFlowNode for request | flask_mail.py:18:14:18:25 | ControlFlowNode for Attribute | | flask_mail.py:13:22:13:33 | ControlFlowNode for Attribute | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | @@ -6,6 +11,11 @@ edges | flask_mail.py:18:14:18:25 | ControlFlowNode for Attribute | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | | flask_mail.py:31:24:31:30 | ControlFlowNode for request | flask_mail.py:31:24:31:35 | ControlFlowNode for Attribute | | flask_mail.py:31:24:31:35 | ControlFlowNode for Attribute | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | +| sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | +| sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | +| sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | +| sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:1:19:1:25 | GSSA Variable request | +| sendgrid_mail.py:1:19:1:25 | GSSA Variable request | sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | sendgrid_mail.py:14:22:14:33 | ControlFlowNode for Attribute | | sendgrid_mail.py:14:22:14:33 | ControlFlowNode for Attribute | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | sendgrid_mail.py:26:34:26:45 | ControlFlowNode for Attribute | @@ -13,6 +23,11 @@ edges | sendgrid_mail.py:26:34:26:61 | ControlFlowNode for Subscript | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | sendgrid_mail.py:37:41:37:52 | ControlFlowNode for Attribute | | sendgrid_mail.py:37:41:37:52 | ControlFlowNode for Attribute | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | +| sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | +| sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | +| sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | +| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | GSSA Variable request | +| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | GSSA Variable request | sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:62 | ControlFlowNode for Attribute | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:61 | ControlFlowNode for Attribute | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:61 | ControlFlowNode for Attribute | @@ -25,9 +40,15 @@ edges | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:61 | ControlFlowNode for Attribute | | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:61 | ControlFlowNode for Attribute | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:78 | ControlFlowNode for Subscript | | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:78 | ControlFlowNode for Subscript | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | +| smtplib_bad_subparts.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_subparts.request | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | +| smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_subparts.py:2:26:2:32 | GSSA Variable request | +| smtplib_bad_subparts.py:2:26:2:32 | GSSA Variable request | smtplib_bad_subparts.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_subparts.request | | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | smtplib_bad_subparts.py:17:12:17:23 | ControlFlowNode for Attribute | | smtplib_bad_subparts.py:17:12:17:23 | ControlFlowNode for Attribute | smtplib_bad_subparts.py:17:12:17:33 | ControlFlowNode for Subscript | | smtplib_bad_subparts.py:17:12:17:33 | ControlFlowNode for Subscript | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | +| smtplib_bad_via_attach.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_via_attach.request | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | +| smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_via_attach.py:2:26:2:32 | GSSA Variable request | +| smtplib_bad_via_attach.py:2:26:2:32 | GSSA Variable request | smtplib_bad_via_attach.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_via_attach.request | | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | smtplib_bad_via_attach.py:20:12:20:23 | ControlFlowNode for Attribute | | smtplib_bad_via_attach.py:20:12:20:23 | ControlFlowNode for Attribute | smtplib_bad_via_attach.py:20:12:20:31 | ControlFlowNode for Subscript | | smtplib_bad_via_attach.py:20:12:20:31 | ControlFlowNode for Subscript | smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | @@ -35,6 +56,9 @@ nodes | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | semmle.label | ModuleVariableNode for flask_mail.request | +| flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_mail.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_mail.py:13:22:13:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mail.py:13:22:13:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -44,6 +68,9 @@ nodes | flask_mail.py:31:24:31:30 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mail.py:31:24:31:35 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | semmle.label | ModuleVariableNode for sendgrid_mail.request | +| sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| sendgrid_mail.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | sendgrid_mail.py:14:22:14:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -54,6 +81,9 @@ nodes | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | sendgrid_mail.py:37:41:37:52 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | semmle.label | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | +| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | GSSA Variable request | semmle.label | GSSA Variable request | | sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:62 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -66,10 +96,16 @@ nodes | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:61 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:78 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| smtplib_bad_subparts.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_subparts.request | semmle.label | ModuleVariableNode for smtplib_bad_subparts.request | +| smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| smtplib_bad_subparts.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | smtplib_bad_subparts.py:17:12:17:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | smtplib_bad_subparts.py:17:12:17:33 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | semmle.label | ControlFlowNode for html | +| smtplib_bad_via_attach.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_via_attach.request | semmle.label | ModuleVariableNode for smtplib_bad_via_attach.request | +| smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| smtplib_bad_via_attach.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | smtplib_bad_via_attach.py:20:12:20:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | smtplib_bad_via_attach.py:20:12:20:31 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -79,18 +115,14 @@ subpaths | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | a user-provided value | | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | a user-provided value | | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | a user-provided value | -| flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | flask_mail.py:13:22:13:28 | ControlFlowNode for request | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:13:22:13:28 | ControlFlowNode for request | a user-provided value | -| flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | flask_mail.py:13:22:13:28 | ControlFlowNode for request | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:13:22:13:28 | ControlFlowNode for request | a user-provided value | -| flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | flask_mail.py:18:14:18:20 | ControlFlowNode for request | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:18:14:18:20 | ControlFlowNode for request | a user-provided value | -| flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | flask_mail.py:31:24:31:30 | ControlFlowNode for request | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:31:24:31:30 | ControlFlowNode for request | a user-provided value | -| sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | a user-provided value | -| sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | a user-provided value | -| sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | a user-provided value | -| smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | a user-provided value | -| smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | a user-provided value | +| flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value | +| smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | 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 100beb0f4b3..588c9ea3bb5 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,6 +1,12 @@ 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:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:9:18:9:24 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:19:18:19:24 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:27:18:27:24 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:35:18:35:24 | ControlFlowNode for request | +| flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_bad.py:1:29:1:35 | GSSA Variable request | +| flask_bad.py:1:29:1:35 | GSSA Variable request | flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | | 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 | @@ -18,6 +24,9 @@ nodes | 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:0:0:0:0 | ModuleVariableNode for flask_bad.request | semmle.label | ModuleVariableNode for flask_bad.request | +| flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_bad.py:1:29:1:35 | GSSA Variable request | semmle.label | GSSA Variable request | | 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 | @@ -38,7 +47,7 @@ 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: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:12:31:12:40 | ControlFlowNode for rfs_header | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | 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:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value | +| flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | 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:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value | +| flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | 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:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value | +| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | 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:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected index 2b6fb18f47b..5b6b8a4bc24 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected @@ -1,10 +1,17 @@ edges +| csv_bad.py:0:0:0:0 | ModuleVariableNode for csv_bad.request | csv_bad.py:16:16:16:22 | ControlFlowNode for request | +| csv_bad.py:0:0:0:0 | ModuleVariableNode for csv_bad.request | csv_bad.py:24:16:24:22 | ControlFlowNode for request | +| csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:9:19:9:25 | GSSA Variable request | +| csv_bad.py:9:19:9:25 | GSSA Variable request | csv_bad.py:0:0:0:0 | ModuleVariableNode for csv_bad.request | | csv_bad.py:16:16:16:22 | ControlFlowNode for request | csv_bad.py:16:16:16:27 | ControlFlowNode for Attribute | | csv_bad.py:16:16:16:27 | ControlFlowNode for Attribute | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | | csv_bad.py:16:16:16:27 | ControlFlowNode for Attribute | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | | csv_bad.py:24:16:24:22 | ControlFlowNode for request | csv_bad.py:24:16:24:27 | ControlFlowNode for Attribute | | csv_bad.py:24:16:24:27 | ControlFlowNode for Attribute | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | nodes +| csv_bad.py:0:0:0:0 | ModuleVariableNode for csv_bad.request | semmle.label | ModuleVariableNode for csv_bad.request | +| csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| csv_bad.py:9:19:9:25 | GSSA Variable request | semmle.label | GSSA Variable request | | csv_bad.py:16:16:16:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | csv_bad.py:16:16:16:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | semmle.label | ControlFlowNode for csv_data | @@ -14,6 +21,6 @@ nodes | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | semmle.label | ControlFlowNode for csv_data | subpaths #select -| csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | csv_bad.py:16:16:16:22 | ControlFlowNode for request | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:16:16:16:22 | ControlFlowNode for request | this user input | -| csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | csv_bad.py:16:16:16:22 | ControlFlowNode for request | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:16:16:16:22 | ControlFlowNode for request | this user input | -| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | csv_bad.py:24:16:24:22 | ControlFlowNode for request | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:24:16:24:22 | ControlFlowNode for request | this user input | +| csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input | +| csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input | +| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input | 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 a432cf5053f..fd5bbf319dc 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,16 +1,8 @@ edges -| 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 -| 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 | 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 | | 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-522/LDAPInsecureAuth.expected b/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected index 24784f039e7..425b00a85c7 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected @@ -1,4 +1,7 @@ edges +| ldap3_remote.py:0:0:0:0 | ModuleVariableNode for ldap3_remote.request | ldap3_remote.py:138:21:138:27 | ControlFlowNode for request | +| ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | ldap3_remote.py:2:19:2:25 | GSSA Variable request | +| ldap3_remote.py:2:19:2:25 | GSSA Variable request | ldap3_remote.py:0:0:0:0 | ModuleVariableNode for ldap3_remote.request | | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | | ldap3_remote.py:126:12:126:31 | ControlFlowNode for BinaryExpr | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | @@ -8,6 +11,9 @@ edges nodes | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| ldap3_remote.py:0:0:0:0 | ModuleVariableNode for ldap3_remote.request | semmle.label | ModuleVariableNode for ldap3_remote.request | +| ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap3_remote.py:2:19:2:25 | GSSA Variable request | semmle.label | GSSA Variable request | | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | semmle.label | ControlFlowNode for host | | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -25,4 +31,4 @@ subpaths | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | This LDAP host | | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | This LDAP host | | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | ldap3_remote.py:126:12:126:31 | ControlFlowNode for BinaryExpr | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | This LDAP host | -| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | ldap3_remote.py:138:21:138:27 | ControlFlowNode for request | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | This LDAP host | +| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | This LDAP host | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected index d246f8b14d6..5cc54fbdad2 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected @@ -1,6 +1,12 @@ edges | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:24:21:24:27 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:24:49:24:55 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:32:37:32:43 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:32:60:32:66 | ControlFlowNode for request | +| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:1:26:1:32 | GSSA Variable request | +| flask_bad.py:1:26:1:32 | GSSA Variable request | flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:32 | ControlFlowNode for Attribute | | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:60 | ControlFlowNode for Attribute | | flask_bad.py:24:21:24:32 | ControlFlowNode for Attribute | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | @@ -19,6 +25,9 @@ nodes | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring | | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | semmle.label | ModuleVariableNode for flask_bad.request | +| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_bad.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_bad.py:24:21:24:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -46,18 +55,12 @@ subpaths | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input | | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input | | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input | -| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:49:24:55 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:24:49:24:55 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:49:24:55 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:24:49:24:55 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:49:24:55 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:24:49:24:55 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:37:32:43 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:32:37:32:43 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:37:32:43 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:32:37:32:43 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:37:32:43 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:32:37:32:43 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:60:32:66 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:32:60:32:66 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:60:32:66 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:32:60:32:66 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:60:32:66 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:32:60:32:66 | ControlFlowNode for request | user-supplied input | +| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index 2922cc9f97e..54948a2d17f 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -1,4 +1,8 @@ edges +| flask_mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for flask_mongoengine_bad.request | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | +| flask_mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for flask_mongoengine_bad.request | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | +| flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | +| flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | flask_mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for flask_mongoengine_bad.request | | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | | flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | | flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:20:30:20:42 | ControlFlowNode for unsafe_search | @@ -9,11 +13,22 @@ edges | flask_mongoengine_bad.py:26:21:26:42 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:27:30:27:42 | ControlFlowNode for unsafe_search | | flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | | flask_mongoengine_bad.py:27:30:27:42 | ControlFlowNode for unsafe_search | flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | +| flask_pymongo_bad.py:0:0:0:0 | ModuleVariableNode for flask_pymongo_bad.request | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | +| flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_pymongo_bad.py:1:26:1:32 | GSSA Variable request | +| flask_pymongo_bad.py:1:26:1:32 | GSSA Variable request | flask_pymongo_bad.py:0:0:0:0 | ModuleVariableNode for flask_pymongo_bad.request | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | | flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | +| mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:1:26:1:32 | GSSA Variable request | +| mongoengine_bad.py:1:26:1:32 | GSSA Variable request | mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | | mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | @@ -44,6 +59,11 @@ edges | mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | mongoengine_bad.py:58:30:58:42 | ControlFlowNode for unsafe_search | | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | | mongoengine_bad.py:58:30:58:42 | ControlFlowNode for unsafe_search | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | +| pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | +| pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | +| pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | +| pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:1:26:1:32 | GSSA Variable request | +| pymongo_test.py:1:26:1:32 | GSSA Variable request | pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | pymongo_test.py:12:21:12:32 | ControlFlowNode for Attribute | | pymongo_test.py:12:21:12:32 | ControlFlowNode for Attribute | pymongo_test.py:12:21:12:42 | ControlFlowNode for Subscript | | pymongo_test.py:12:21:12:42 | ControlFlowNode for Subscript | pymongo_test.py:13:30:13:42 | ControlFlowNode for unsafe_search | @@ -58,6 +78,9 @@ edges | pymongo_test.py:39:27:39:38 | ControlFlowNode for Attribute | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | pymongo_test.py:39:16:39:51 | ControlFlowNode for Attribute() | nodes +| flask_mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for flask_mongoengine_bad.request | semmle.label | ModuleVariableNode for flask_mongoengine_bad.request | +| flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -70,12 +93,18 @@ nodes | flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_mongoengine_bad.py:27:30:27:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_pymongo_bad.py:0:0:0:0 | ModuleVariableNode for flask_pymongo_bad.request | semmle.label | ModuleVariableNode for flask_pymongo_bad.request | +| flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_pymongo_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | semmle.label | ModuleVariableNode for mongoengine_bad.request | +| mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| mongoengine_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -112,6 +141,9 @@ nodes | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_bad.py:58:30:58:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | semmle.label | ModuleVariableNode for pymongo_test.request | +| pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| pymongo_test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_test.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_test.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -130,15 +162,15 @@ nodes | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | subpaths #select -| flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | user-provided value | -| flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | -| flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | This | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | This | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | This | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | This | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | This | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | This | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected index fcb2d3103eb..c64a6943813 100644 --- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected @@ -1,10 +1,16 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:13:16:13:22 | ControlFlowNode for request | +| test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:5:26:5:32 | GSSA Variable request | +| test.py:5:26:5:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:13:16:13:22 | ControlFlowNode for request | test.py:13:16:13:27 | ControlFlowNode for Attribute | | test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:36:15:39 | ControlFlowNode for data | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:13:16:13:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:13:16:13:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:15:36:15:39 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | subpaths #select -| test.py:15:36:15:39 | ControlFlowNode for data | test.py:13:16:13:22 | ControlFlowNode for request | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [param 1] with untrusted data from $@. | test.py:13:16:13:22 | ControlFlowNode for request | ControlFlowNode for request | +| test.py:15:36:15:39 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [param 1] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected index 49c173f6fe9..64fe441dc64 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected @@ -1,6 +1,22 @@ edges +| flask_path_injection.py:0:0:0:0 | ModuleVariableNode for flask_path_injection.request | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | +| flask_path_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_path_injection.py:1:26:1:32 | GSSA Variable request | +| flask_path_injection.py:1:26:1:32 | GSSA Variable request | flask_path_injection.py:0:0:0:0 | ModuleVariableNode for flask_path_injection.request | | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:19:15:19:26 | ControlFlowNode for Attribute | | flask_path_injection.py:19:15:19:26 | ControlFlowNode for Attribute | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:12:16:12:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:19:16:19:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:27:16:27:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:46:16:46:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:63:16:63:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:84:16:84:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:107:16:107:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:118:16:118:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:129:16:129:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:138:16:138:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:149:16:149:22 | ControlFlowNode for request | +| path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:3:26:3:32 | GSSA Variable request | +| path_injection.py:3:26:3:32 | GSSA Variable request | path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | | path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | @@ -33,6 +49,9 @@ edges | path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | path_injection.py:142:14:142:17 | ControlFlowNode for path | | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | path_injection.py:152:18:152:21 | ControlFlowNode for path | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:9:12:9:18 | ControlFlowNode for request | +| test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:3:26:3:32 | GSSA Variable request | +| test.py:3:26:3:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:9:12:9:18 | ControlFlowNode for request | test.py:9:12:9:23 | ControlFlowNode for Attribute | | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | ControlFlowNode for Attribute() | | test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:18:9:18:16 | ControlFlowNode for source() | @@ -52,9 +71,15 @@ edges | test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | | test.py:48:23:48:23 | ControlFlowNode for x | test.py:48:13:48:24 | ControlFlowNode for normalize() | nodes +| flask_path_injection.py:0:0:0:0 | ModuleVariableNode for flask_path_injection.request | semmle.label | ModuleVariableNode for flask_path_injection.request | +| flask_path_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_path_injection.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_path_injection.py:19:15:19:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | semmle.label | ControlFlowNode for dirname | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | semmle.label | ModuleVariableNode for path_injection.request | +| path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| path_injection.py:3:26:3:32 | GSSA Variable request | semmle.label | GSSA Variable request | | path_injection.py:12:16:12:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | @@ -100,6 +125,9 @@ nodes | path_injection.py:149:16:149:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | path_injection.py:152:18:152:21 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:3:26:3:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:9:12:9:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | @@ -122,21 +150,21 @@ subpaths | test.py:25:19:25:19 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:25:9:25:20 | ControlFlowNode for normalize() | | test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:48:13:48:24 | ControlFlowNode for normalize() | #select -| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | This path depends on $@. | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | a user-provided value | -| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:12:16:12:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:19:16:19:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:27:16:27:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:46:16:46:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:63:16:63:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | This path depends on $@. | path_injection.py:84:16:84:22 | ControlFlowNode for request | a user-provided value | +| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | This path depends on $@. | flask_path_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | | path_injection.py:94:14:94:17 | ControlFlowNode for path | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:94:14:94:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | a user-provided value | | path_injection.py:102:14:102:17 | ControlFlowNode for path | path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:102:14:102:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:98:20:98:22 | ControlFlowNode for foo | a user-provided value | -| path_injection.py:113:14:113:17 | ControlFlowNode for path | path_injection.py:107:16:107:22 | ControlFlowNode for request | path_injection.py:113:14:113:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:107:16:107:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:124:14:124:17 | ControlFlowNode for path | path_injection.py:118:16:118:22 | ControlFlowNode for request | path_injection.py:124:14:124:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:118:16:118:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:129:16:129:22 | ControlFlowNode for request | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | This path depends on $@. | path_injection.py:129:16:129:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:142:14:142:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:138:16:138:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:152:18:152:21 | ControlFlowNode for path | This path depends on $@. | path_injection.py:149:16:149:22 | ControlFlowNode for request | a user-provided value | -| test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:49:14:49:14 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | +| path_injection.py:113:14:113:17 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:113:14:113:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:124:14:124:17 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:124:14:124:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:142:14:142:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:152:18:152:21 | ControlFlowNode for path | This path depends on $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:19:10:19:10 | ControlFlowNode for x | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:26:10:26:10 | ControlFlowNode for y | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:33:14:33:14 | ControlFlowNode for x | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:49:14:49:14 | ControlFlowNode for y | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected index 8d26b3f6d5c..c86a2a28688 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected @@ -1,4 +1,7 @@ edges +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:18:13:18:19 | ControlFlowNode for request | +| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:5:26:5:32 | GSSA Variable request | +| command_injection.py:5:26:5:32 | GSSA Variable request | command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | @@ -10,6 +13,9 @@ edges | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | nodes +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | semmle.label | ModuleVariableNode for command_injection.request | +| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| command_injection.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request | | command_injection.py:18:13:18:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -23,12 +29,12 @@ nodes | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | +| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected index cce39a976db..71b8d19b2cd 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected @@ -1,4 +1,14 @@ edges +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:11:13:11:19 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:18:13:18:19 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:25:11:25:17 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:31:13:31:19 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:38:15:38:21 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:54:15:54:21 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:71:12:71:18 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:78:12:78:18 | ControlFlowNode for request | +| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:5:26:5:32 | GSSA Variable request | +| command_injection.py:5:26:5:32 | GSSA Variable request | command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | @@ -21,6 +31,9 @@ edges | command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | | command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | nodes +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | semmle.label | ModuleVariableNode for command_injection.request | +| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| command_injection.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request | | command_injection.py:11:13:11:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -52,16 +65,16 @@ nodes | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:11:13:11:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:25:11:25:17 | ControlFlowNode for request | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | This command line depends on $@. | command_injection.py:25:11:25:17 | ControlFlowNode for request | a user-provided value | -| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:31:13:31:19 | ControlFlowNode for request | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:31:13:31:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:41:15:41:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:42:15:42:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:55:15:55:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:56:14:56:20 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:71:12:71:18 | ControlFlowNode for request | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:71:12:71:18 | ControlFlowNode for request | a user-provided value | -| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:78:12:78:18 | ControlFlowNode for request | a user-provided value | +| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:41:15:41:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:42:15:42:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:55:15:55:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:56:14:56:20 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | +| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected index 39c2bb3778f..5dc0fc3e5d7 100644 --- a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected +++ b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected @@ -1,4 +1,9 @@ edges +| reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | +| reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | +| reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | +| reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:2:26:2:32 | GSSA Variable request | +| reflected_xss.py:2:26:2:32 | GSSA Variable request | reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | reflected_xss.py:21:23:21:34 | ControlFlowNode for Attribute | @@ -6,6 +11,9 @@ edges | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | | reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | nodes +| reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | semmle.label | ModuleVariableNode for reflected_xss.request | +| reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| reflected_xss.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -17,6 +25,6 @@ nodes | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | subpaths #select -| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to $@. | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | a user-provided value | -| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | a user-provided value | -| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | a user-provided value | +| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected index 7dcddaaae83..53fd7478f44 100644 --- a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected @@ -1,4 +1,14 @@ edges +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | +| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:1:19:1:25 | GSSA Variable request | +| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:1:19:1:25 | GSSA Variable request | +| ldap3_bad.py:1:19:1:25 | GSSA Variable request | ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | +| ldap3_bad.py:1:19:1:25 | GSSA Variable request | ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:13:17:13:28 | ControlFlowNode for Attribute | | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:14:21:14:32 | ControlFlowNode for Attribute | | ldap3_bad.py:13:17:13:28 | ControlFlowNode for Attribute | ldap3_bad.py:13:17:13:34 | ControlFlowNode for Subscript | @@ -13,6 +23,19 @@ edges | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | ldap3_bad.py:31:21:31:32 | ControlFlowNode for Attribute | | ldap3_bad.py:31:21:31:32 | ControlFlowNode for Attribute | ldap3_bad.py:31:21:31:44 | ControlFlowNode for Subscript | | ldap3_bad.py:31:21:31:44 | ControlFlowNode for Subscript | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | +| ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:1:19:1:25 | GSSA Variable request | +| ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:1:19:1:25 | GSSA Variable request | +| ldap_bad.py:1:19:1:25 | GSSA Variable request | ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | +| ldap_bad.py:1:19:1:25 | GSSA Variable request | ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:13:17:13:28 | ControlFlowNode for Attribute | | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:14:21:14:32 | ControlFlowNode for Attribute | | ldap_bad.py:13:17:13:28 | ControlFlowNode for Attribute | ldap_bad.py:13:17:13:34 | ControlFlowNode for Subscript | @@ -35,6 +58,12 @@ edges | ldap_bad.py:48:21:48:32 | ControlFlowNode for Attribute | ldap_bad.py:48:21:48:44 | ControlFlowNode for Subscript | | ldap_bad.py:48:21:48:44 | ControlFlowNode for Subscript | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | nodes +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | semmle.label | ModuleVariableNode for ldap3_bad.request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | semmle.label | ModuleVariableNode for ldap3_bad.request | +| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap3_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| ldap3_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | ldap3_bad.py:13:17:13:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -53,6 +82,12 @@ nodes | ldap3_bad.py:31:21:31:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | semmle.label | ControlFlowNode for dn | | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | semmle.label | ControlFlowNode for search_filter | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | semmle.label | ModuleVariableNode for ldap_bad.request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | semmle.label | ModuleVariableNode for ldap_bad.request | +| ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| ldap_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | ldap_bad.py:13:17:13:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -82,18 +117,13 @@ nodes | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | semmle.label | ControlFlowNode for search_filter | subpaths #select -| ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | $@ depends on $@. | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | $@ depends on $@. | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | a user-provided value | +| ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | $@ depends on $@. | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | $@ depends on $@. | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected index 97f5bc54118..a1911a6331e 100644 --- a/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected @@ -1,4 +1,8 @@ edges +| code_injection.py:0:0:0:0 | ModuleVariableNode for code_injection.request | code_injection.py:6:12:6:18 | ControlFlowNode for request | +| code_injection.py:0:0:0:0 | ModuleVariableNode for code_injection.request | code_injection.py:18:16:18:22 | ControlFlowNode for request | +| code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:1:26:1:32 | GSSA Variable request | +| code_injection.py:1:26:1:32 | GSSA Variable request | code_injection.py:0:0:0:0 | ModuleVariableNode for code_injection.request | | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:7:10:7:13 | ControlFlowNode for code | | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:8:10:8:13 | ControlFlowNode for code | @@ -6,6 +10,9 @@ edges | code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:18:16:18:27 | ControlFlowNode for Attribute | | code_injection.py:18:16:18:27 | ControlFlowNode for Attribute | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | nodes +| code_injection.py:0:0:0:0 | ModuleVariableNode for code_injection.request | semmle.label | ModuleVariableNode for code_injection.request | +| code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| code_injection.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | code_injection.py:6:12:6:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | code_injection.py:7:10:7:13 | ControlFlowNode for code | semmle.label | ControlFlowNode for code | @@ -16,7 +23,7 @@ nodes | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | semmle.label | ControlFlowNode for obj_name | subpaths #select -| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:7:10:7:13 | ControlFlowNode for code | This code execution depends on $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | a user-provided value | -| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:8:10:8:13 | ControlFlowNode for code | This code execution depends on $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | a user-provided value | -| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | This code execution depends on $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | a user-provided value | -| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | This code execution depends on $@. | code_injection.py:18:16:18:22 | ControlFlowNode for request | a user-provided value | +| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:7:10:7:13 | ControlFlowNode for code | This code execution depends on $@. | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:8:10:8:13 | ControlFlowNode for code | This code execution depends on $@. | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | This code execution depends on $@. | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | This code execution depends on $@. | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected b/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected index 9641f49e3e2..d4138316fc2 100644 --- a/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected @@ -1,4 +1,10 @@ edges +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | +| LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:7:19:7:25 | GSSA Variable request | +| LogInjectionBad.py:7:19:7:25 | GSSA Variable request | LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | | 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 | @@ -8,6 +14,9 @@ edges | 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:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | semmle.label | ModuleVariableNode for LogInjectionBad.request | +| LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| LogInjectionBad.py:7:19:7:25 | GSSA Variable request | semmle.label | GSSA Variable request | | 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 | @@ -22,7 +31,7 @@ nodes | 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 | This log entry depends on $@. | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | a 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 | This log entry depends on $@. | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | a 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 | This log entry depends on $@. | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | a 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 | This log entry depends on $@. | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | a user-provided value | +| LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | This log entry depends on $@. | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | a user-provided value | +| LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | This log entry depends on $@. | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | a user-provided value | +| LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | This log entry depends on $@. | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | a user-provided value | +| LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | This log entry depends on $@. | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected index 9cab4ce7d16..dc536fa9e7e 100644 --- a/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected +++ b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected @@ -1,10 +1,16 @@ edges +| unsafe_deserialization.py:0:0:0:0 | ModuleVariableNode for unsafe_deserialization.request | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | +| unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:8:26:8:32 | GSSA Variable request | +| unsafe_deserialization.py:8:26:8:32 | GSSA Variable request | unsafe_deserialization.py:0:0:0:0 | ModuleVariableNode for unsafe_deserialization.request | | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | nodes +| unsafe_deserialization.py:0:0:0:0 | ModuleVariableNode for unsafe_deserialization.request | semmle.label | ModuleVariableNode for unsafe_deserialization.request | +| unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| unsafe_deserialization.py:8:26:8:32 | GSSA Variable request | semmle.label | GSSA Variable request | | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload | @@ -13,7 +19,7 @@ nodes | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload | subpaths #select -| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | a user-provided value | -| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | a user-provided value | -| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | a user-provided value | -| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | a user-provided value | +| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | a user-provided value | +| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | a user-provided value | +| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | a user-provided value | +| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected index 750e61d048d..19f96791e87 100644 --- a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected +++ b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected @@ -1,4 +1,14 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:7:14:7:20 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:30:17:30:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:37:17:37:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:44:17:44:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:60:17:60:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:67:17:67:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:74:17:74:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:81:17:81:23 | ControlFlowNode for request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:1:26:1:32 | GSSA Variable request | +| test.py:1:26:1:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:7:14:7:20 | ControlFlowNode for request | test.py:7:14:7:25 | ControlFlowNode for Attribute | | test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:8:21:8:26 | ControlFlowNode for target | | test.py:30:17:30:23 | ControlFlowNode for request | test.py:30:17:30:28 | ControlFlowNode for Attribute | @@ -16,6 +26,9 @@ edges | test.py:81:17:81:23 | ControlFlowNode for request | test.py:81:17:81:28 | ControlFlowNode for Attribute | | test.py:81:17:81:28 | ControlFlowNode for Attribute | test.py:83:21:83:26 | ControlFlowNode for unsafe | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:7:14:7:20 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:7:14:7:25 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:8:21:8:26 | ControlFlowNode for target | semmle.label | ControlFlowNode for target | @@ -42,11 +55,11 @@ nodes | test.py:83:21:83:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | subpaths #select -| test.py:8:21:8:26 | ControlFlowNode for target | test.py:7:14:7:20 | ControlFlowNode for request | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection depends on $@. | test.py:7:14:7:20 | ControlFlowNode for request | a user-provided value | -| test.py:32:21:32:24 | ControlFlowNode for safe | test.py:30:17:30:23 | ControlFlowNode for request | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| test.py:39:21:39:24 | ControlFlowNode for safe | test.py:37:17:37:23 | ControlFlowNode for request | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:37:17:37:23 | ControlFlowNode for request | a user-provided value | -| test.py:46:21:46:24 | ControlFlowNode for safe | test.py:44:17:44:23 | ControlFlowNode for request | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:44:17:44:23 | ControlFlowNode for request | a user-provided value | -| test.py:62:21:62:26 | ControlFlowNode for unsafe | test.py:60:17:60:23 | ControlFlowNode for request | test.py:62:21:62:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:60:17:60:23 | ControlFlowNode for request | a user-provided value | -| test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:67:17:67:23 | ControlFlowNode for request | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:67:17:67:23 | ControlFlowNode for request | a user-provided value | -| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:74:17:74:23 | ControlFlowNode for request | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:74:17:74:23 | ControlFlowNode for request | a user-provided value | -| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:81:17:81:23 | ControlFlowNode for request | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:81:17:81:23 | ControlFlowNode for request | a user-provided value | +| test.py:8:21:8:26 | ControlFlowNode for target | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection depends on $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:32:21:32:24 | ControlFlowNode for safe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:39:21:39:24 | ControlFlowNode for safe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:46:21:46:24 | ControlFlowNode for safe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:62:21:62:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:62:21:62:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected b/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected index 402ee97db09..3421155d992 100644 --- a/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected +++ b/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected @@ -1,4 +1,8 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:8:19:8:25 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:19:19:19:25 | ControlFlowNode for request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:1:26:1:32 | GSSA Variable request | +| test.py:1:26:1:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:8:19:8:25 | ControlFlowNode for request | test.py:8:19:8:30 | ControlFlowNode for Attribute | | test.py:8:19:8:30 | ControlFlowNode for Attribute | test.py:8:19:8:45 | ControlFlowNode for Subscript | | test.py:8:19:8:45 | ControlFlowNode for Subscript | test.py:9:34:9:44 | ControlFlowNode for xml_content | @@ -6,6 +10,9 @@ edges | test.py:19:19:19:30 | ControlFlowNode for Attribute | test.py:19:19:19:45 | ControlFlowNode for Subscript | | test.py:19:19:19:45 | ControlFlowNode for Subscript | test.py:30:34:30:44 | ControlFlowNode for xml_content | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:8:19:8:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:8:19:8:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:8:19:8:45 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -16,5 +23,5 @@ nodes | test.py:30:34:30:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | subpaths #select -| test.py:9:34:9:44 | ControlFlowNode for xml_content | test.py:8:19:8:25 | ControlFlowNode for request | test.py:9:34:9:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against external entity expansion. | test.py:8:19:8:25 | ControlFlowNode for request | a user-provided value | -| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against external entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | a user-provided value | +| test.py:9:34:9:44 | ControlFlowNode for xml_content | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:9:34:9:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against external entity expansion. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against external entity expansion. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected b/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected index d0068a4b872..a33e851828d 100644 --- a/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected @@ -2,6 +2,13 @@ edges | xpathBad.py:9:7:9:13 | ControlFlowNode for request | xpathBad.py:10:13:10:23 | ControlFlowNode for Attribute | | xpathBad.py:10:13:10:23 | ControlFlowNode for Attribute | xpathBad.py:10:13:10:32 | ControlFlowNode for Subscript | | xpathBad.py:10:13:10:32 | ControlFlowNode for Subscript | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | +| xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:2:26:2:32 | GSSA Variable request | +| xpathFlow.py:2:26:2:32 | GSSA Variable request | xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | xpathFlow.py:11:18:11:29 | ControlFlowNode for Attribute | | xpathFlow.py:11:18:11:29 | ControlFlowNode for Attribute | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | xpathFlow.py:20:18:20:29 | ControlFlowNode for Attribute | @@ -17,6 +24,9 @@ nodes | xpathBad.py:10:13:10:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | xpathBad.py:10:13:10:32 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | semmle.label | ModuleVariableNode for xpathFlow.request | +| xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| xpathFlow.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | xpathFlow.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | semmle.label | ControlFlowNode for xpathQuery | @@ -35,8 +45,8 @@ nodes subpaths #select | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | xpathBad.py:9:7:9:13 | ControlFlowNode for request | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | XPath expression depends on $@. | xpathBad.py:9:7:9:13 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | a user-provided value | +| xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected index 7f5cf5926c0..4646f9c03e9 100644 --- a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected +++ b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected @@ -1,13 +1,19 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:7:12:7:18 | ControlFlowNode for request | +| test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:2:26:2:32 | GSSA Variable request | +| test.py:2:26:2:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:7:12:7:18 | ControlFlowNode for request | test.py:7:12:7:23 | ControlFlowNode for Attribute | | test.py:7:12:7:23 | ControlFlowNode for Attribute | test.py:8:30:8:33 | ControlFlowNode for text | | test.py:7:12:7:23 | ControlFlowNode for Attribute | test.py:9:32:9:35 | ControlFlowNode for text | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:7:12:7:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:7:12:7:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:8:30:8:33 | ControlFlowNode for text | semmle.label | ControlFlowNode for text | | test.py:9:32:9:35 | ControlFlowNode for text | semmle.label | ControlFlowNode for text | subpaths #select -| test.py:8:30:8:33 | ControlFlowNode for text | test.py:7:12:7:18 | ControlFlowNode for request | test.py:8:30:8:33 | ControlFlowNode for text | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | test.py:8:21:8:23 | \\s+ | regular expression | test.py:7:12:7:18 | ControlFlowNode for request | a user-provided value | -| test.py:9:32:9:35 | ControlFlowNode for text | test.py:7:12:7:18 | ControlFlowNode for request | test.py:9:32:9:35 | ControlFlowNode for text | This $@ that depends on $@ may run slow on strings with many repetitions of '99'. | test.py:9:27:9:29 | \\d+ | regular expression | test.py:7:12:7:18 | ControlFlowNode for request | a user-provided value | +| test.py:8:30:8:33 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:8:30:8:33 | ControlFlowNode for text | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | test.py:8:21:8:23 | \\s+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| test.py:9:32:9:35 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:9:32:9:35 | ControlFlowNode for text | This $@ that depends on $@ may run slow on strings with many repetitions of '99'. | test.py:9:27:9:29 | \\d+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected index 317815142fe..bbc01aab4be 100644 --- a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected @@ -1,4 +1,9 @@ edges +| re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | re_bad.py:13:22:13:28 | ControlFlowNode for request | +| re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | re_bad.py:24:22:24:28 | ControlFlowNode for request | +| re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | re_bad.py:36:22:36:28 | ControlFlowNode for request | +| re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | re_bad.py:1:19:1:25 | GSSA Variable request | +| re_bad.py:1:19:1:25 | GSSA Variable request | re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | | re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | | re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | @@ -9,6 +14,9 @@ edges | re_bad.py:36:22:36:33 | ControlFlowNode for Attribute | re_bad.py:36:22:36:44 | ControlFlowNode for Subscript | | re_bad.py:36:22:36:44 | ControlFlowNode for Subscript | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | nodes +| re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | semmle.label | ModuleVariableNode for re_bad.request | +| re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| re_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | re_bad.py:13:22:13:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -23,6 +31,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 | $@ depends on $@ and executed by $@. | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:13:22:13:28 | ControlFlowNode for request | a 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 | $@ depends on $@ and executed by $@. | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:24:22:24:28 | ControlFlowNode for request | a 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 | $@ depends on $@ and executed by $@. | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:36:22:36:28 | ControlFlowNode for request | a user-provided value | re_bad.py:37:5:37:41 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | $@ depends on $@ and executed by $@. | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a 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:1:19:1:25 | ControlFlowNode for ImportMember | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | $@ depends on $@ and executed by $@. | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a 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:1:19:1:25 | ControlFlowNode for ImportMember | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | $@ depends on $@ and executed by $@. | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | a 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-776-XmlBomb/XmlBomb.expected b/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected index 79ebe0bfef7..99f81737974 100644 --- a/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected +++ b/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected @@ -1,12 +1,18 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:19:19:19:25 | ControlFlowNode for request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:1:26:1:32 | GSSA Variable request | +| test.py:1:26:1:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:19:19:19:25 | ControlFlowNode for request | test.py:19:19:19:30 | ControlFlowNode for Attribute | | test.py:19:19:19:30 | ControlFlowNode for Attribute | test.py:19:19:19:45 | ControlFlowNode for Subscript | | test.py:19:19:19:45 | ControlFlowNode for Subscript | test.py:30:34:30:44 | ControlFlowNode for xml_content | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:19:19:19:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:19:19:19:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:19:19:19:45 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:30:34:30:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | subpaths #select -| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against uncontrolled entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | a user-provided value | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against uncontrolled entity expansion. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected index cc55c8317e1..9de3a7c1182 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected @@ -1,4 +1,26 @@ edges +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | @@ -79,6 +101,15 @@ edges | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:11:18:11:24 | ControlFlowNode for request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | @@ -107,6 +138,12 @@ edges | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:33:25:33:28 | ControlFlowNode for path | | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:37:25:37:28 | ControlFlowNode for path | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | test_requests.py:6:18:6:24 | ControlFlowNode for request | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | test_requests.py:6:18:6:24 | ControlFlowNode for request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request | +| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | +| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | @@ -114,6 +151,12 @@ edges | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | nodes +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | semmle.label | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | semmle.label | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -204,6 +247,12 @@ nodes | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | semmle.label | ModuleVariableNode for test_http_client.request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | semmle.label | ModuleVariableNode for test_http_client.request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -233,6 +282,12 @@ nodes | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | | test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | | test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | semmle.label | ModuleVariableNode for test_requests.request | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | semmle.label | ModuleVariableNode for test_requests.request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -243,24 +298,22 @@ nodes | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | subpaths #select -| full_partial_test.py:10:5:10:28 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:13:5:13:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:19:5:19:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:23:5:23:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:42:5:42:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:45:5:45:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:48:5:48:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:54:5:54:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:62:5:62:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:65:5:65:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:79:5:79:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:82:5:82:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_requests.py:8:5:8:28 | ControlFlowNode for Attribute() | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | test_requests.py:6:18:6:24 | ControlFlowNode for request | a user-provided value | +| full_partial_test.py:10:5:10:28 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:13:5:13:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:19:5:19:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:23:5:23:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:42:5:42:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:45:5:45:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:48:5:48:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:54:5:54:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:62:5:62:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:65:5:65:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:79:5:79:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:82:5:82:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test_requests.py:8:5:8:28 | ControlFlowNode for Attribute() | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected index 6206a070a88..7294de47bc2 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected @@ -1,4 +1,26 @@ edges +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | @@ -79,6 +101,15 @@ edges | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:11:18:11:24 | ControlFlowNode for request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | @@ -107,6 +138,12 @@ edges | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:33:25:33:28 | ControlFlowNode for path | | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:37:25:37:28 | ControlFlowNode for path | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | test_requests.py:6:18:6:24 | ControlFlowNode for request | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | test_requests.py:6:18:6:24 | ControlFlowNode for request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request | +| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | +| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | @@ -114,6 +151,12 @@ edges | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | nodes +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | semmle.label | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | semmle.label | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -204,6 +247,12 @@ nodes | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | semmle.label | ModuleVariableNode for test_http_client.request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | semmle.label | ModuleVariableNode for test_http_client.request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -233,6 +282,12 @@ nodes | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | | test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | | test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | semmle.label | ModuleVariableNode for test_requests.request | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | semmle.label | ModuleVariableNode for test_requests.request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -243,21 +298,15 @@ nodes | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | subpaths #select -| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:95:5:95:21 | ControlFlowNode for Attribute() | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:101:5:101:21 | ControlFlowNode for Attribute() | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:107:5:107:21 | ControlFlowNode for Attribute() | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:116:5:116:21 | ControlFlowNode for Attribute() | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:122:5:122:21 | ControlFlowNode for Attribute() | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:22:5:22:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:26:5:26:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | a user-provided value | +| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:95:5:95:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:101:5:101:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:107:5:107:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:116:5:116:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| full_partial_test.py:122:5:122:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:22:5:22:31 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:26:5:26:31 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | +| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | a user-provided value | From d7be27a1c05fe1f91bd85193bb069e2e722e88dd Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 3 Oct 2022 21:19:30 +0200 Subject: [PATCH 010/107] Python: Fix experimental `py/ip-address-spoofing` I realized the modeling was done in a non-recommended way, so I changed the modeling. It was very nice that I could use API graphs for the flask part, and a little sad when I couldn't for Django/Tornado. --- .../lib/semmle/python/frameworks/Tornado.qll | 7 +- ...ClientSuppliedIpUsedInSecurityCheckLib.qll | 82 ++++++++----------- ...ientSuppliedIpUsedInSecurityCheck.expected | 8 ++ 3 files changed, 45 insertions(+), 52 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Tornado.qll b/python/ql/lib/semmle/python/frameworks/Tornado.qll index 77c60097cb5..9cf258babe9 100644 --- a/python/ql/lib/semmle/python/frameworks/Tornado.qll +++ b/python/ql/lib/semmle/python/frameworks/Tornado.qll @@ -14,10 +14,12 @@ private import semmle.python.frameworks.Stdlib private import semmle.python.frameworks.internal.InstanceTaintStepsHelper /** + * INTERNAL: Do not use. + * * Provides models for the `tornado` PyPI package. * See https://www.tornadoweb.org/en/stable/. */ -private module Tornado { +module Tornado { /** * Provides models for the `tornado.httputil.HTTPHeaders` class * @@ -126,8 +128,7 @@ private module Tornado { abstract class InstanceSource extends DataFlow::LocalSourceNode { } /** The `self` parameter in a method on the `tornado.web.RequestHandler` class or any subclass. */ - private class SelfParam extends InstanceSource, RemoteFlowSource::Range, - DataFlow::ParameterNode { + class SelfParam extends InstanceSource, RemoteFlowSource::Range, DataFlow::ParameterNode { SelfParam() { exists(RequestHandlerClass cls | cls.getAMethod().getArg(0) = this.getParameter()) } diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll index 21e602e5d34..39b69b10004 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll @@ -1,73 +1,57 @@ private import python private import semmle.python.Concepts private import semmle.python.ApiGraphs -private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.frameworks.Flask +private import semmle.python.frameworks.Django +private import semmle.python.frameworks.Tornado /** * 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")`. + * + * A call to `request.headers.get` or `request.headers.get_all` or `request.headers.getlist`. */ -abstract class ClientSuppliedIpUsedInSecurityCheck extends DataFlow::CallCfgNode { } +abstract class ClientSuppliedIpUsedInSecurityCheck extends DataFlow::Node { } -private class FlaskClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { +private class FlaskClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck, + DataFlow::MethodCallNode { FlaskClientSuppliedIpUsedInSecurityCheck() { - 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() - ) + this = Flask::request().getMember("headers").getMember(["get", "get_all", "getlist"]).getACall() and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() } } -private class DjangoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { +private class DjangoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck, + DataFlow::MethodCallNode { DjangoClientSuppliedIpUsedInSecurityCheck() { - exists(RemoteFlowSource rfs, DataFlow::AttrRead get | - rfs.getSourceType() = "django.http.request.HttpRequest" and this.getFunction() = get - | - // `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() - ) + exists(DataFlow::Node req, DataFlow::AttrRead headers | + // a call to request.headers.get or request.META.get + req = PrivateDjango::DjangoImpl::DjangoHttp::Request::HttpRequest::instance() and + headers.getObject().getALocalSource() = req and + headers.getAttributeName() in ["headers", "META"] and + this.calls(headers, "get") + ) and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() } } -private class TornadoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { +private class TornadoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck, + DataFlow::MethodCallNode { TornadoClientSuppliedIpUsedInSecurityCheck() { - exists(RemoteFlowSource rfs, DataFlow::AttrRead get | - rfs.getSourceType() = "tornado.web.RequestHandler" and this.getFunction() = get + // a call to self.request.headers.get or self.request.headers.get_list inside a tornado requesthandler + exists( + Tornado::TornadoModule::Web::RequestHandler::SelfParam selfParam, DataFlow::AttrRead headers, + DataFlow::AttrRead req | - // `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() - ) + req.getObject().getALocalSource() = selfParam and + req.getAttributeName() = "request" and + headers.getObject().getALocalSource() = req and + headers.getAttributeName() = "headers" and + this.calls(headers, ["get", "get_list"]) + ) and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() } } 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 fd5bbf319dc..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 @@ -1,8 +1,16 @@ edges +| 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 +| 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 | 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 | | 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 | From 33d204913c99c491db086bde686b7ab7ded45480 Mon Sep 17 00:00:00 2001 From: tyage Date: Tue, 4 Oct 2022 14:45:09 +0900 Subject: [PATCH 011/107] add test for json stringify xss --- .../XssWithAdditionalSources.expected | 30 ++++++++++++++ .../CWE-079/DomBasedXss/json-stringify.jsx | 40 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/json-stringify.jsx diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index fa65ccbe3df..e09f45e5209 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected @@ -1,4 +1,18 @@ nodes +| JsonStringify.jsx:5:9:5:36 | locale | +| JsonStringify.jsx:5:9:5:36 | locale | +| JsonStringify.jsx:5:18:5:36 | req.param("locale") | +| JsonStringify.jsx:5:18:5:36 | req.param("locale") | +| JsonStringify.jsx:5:18:5:36 | req.param("locale") | +| JsonStringify.jsx:14:18:14:60 | `https: ... ocale}` | +| JsonStringify.jsx:14:53:14:58 | locale | +| JsonStringify.jsx:22:18:22:65 | `https: ... ocale}` | +| JsonStringify.jsx:22:58:22:63 | locale | +| JsonStringify.jsx:30:40:30:45 | locale | +| JsonStringify.jsx:30:40:30:45 | locale | +| JsonStringify.jsx:30:40:30:45 | locale | +| JsonStringify.jsx:34:40:34:61 | JSON.st ... jsonLD) | +| JsonStringify.jsx:34:40:34:61 | JSON.st ... jsonLD) | | addEventListener.js:1:43:1:47 | event | | addEventListener.js:1:43:1:47 | event | | addEventListener.js:1:43:1:47 | event | @@ -1154,6 +1168,22 @@ nodes | xmlRequest.js:22:24:22:35 | json.message | | xmlRequest.js:22:24:22:35 | json.message | edges +| JsonStringify.jsx:5:9:5:36 | locale | JsonStringify.jsx:14:53:14:58 | locale | +| JsonStringify.jsx:5:9:5:36 | locale | JsonStringify.jsx:22:58:22:63 | locale | +| JsonStringify.jsx:5:9:5:36 | locale | JsonStringify.jsx:30:40:30:45 | locale | +| JsonStringify.jsx:5:9:5:36 | locale | JsonStringify.jsx:30:40:30:45 | locale | +| JsonStringify.jsx:5:9:5:36 | locale | JsonStringify.jsx:30:40:30:45 | locale | +| JsonStringify.jsx:5:9:5:36 | locale | JsonStringify.jsx:30:40:30:45 | locale | +| JsonStringify.jsx:5:18:5:36 | req.param("locale") | JsonStringify.jsx:5:9:5:36 | locale | +| JsonStringify.jsx:5:18:5:36 | req.param("locale") | JsonStringify.jsx:5:9:5:36 | locale | +| JsonStringify.jsx:5:18:5:36 | req.param("locale") | JsonStringify.jsx:5:9:5:36 | locale | +| JsonStringify.jsx:5:18:5:36 | req.param("locale") | JsonStringify.jsx:5:9:5:36 | locale | +| JsonStringify.jsx:14:18:14:60 | `https: ... ocale}` | JsonStringify.jsx:34:40:34:61 | JSON.st ... jsonLD) | +| JsonStringify.jsx:14:18:14:60 | `https: ... ocale}` | JsonStringify.jsx:34:40:34:61 | JSON.st ... jsonLD) | +| JsonStringify.jsx:14:53:14:58 | locale | JsonStringify.jsx:14:18:14:60 | `https: ... ocale}` | +| JsonStringify.jsx:22:18:22:65 | `https: ... ocale}` | JsonStringify.jsx:34:40:34:61 | JSON.st ... jsonLD) | +| JsonStringify.jsx:22:18:22:65 | `https: ... ocale}` | JsonStringify.jsx:34:40:34:61 | JSON.st ... jsonLD) | +| JsonStringify.jsx:22:58:22:63 | locale | JsonStringify.jsx:22:18:22:65 | `https: ... ocale}` | | addEventListener.js:1:43:1:47 | event | addEventListener.js:2:20:2:24 | event | | addEventListener.js:1:43:1:47 | event | addEventListener.js:2:20:2:24 | event | | addEventListener.js:1:43:1:47 | event | addEventListener.js:2:20:2:24 | event | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/json-stringify.jsx b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/json-stringify.jsx new file mode 100644 index 00000000000..8d484964ca0 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/json-stringify.jsx @@ -0,0 +1,40 @@ +var express = require("express"); +var app = express(); + +app.get("/some/path", function (req, res) { + const locale = req.param("locale"); + const jsonLD = { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + item: { + "@id": `https://example.com/some?locale=${locale}`, + name: "Some", + }, + }, + { + "@type": "ListItem", + position: 2, + item: { + "@id": `https://example.com/some/path?locale=${locale}`, + name: "Real Dresses", + }, + }, + ], + }; + // OK }); From 48bdf13c8979cf5688e8c7c884f3ee03e8c60975 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 6 Oct 2022 10:11:23 +0200 Subject: [PATCH 046/107] Ruby: Take overrides into account for singleton methods defined on modules --- .../dataflow/internal/DataFlowDispatch.qll | 23 +++++++++++++++++-- .../library-tests/modules/callgraph.expected | 4 ++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll index b7e9b14a910..355b235e926 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll @@ -389,7 +389,7 @@ private module Cached { // ``` exists(DataFlow::Node sourceNode, Module m | flowsToMethodCall(call, sourceNode, method) and - singletonMethodOnModule(result, method, m) + result = lookupSingletonMethod(m, method) | // ```rb // def C.singleton; end # <- result @@ -725,7 +725,10 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module selfInModule(object.(SelfVariableReadAccess).getVariable(), m) ) or - flowsToSingletonMethodObject(trackModuleAccess(m), method, name) + exists(DataFlow::LocalSourceNode sourceNode | + m = resolveConstantReadAccess(sourceNode.asExpr().getExpr()) and + flowsToSingletonMethodObject(sourceNode, method, name) + ) or exists(Module other | extendCallModule(m, other) and @@ -733,6 +736,22 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module ) } +pragma[nomagic] +private MethodBase lookupSingletonMethod(Module m, string name) { + singletonMethodOnModule(result, name, m) + or + // cannot be part of `singletonMethodOnModule` because it would introduce + // negative recursion below + exists(DataFlow::LocalSourceNode sourceNode | + sourceNode = trackModuleAccess(m) and + not m = resolveConstantReadAccess(sourceNode.asExpr().getExpr()) and + flowsToSingletonMethodObject(sourceNode, result, name) + ) + or + not singletonMethodOnModule(_, name, m) and + result = lookupSingletonMethod(m.getSuperClass(), name) +} + /** * Holds if `method` is a singleton method named `name`, defined on expression * `object`, where `object` is not likely to resolve to a module: diff --git a/ruby/ql/test/library-tests/modules/callgraph.expected b/ruby/ql/test/library-tests/modules/callgraph.expected index 4af83afbe26..df2bffe2933 100644 --- a/ruby/ql/test/library-tests/modules/callgraph.expected +++ b/ruby/ql/test/library-tests/modules/callgraph.expected @@ -161,6 +161,8 @@ getTarget | calls.rb:412:9:412:44 | call to puts | calls.rb:102:5:102:30 | puts | | calls.rb:416:1:416:29 | call to singleton1 | calls.rb:406:9:408:11 | singleton1 | | calls.rb:417:1:417:29 | call to singleton2 | calls.rb:411:5:413:7 | singleton2 | +| calls.rb:418:1:418:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 | +| calls.rb:419:1:419:34 | call to call_singleton2 | calls.rb:392:5:394:7 | call_singleton2 | | calls.rb:424:13:424:48 | call to puts | calls.rb:102:5:102:30 | puts | | calls.rb:429:9:429:44 | call to puts | calls.rb:102:5:102:30 | puts | | calls.rb:432:13:432:48 | call to puts | calls.rb:102:5:102:30 | puts | @@ -290,8 +292,6 @@ unresolvedCall | calls.rb:274:1:274:14 | call to singleton_g | | calls.rb:276:1:276:14 | call to singleton_g | | calls.rb:313:9:313:20 | call to instance | -| calls.rb:418:1:418:34 | call to call_singleton1 | -| calls.rb:419:1:419:34 | call to call_singleton2 | | calls.rb:422:8:422:13 | call to rand | | calls.rb:422:8:422:17 | ... > ... | | calls.rb:439:9:439:10 | call to m3 | From 6f3c9e4403a09d5876d28724bef113a27966a1b4 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 27 Sep 2022 12:55:54 +0100 Subject: [PATCH 047/107] Split up extractRawMethodAccess --- .../src/main/kotlin/KotlinFileExtractor.kt | 150 +++++++++--------- 1 file changed, 76 insertions(+), 74 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index b7aff59b599..81acc665be3 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1557,6 +1557,64 @@ open class KotlinFileExtractor( } + private fun getFunctionInvokeMethod(typeArgs: List): IrFunction? { + // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we + // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`. + val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(typeArgs) + if (functionalInterface == null) { + logger.warn("Cannot find functional interface type for raw method access") + return null + } + val functionalInterfaceClass = functionalInterface.classOrNull + if (functionalInterfaceClass == null) { + logger.warn("Cannot find functional interface class for raw method access") + return null + } + val interfaceType = functionalInterfaceClass.owner + val substituted = getJavaEquivalentClass(interfaceType) ?: interfaceType + val function = findFunction(substituted, OperatorNameConventions.INVOKE.asString()) + if (function == null) { + logger.warn("Cannot find invoke function for raw method access") + return null + } + return function + } + + private fun isFunctionInvoke(callTarget: IrFunction, drType: IrSimpleType) = + (drType.isFunctionOrKFunction() || drType.isSuspendFunctionOrKFunction()) && + callTarget.name.asString() == OperatorNameConventions.INVOKE.asString() + + private fun getCalleeMethodId(callTarget: IrFunction, drType: IrType?, allowInstantiatedGenericMethod: Boolean): Label? { + if (callTarget.isLocalFunction()) + return getLocallyVisibleFunctionLabels(callTarget).function + + if (allowInstantiatedGenericMethod && drType is IrSimpleType && !isUnspecialised(drType, logger)) { + val calleeIsInvoke = isFunctionInvoke(callTarget, drType) + + val extractionMethod = + if (calleeIsInvoke) + getFunctionInvokeMethod(drType.arguments) + else + callTarget + + return extractionMethod?.let { + val typeArgs = + if (calleeIsInvoke && drType.arguments.size > BuiltInFunctionArity.BIG_ARITY) { + // Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to + // `kotlin.jvm.functions.FunctionN::invoke(vararg args: Any?)`, so we only need to pass the type + // argument for the return type. Additionally, the arguments are extracted inside an array literal below. + listOf(drType.arguments.last()) + } else { + getDeclaringTypeArguments(callTarget, drType) + } + useFunction(extractionMethod, typeArgs) + } + } + else { + return useFunction(callTarget) + } + } + fun extractRawMethodAccess( syntacticCallTarget: IrFunction, @@ -1588,86 +1646,30 @@ open class KotlinFileExtractor( // type arguments at index -2, -3, ... extractTypeArguments(typeArguments, locId, id, enclosingCallable, enclosingStmt, -2, true) - val (isFunctionInvoke, isBigArityFunctionInvoke) = - if (drType is IrSimpleType && - (drType.isFunctionOrKFunction() || drType.isSuspendFunctionOrKFunction()) && - callTarget.name.asString() == OperatorNameConventions.INVOKE.asString()) { - Pair(true, drType.arguments.size > BuiltInFunctionArity.BIG_ARITY) - } else { - Pair(false, false) - } + val methodId = getCalleeMethodId(callTarget, drType, extractClassTypeArguments) + + if (methodId == null) { + logger.warn("No method to bind call to for raw method access") + } else { + tw.writeCallableBinding(id, methodId) + } if (callTarget.isLocalFunction()) { - val ids = getLocallyVisibleFunctionLabels(callTarget) - - val methodId = ids.function - tw.writeCallableBinding(id, methodId) - - extractNewExprForLocalFunction(ids, id, locId, enclosingCallable, enclosingStmt) - } else { - val methodId = - if (extractClassTypeArguments && drType is IrSimpleType && !isUnspecialised(drType, logger)) { - - val extractionMethod = if (isFunctionInvoke) { - // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we - // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`. - val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments) - if (functionalInterface == null) { - logger.warn("Cannot find functional interface type for raw method access") - null - } else { - val functionalInterfaceClass = functionalInterface.classOrNull - if (functionalInterfaceClass == null) { - logger.warn("Cannot find functional interface class for raw method access") - null - } else { - val interfaceType = functionalInterfaceClass.owner - val substituted = getJavaEquivalentClass(interfaceType) ?: interfaceType - val function = findFunction(substituted, OperatorNameConventions.INVOKE.asString()) - if (function == null) { - logger.warn("Cannot find invoke function for raw method access") - null - } else { - function - } - } - } - } else { - callTarget - } - - if (extractionMethod == null) { - null - } else if (isBigArityFunctionInvoke) { - // Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to - // `kotlin.jvm.functions.FunctionN::invoke(vararg args: Any?)`, so we only need to pass the type - // argument for the return type. Additionally, the arguments are extracted inside an array literal below. - useFunction(extractionMethod, listOf(drType.arguments.last())) - } else { - useFunction(extractionMethod, getDeclaringTypeArguments(callTarget, drType)) - } - } - else { - useFunction(callTarget) - } - - if (methodId == null) { - logger.warn("No method to bind call to for raw method access") - } else { - tw.writeCallableBinding(id, methodId) - } - - if (callTarget.shouldExtractAsStatic) { - extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt) - } else if (superQualifierSymbol != null) { - extractSuperAccess(superQualifierSymbol.typeWith(), enclosingCallable, id, -1, enclosingStmt, locId) - } else if (extractDispatchReceiver != null) { - extractDispatchReceiver(id) - } + extractNewExprForLocalFunction(getLocallyVisibleFunctionLabels(callTarget), id, locId, enclosingCallable, enclosingStmt) + } else if (callTarget.shouldExtractAsStatic) { + extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt) + } else if (superQualifierSymbol != null) { + extractSuperAccess(superQualifierSymbol.typeWith(), enclosingCallable, id, -1, enclosingStmt, locId) + } else if (extractDispatchReceiver != null) { + extractDispatchReceiver(id) } val idxOffset = if (extractExtensionReceiver != null) 1 else 0 + val isBigArityFunctionInvoke = drType is IrSimpleType && + isFunctionInvoke(callTarget, drType) && + drType.arguments.size > BuiltInFunctionArity.BIG_ARITY + val argParent = if (isBigArityFunctionInvoke) { extractArrayCreationWithInitializer(id, nValueArguments + idxOffset, locId, enclosingCallable, enclosingStmt) } else { From c6b7bb436d6400f11c5fab93a821ec0f8c060f26 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 6 Oct 2022 11:25:22 +0100 Subject: [PATCH 048/107] C++: Make the ql-for-ql checks happy. --- cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql index f2ae677813a..a378d50b0df 100644 --- a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql @@ -60,11 +60,11 @@ class VarargsFunction extends Function { // the terminator is 0 or -1 result = ["0", "-1"] and // at least 80% of calls have the terminator - cnt = trailingArgValueCount(result) and - totalCount = totalCount() and + cnt = this.trailingArgValueCount(result) and + totalCount = this.totalCount() and 100 * cnt / totalCount >= 80 and // terminator value is not used in a non-terminating position - not exists(FunctionCall fc, int index | nonTrailingVarArgValue(fc, index) = result) + not exists(FunctionCall fc, int index | this.nonTrailingVarArgValue(fc, index) = result) } predicate isWhitelisted() { From 169965cfb9318dde36cc6ead8c637882a09eb948 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Thu, 6 Oct 2022 13:28:10 +0200 Subject: [PATCH 049/107] make rb/meta/taint-steps into a @kind problem query --- ruby/ql/src/queries/meta/TaintSteps.ql | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ruby/ql/src/queries/meta/TaintSteps.ql b/ruby/ql/src/queries/meta/TaintSteps.ql index c93322500c3..dfcf2dc9e77 100644 --- a/ruby/ql/src/queries/meta/TaintSteps.ql +++ b/ruby/ql/src/queries/meta/TaintSteps.ql @@ -1,11 +1,11 @@ /** * @name Taint steps - * @description The number of default taint steps. - * @kind metric - * @metricType project - * @metricAggregate sum - * @tags meta + * @description All taint steps. + * @kind problem + * @problem.severity recommendation * @id rb/meta/taint-steps + * @tags meta + * @precision very-low */ import ruby @@ -14,4 +14,8 @@ import codeql.ruby.dataflow.internal.TaintTrackingPublic predicate relevantStep(DataFlow::Node pred, DataFlow::Node succ) { localTaintStep(pred, succ) } -select projectRoot(), count(DataFlow::Node pred, DataFlow::Node succ | relevantStep(pred, succ)) +from DataFlow::Node pred, int numOfSuccessors +where + relevantStep(pred, _) and + numOfSuccessors = count(DataFlow::Node succ | relevantStep(pred, succ)) +select pred, "Step to " + numOfSuccessors + " other nodes." From 34a0a0d080baac79099aba8862ba0fe23bc377bc Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 3 Oct 2022 14:47:07 +0100 Subject: [PATCH 050/107] Implement $default method synthesis This adds methods that fill in default parameters whenever a constructor or method uses default parameter values. I use as similar an approach to the real Kotlin compiler as possible both because this produces the desirable dataflow, and because it should merge cleanly with the same class file seen by the Java extractor, which will see and extract the signatures of the default methods. --- .../src/main/kotlin/KotlinFileExtractor.kt | 494 ++++++++-- .../src/main/kotlin/KotlinUsesExtractor.kt | 32 +- java/ql/lib/semmle/code/java/Element.qll | 2 + .../parameter-defaults/PrintAst.expected | 849 ++++++++++++++++++ .../parameter-defaults/PrintAst.qlref | 1 + .../parameter-defaults/flowTest.expected | 2 + .../parameter-defaults/flowTest.ql | 34 + .../library-tests/parameter-defaults/test.kt | 141 +++ 8 files changed, 1460 insertions(+), 95 deletions(-) create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.qlref create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.expected create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.ql create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/test.kt diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 81acc665be3..d5615a1cfa9 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* @@ -688,7 +689,7 @@ open class KotlinFileExtractor( "", listOf(), pluginContext.irBuiltIns.unitType, - extensionReceiverParameter = null, + extensionParamType = null, functionTypeParameters = listOf(), classTypeArgsIncludingOuterClasses = listOf(), overridesCollectionsMethod = false, @@ -832,10 +833,117 @@ open class KotlinFileExtractor( null else { forceExtractFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses).also { + // The defaults-forwarder function is a static utility, not a member, so we only need to extract this for the unspecialised instance of this class. + if (classTypeArgsIncludingOuterClasses.isNullOrEmpty()) + extractDefaultsFunction(f, parentId, extractBody) extractGeneratedOverloads(f, parentId, null, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses) } } + private fun extractDefaultsFunction(f: IrFunction, parentId: Label, extractBody: Boolean) { + if (f.valueParameters.none { it.defaultValue != null }) + return + + val id = getDefaultsMethodLabel(f) + val locId = getLocation(f, null) + val extReceiver = f.extensionReceiverParameter + val dispatchReceiver = if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter + val parameterTypes = listOfNotNull(extReceiver?.let { erase(it.type) }) + getDefaultsMethodArgTypes(f) + val allParamTypeResults = parameterTypes.mapIndexed { i, paramType -> + val paramId = tw.getLabelFor(getValueParameterLabel(id, i)) + extractValueParameter(paramId, paramType, "p$i", locId, id, i, paramId, isVararg = false, syntheticParameterNames = true, isCrossinline = false, isNoinline = false).also { + extractTypeAccess(useType(paramType), locId, paramId, -1) + } + } + val paramsSignature = allParamTypeResults.joinToString(separator = ",", prefix = "(", postfix = ")") { it.javaResult.signature } + val shortName = getDefaultsMethodName(f) + + if (f.symbol is IrConstructorSymbol) { + val constrId = id.cast() + extractConstructor(constrId, shortName, paramsSignature, parentId, constrId) + } else { + val methodId = id.cast() + extractMethod(methodId, locId, shortName, erase(f.returnType), paramsSignature, parentId, methodId, origin = null, extractTypeAccess = true) + addModifiers(id, "static") + } + tw.writeHasLocation(id, locId) + addModifiers(id, "public") + tw.writeCompiler_generated(id, CompilerGeneratedKinds.DEFAULT_ARGUMENTS_METHOD.kind) + + if (extractBody) { + val nonSyntheticParams = listOfNotNull(dispatchReceiver) + f.valueParameters + // This stack entry represents as if we're extracting the 'real' function `f`, giving the indices of its non-synthetic parameters + // such that when we extract the default expressions below, any reference to f's nth parameter will resolve to f$default's + // n + o'th parameter, where `o` is the parameter offset caused by adding any dispatch receiver to the parameter list. + // Note we don't need to add the extension receiver here because `useValueParameter` always assumes an extension receiver + // will be prepended if one exists. + DeclarationStackAdjuster(f, OverriddenFunctionAttributes(id, id, locId, nonSyntheticParams)).use { + val realParamsVarId = getValueParameterLabel(id, parameterTypes.size - 2) + val intType = pluginContext.irBuiltIns.intType + val paramIdxOffset = listOf(dispatchReceiver, f.extensionReceiverParameter).count { it != null } + extractBlockBody(id, locId).also { blockId -> + var nextStmt = 0 + // For each parameter with a default, sub in the default value if the caller hasn't supplied a value: + f.valueParameters.forEachIndexed { paramIdx, param -> + val defaultVal = param.defaultValue + if (defaultVal != null) { + extractIfStmt(locId, blockId, nextStmt++, id).also { ifId -> + // if (realParams & thisParamBit == 0) ... + extractEqualsExpression(locId, ifId, 0, id, ifId).also { eqId -> + extractAndbitExpression(intType, locId, eqId, 0, id, ifId).also { opId -> + extractConstantInteger(1 shl paramIdx, locId, opId, 0, id, ifId) + extractVariableAccess(tw.getLabelFor(realParamsVarId), intType, locId, opId, 1, id, ifId) + } + extractConstantInteger(0, locId, eqId, 1, id, ifId) + } + // thisParamVar = defaultExpr... + extractExpressionStmt(locId, ifId, 1, id).also { exprStmtId -> + extractAssignExpr(param.type, locId, exprStmtId, 0, id, exprStmtId).also { assignId -> + extractVariableAccess(tw.getLabelFor(getValueParameterLabel(id, paramIdx + paramIdxOffset)), param.type, locId, assignId, 0, id, exprStmtId) + extractExpressionExpr(defaultVal.expression, id, assignId, 1, exprStmtId) + } + } + } + } + } + // Now call the real function: + val realFunctionId = useFunction(f) + if (f is IrConstructor) { + tw.getFreshIdLabel().also { thisCallId -> + tw.writeStmts_constructorinvocationstmt(thisCallId, blockId, nextStmt++, id) + tw.writeHasLocation(thisCallId, locId) + f.valueParameters.forEachIndexed { idx, param -> + extractVariableAccess(tw.getLabelFor(getValueParameterLabel(id, idx)), param.type, locId, thisCallId, idx, id, thisCallId) + } + tw.writeCallableBinding(thisCallId, realFunctionId) + } + } else { + tw.getFreshIdLabel().also { returnId -> + tw.writeStmts_returnstmt(returnId, blockId, nextStmt++, id) + tw.writeHasLocation(returnId, locId) + extractMethodAccessWithoutArgs(f.returnType, locId, id, returnId, 0, returnId, realFunctionId).also { thisCallId -> + val realFnIdxOffset = if (f.extensionReceiverParameter != null) 1 else 0 + val paramMappings = f.valueParameters.mapIndexed { idx, param -> Triple(param.type, idx + paramIdxOffset, idx + realFnIdxOffset) } + + listOfNotNull( + dispatchReceiver?.let { Triple(it.type, realFnIdxOffset, -1) }, + extReceiver?.let { Triple(it.type, 0, 0) } + ) + paramMappings.forEach { (type, fromIdx, toIdx) -> + extractVariableAccess(tw.getLabelFor(getValueParameterLabel(id, fromIdx)), type, locId, thisCallId, toIdx, id, returnId) + } + if (f.shouldExtractAsStatic) + extractStaticTypeAccessQualifier(f, thisCallId, locId, id, returnId) + else if (f.isLocalFunction()) { + extractNewExprForLocalFunction(getLocallyVisibleFunctionLabels(f), thisCallId, locId, id, returnId) + } + } + } + } + } + } + } + } + private val jvmOverloadsFqName = FqName("kotlin.jvm.JvmOverloads") private fun extractGeneratedOverloads(f: IrFunction, parentId: Label, maybeSourceParentId: Label?, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?) { @@ -932,6 +1040,29 @@ open class KotlinFileExtractor( } } + private fun extractConstructor(id: Label, shortName: String, paramsSignature: String, parentId: Label, sourceDeclaration: Label) { + val unitType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN) + tw.writeConstrs(id, shortName, "$shortName$paramsSignature", unitType.javaResult.id, parentId, sourceDeclaration) + tw.writeConstrsKotlinType(id, unitType.kotlinResult.id) + } + + private fun extractMethod(id: Label, locId: Label, shortName: String, returnType: IrType, paramsSignature: String, parentId: Label, sourceDeclaration: Label, origin: IrDeclarationOrigin?, extractTypeAccess: Boolean) { + val returnTypeResults = useType(returnType, TypeContext.RETURN) + tw.writeMethods(id, shortName, "$shortName$paramsSignature", returnTypeResults.javaResult.id, parentId, sourceDeclaration) + tw.writeMethodsKotlinType(id, returnTypeResults.kotlinResult.id) + when (origin) { + IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER -> + tw.writeCompiler_generated(id, CompilerGeneratedKinds.GENERATED_DATA_CLASS_MEMBER.kind) + IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR -> + tw.writeCompiler_generated(id, CompilerGeneratedKinds.DEFAULT_PROPERTY_ACCESSOR.kind) + IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> + tw.writeCompiler_generated(id, CompilerGeneratedKinds.ENUM_CLASS_SPECIAL_MEMBER.kind) + } + if (extractTypeAccess) { + extractTypeAccessRecursive(returnType, locId, id, -1) + } + } + private fun forceExtractFunction(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?, extractOrigin: Boolean = true, overriddenAttributes: OverriddenFunctionAttributes? = null): Label { with("function", f) { DeclarationStackAdjuster(f, overriddenAttributes).use { @@ -976,42 +1107,23 @@ open class KotlinFileExtractor( val locId = overriddenAttributes?.sourceLoc ?: getLocation(f, classTypeArgsIncludingOuterClasses) if (f.symbol is IrConstructorSymbol) { - val unitType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN) val shortName = when { adjustedReturnType.isAnonymous -> "" typeSubstitution != null -> useType(substReturnType).javaResult.shortName else -> adjustedReturnType.classFqName?.shortName()?.asString() ?: f.name.asString() } - val constrId = id.cast() - tw.writeConstrs(constrId, shortName, "$shortName$paramsSignature", unitType.javaResult.id, parentId, sourceDeclaration.cast()) - tw.writeConstrsKotlinType(constrId, unitType.kotlinResult.id) + extractConstructor(id.cast(), shortName, paramsSignature, parentId, sourceDeclaration.cast()) } else { - val returnType = useType(substReturnType, TypeContext.RETURN) - val shortName = getFunctionShortName(f) + val shortNames = getFunctionShortName(f) val methodId = id.cast() - tw.writeMethods(methodId, shortName.nameInDB, "${shortName.nameInDB}$paramsSignature", returnType.javaResult.id, parentId, sourceDeclaration.cast()) - tw.writeMethodsKotlinType(methodId, returnType.kotlinResult.id) - if (extractOrigin) { - when (f.origin) { - IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER -> - tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.GENERATED_DATA_CLASS_MEMBER.kind) - IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR -> - tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.DEFAULT_PROPERTY_ACCESSOR.kind) - IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> - tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.ENUM_CLASS_SPECIAL_MEMBER.kind) - } - } + extractMethod(methodId, locId, shortNames.nameInDB, substReturnType, paramsSignature, parentId, sourceDeclaration.cast(), if (extractOrigin) f.origin else null, extractMethodAndParameterTypeAccesses) - if (extractMethodAndParameterTypeAccesses) { - extractTypeAccessRecursive(substReturnType, locId, id, -1) - } - - if (shortName.nameInDB != shortName.kotlinName) { - tw.writeKtFunctionOriginalNames(methodId, shortName.kotlinName) + if (shortNames.nameInDB != shortNames.kotlinName) { + tw.writeKtFunctionOriginalNames(methodId, shortNames.kotlinName) } if (f.hasInterfaceParent() && f.body != null) { - addModifiers(id, "default") // The actual output class file may or may not have this modifier, depending on the -Xjvm-default setting. + addModifiers(methodId, "default") // The actual output class file may or may not have this modifier, depending on the -Xjvm-default setting. } } @@ -1209,14 +1321,18 @@ open class KotlinFileExtractor( } } + private fun extractBlockBody(callable: Label, locId: Label) = + tw.getFreshIdLabel().also { + tw.writeStmts_block(it, callable, 0, callable) + tw.writeHasLocation(it, locId) + } + private fun extractBlockBody(b: IrBlockBody, callable: Label) { with("block body", b) { - val id = tw.getFreshIdLabel() - val locId = tw.getLocation(b) - tw.writeStmts_block(id, callable, 0, callable) - tw.writeHasLocation(id, locId) - for ((sIdx, stmt) in b.statements.withIndex()) { - extractStatement(stmt, callable, id, sIdx) + extractBlockBody(callable, tw.getLocation(b)).also { + for ((sIdx, stmt) in b.statements.withIndex()) { + extractStatement(stmt, callable, it, sIdx) + } } } } @@ -1294,6 +1410,12 @@ open class KotlinFileExtractor( } } + private fun extractIfStmt(locId: Label, parent: Label, idx: Int, callable: Label) = + tw.getFreshIdLabel().also { + tw.writeStmts_ifstmt(it, parent, idx, callable) + tw.writeHasLocation(it, locId) + } + private fun extractStatement(s: IrStatement, callable: Label, parent: Label, idx: Int) { with("statement", s) { when(s) { @@ -1521,6 +1643,147 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(pluginContext.irBuiltIns.anyType, locId, idNewexpr, -3, enclosingCallable, enclosingStmt) } + fun extractMethodAccessWithoutArgs( + returnType: IrType, + locId: Label, + enclosingCallable: Label, + callsiteParent: Label, + childIdx: Int, + enclosingStmt: Label, + methodLabel: Label? + ) = tw.getFreshIdLabel().also { id -> + val type = useType(returnType) + + tw.writeExprs_methodaccess(id, type.javaResult.id, callsiteParent, childIdx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + tw.writeHasLocation(id, locId) + tw.writeCallableEnclosingExpr(id, enclosingCallable) + tw.writeStatementEnclosingExpr(id, enclosingStmt) + + // The caller should have warned about this before, so we don't repeat the warning here. + if (methodLabel != null) + tw.writeCallableBinding(id, methodLabel) + } + + private val defaultConstructorMarkerClass by lazy { + val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.DefaultConstructorMarker"))?.owner + result?.let { extractExternalClassLater(it) } + result + } + + private val defaultConstructorMarkerType by lazy { + defaultConstructorMarkerClass?.typeWith() + } + + private fun getDefaultsMethodLastArgType(f: IrFunction) = + ( + if (f is IrConstructor) + defaultConstructorMarkerType + else + null + ) ?: pluginContext.irBuiltIns.anyType + + private fun getDefaultsMethodArgTypes(f: IrFunction) = + // The $default method has type ([extensionReceiver], [dispatchReciever], paramTypes..., int, Object) + // All parameter types are erased. The trailing int is a mask indicating which parameter values are real + // and which should be replaced by defaults. The final Object parameter is apparently always null. + ( + listOfNotNull(if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter?.type) + + f.valueParameters.map { it.type } + + listOf(pluginContext.irBuiltIns.intType, getDefaultsMethodLastArgType(f)) + ).map { erase(it) } + + private fun getDefaultsMethodName(f: IrFunction) = + if (f is IrConstructor) { + f.returnType.let { + when { + it.isAnonymous -> "" + else -> it.classFqName?.shortName()?.asString() ?: f.name.asString() + } + } + } else { + f.name.asString() + "\$default" + } + + private fun getDefaultsMethodLabel(f: IrFunction): Label { + val defaultsMethodName = getDefaultsMethodName(f) + val normalArgTypes = getDefaultsMethodArgTypes(f) + val extensionParamType = f.extensionReceiverParameter?.let { erase(it.type) } + + val defaultMethodLabelStr = getFunctionLabel( + f.parent, + maybeParentId = null, + defaultsMethodName, + normalArgTypes, + erase(f.returnType), + extensionParamType, + listOf(), + classTypeArgsIncludingOuterClasses = null, + overridesCollectionsMethod = false, + javaSignature = null, + addParameterWildcardsByDefault = false + ) + + return tw.getLabelFor(defaultMethodLabelStr) + } + + private fun extractsDefaultsCall( + syntacticCallTarget: IrFunction, + locId: Label, + callsite: IrCall, + enclosingCallable: Label, + callsiteParent: Label, + childIdx: Int, + enclosingStmt: Label, + valueArguments: List, + dispatchReceiver: IrExpression?, + extensionReceiver: IrExpression? + ) { + val callTarget = syntacticCallTarget.target.realOverrideTarget + val defaultMethodLabel = getDefaultsMethodLabel(callTarget) + val id = extractMethodAccessWithoutArgs(callsite.type, locId, enclosingCallable, callsiteParent, childIdx, enclosingStmt, defaultMethodLabel) + + if (callTarget.isLocalFunction()) { + extractNewExprForLocalFunction(getLocallyVisibleFunctionLabels(callTarget), id, locId, enclosingCallable, enclosingStmt) + } else { + extractStaticTypeAccessQualifierUnchecked(callTarget.parent, id, locId, enclosingCallable, enclosingStmt) + } + + extractDefaultsCallArguments(id, callTarget, enclosingCallable, enclosingStmt, valueArguments, dispatchReceiver, extensionReceiver) + } + + private fun extractDefaultsCallArguments( + id: Label, + callTarget: IrFunction, + enclosingCallable: Label, + enclosingStmt: Label, + valueArguments: List, + dispatchReceiver: IrExpression?, + extensionReceiver: IrExpression? + ) { + var nextIdx = 0 + if (extensionReceiver != null) { + extractExpressionExpr(extensionReceiver, enclosingCallable, id, nextIdx++, enclosingStmt) + } + if (dispatchReceiver != null && !callTarget.shouldExtractAsStatic) { + extractExpressionExpr(dispatchReceiver, enclosingCallable, id, nextIdx++, enclosingStmt) + } + + val valueArgsWithDummies = valueArguments.zip(callTarget.valueParameters).map { + (expr, param) -> expr ?: IrConstImpl.defaultValueForType(0, 0, param.type) + } + + var realParamsMask = 0 + valueArguments.forEachIndexed { index, arg -> if (arg != null) realParamsMask = realParamsMask or (1 shl index) } + + val extraArgs = listOf( + IrConstImpl.int(0, 0, pluginContext.irBuiltIns.intType, realParamsMask), + IrConstImpl.defaultValueForType(0, 0, getDefaultsMethodLastArgType(callTarget)) + ) + + extractCallValueArguments(id, valueArgsWithDummies + extraArgs, enclosingStmt, enclosingCallable, nextIdx) + } + fun extractRawMethodAccess( syntacticCallTarget: IrFunction, callsite: IrCall, @@ -1537,24 +1800,38 @@ open class KotlinFileExtractor( val locId = tw.getLocation(callsite) - extractRawMethodAccess( - syntacticCallTarget, - locId, - callsite.type, - enclosingCallable, - callsiteParent, - childIdx, - enclosingStmt, - valueArguments.size, - { argParent, idxOffset -> extractCallValueArguments(argParent, valueArguments, enclosingStmt, enclosingCallable, idxOffset) }, - dispatchReceiver?.type, - dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } }, - extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } }, - typeArguments, - extractClassTypeArguments, - superQualifierSymbol - ) - + if (valueArguments.any { it == null }) { + extractsDefaultsCall( + syntacticCallTarget, + locId, + callsite, + enclosingCallable, + callsiteParent, + childIdx, + enclosingStmt, + valueArguments, + dispatchReceiver, + extensionReceiver + ) + } else { + extractRawMethodAccess( + syntacticCallTarget, + locId, + callsite.type, + enclosingCallable, + callsiteParent, + childIdx, + enclosingStmt, + valueArguments.size, + { argParent, idxOffset -> extractCallValueArguments(argParent, valueArguments, enclosingStmt, enclosingCallable, idxOffset) }, + dispatchReceiver?.type, + dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } }, + extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } }, + typeArguments, + extractClassTypeArguments, + superQualifierSymbol + ) + } } private fun getFunctionInvokeMethod(typeArgs: List): IrFunction? { @@ -1634,26 +1911,16 @@ open class KotlinFileExtractor( superQualifierSymbol: IrClassSymbol? = null) { val callTarget = syntacticCallTarget.target.realOverrideTarget - val id = tw.getFreshIdLabel() - val type = useType(returnType) + val methodId = getCalleeMethodId(callTarget, drType, extractClassTypeArguments) + if (methodId == null) { + logger.warn("No method to bind call to for raw method access") + } - tw.writeExprs_methodaccess(id, type.javaResult.id, callsiteParent, childIdx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - tw.writeHasLocation(id, locId) - tw.writeCallableEnclosingExpr(id, enclosingCallable) - tw.writeStatementEnclosingExpr(id, enclosingStmt) + val id = extractMethodAccessWithoutArgs(returnType, locId, enclosingCallable, callsiteParent, childIdx, enclosingStmt, methodId) // type arguments at index -2, -3, ... extractTypeArguments(typeArguments, locId, id, enclosingCallable, enclosingStmt, -2, true) - val methodId = getCalleeMethodId(callTarget, drType, extractClassTypeArguments) - - if (methodId == null) { - logger.warn("No method to bind call to for raw method access") - } else { - tw.writeCallableBinding(id, methodId) - } - if (callTarget.isLocalFunction()) { extractNewExprForLocalFunction(getLocallyVisibleFunctionLabels(callTarget), id, locId, enclosingCallable, enclosingStmt) } else if (callTarget.shouldExtractAsStatic) { @@ -1683,16 +1950,19 @@ open class KotlinFileExtractor( extractValueArguments(argParent, idxOffset) } + private fun extractStaticTypeAccessQualifierUnchecked(parent: IrDeclarationParent, parentExpr: Label, locId: Label, enclosingCallable: Label, enclosingStmt: Label) { + if (parent is IrClass) { + extractTypeAccessRecursive(parent.toRawType(), locId, parentExpr, -1, enclosingCallable, enclosingStmt) + } else if (parent is IrFile) { + extractTypeAccess(useFileClassType(parent), locId, parentExpr, -1, enclosingCallable, enclosingStmt) + } else { + logger.warnElement("Unexpected static type access qualifier ${parent.javaClass}", parent) + } + } + private fun extractStaticTypeAccessQualifier(target: IrDeclaration, parentExpr: Label, locId: Label, enclosingCallable: Label, enclosingStmt: Label) { if (target.shouldExtractAsStatic) { - val parent = target.parent - if (parent is IrClass) { - extractTypeAccessRecursive(parent.toRawType(), locId, parentExpr, -1, enclosingCallable, enclosingStmt) - } else if (parent is IrFile) { - extractTypeAccess(useFileClassType(parent), locId, parentExpr, -1, enclosingCallable, enclosingStmt) - } else { - logger.warnElement("Unexpected static type access qualifer ${parent.javaClass}", target) - } + extractStaticTypeAccessQualifierUnchecked(target.parent, parentExpr, locId, enclosingCallable, enclosingStmt) } } @@ -2666,14 +2936,22 @@ open class KotlinFileExtractor( useType(eType) } val locId = tw.getLocation(e) - val id = extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt) + val valueArgs = (0 until e.valueArgumentsCount).map { e.getValueArgument(it) } + val anyDefaultArgs = valueArgs.any { it == null } + val id = if (anyDefaultArgs) { + extractNewExpr(getDefaultsMethodLabel(e.symbol.owner).cast(), type, locId, parent, idx, callable, enclosingStmt).also { + extractDefaultsCallArguments(it, e.symbol.owner, callable, enclosingStmt, valueArgs, null, null) + } + } else { + extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt).also { + extractCallValueArguments(it, e, enclosingStmt, callable, 0) + } + } if (isAnonymous) { tw.writeIsAnonymClass(type.javaResult.id.cast(), id) } - extractCallValueArguments(id, e, enclosingStmt, callable, 0) - val dr = e.dispatchReceiver if (dr != null) { extractExpressionExpr(dr, callable, id, -2, enclosingStmt) @@ -2872,6 +3150,12 @@ open class KotlinFileExtractor( return false } + private fun extractExpressionStmt(locId: Label, parent: Label, idx: Int, callable: Label) = + tw.getFreshIdLabel().also { + tw.writeStmts_exprstmt(it, parent, idx, callable) + tw.writeHasLocation(it, locId) + } + private fun extractExpressionStmt(e: IrExpression, callable: Label, parent: Label, idx: Int) { extractExpression(e, callable, StmtParent(parent, idx)) } @@ -2880,6 +3164,45 @@ open class KotlinFileExtractor( extractExpression(e, callable, ExprParent(parent, idx, enclosingStmt)) } + private fun extractExprContext(id: Label, locId: Label, callable: Label, enclosingStmt: Label) { + tw.writeHasLocation(id, locId) + tw.writeCallableEnclosingExpr(id, callable) + tw.writeStatementEnclosingExpr(id, enclosingStmt) + } + + private fun extractEqualsExpression(locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + tw.getFreshIdLabel().also { + val type = useType(pluginContext.irBuiltIns.booleanType) + tw.writeExprs_eqexpr(it, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(it, type.kotlinResult.id) + extractExprContext(it, locId, callable, enclosingStmt) + } + + private fun extractAndbitExpression(type: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + tw.getFreshIdLabel().also { + val typeResults = useType(type) + tw.writeExprs_andbitexpr(it, typeResults.javaResult.id, parent, idx) + tw.writeExprsKotlinType(it, typeResults.kotlinResult.id) + extractExprContext(it, locId, callable, enclosingStmt) + } + + private fun extractConstantInteger(v: Int, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + tw.getFreshIdLabel().also { + val type = useType(pluginContext.irBuiltIns.intType) + tw.writeExprs_integerliteral(it, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(it, type.kotlinResult.id) + tw.writeNamestrings(v.toString(), v.toString(), it) + extractExprContext(it, locId, callable, enclosingStmt) + } + + private fun extractAssignExpr(type: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + tw.getFreshIdLabel().also { + val typeResults = useType(type) + tw.writeExprs_assignexpr(it, typeResults.javaResult.id, parent, idx) + tw.writeExprsKotlinType(it, typeResults.kotlinResult.id) + extractExprContext(it, locId, callable, enclosingStmt) + } + private fun extractExpression(e: IrExpression, callable: Label, parent: StmtExprParent) { with("expression", e) { when(e) { @@ -3130,7 +3453,7 @@ open class KotlinFileExtractor( val exprParent = parent.expr(e, callable) val owner = e.symbol.owner if (owner is IrValueParameter && owner.index == -1 && !owner.isExtensionReceiver()) { - extractThisAccess(e, exprParent, callable) + extractThisAccess(e, owner.parent, exprParent, callable) } else { val isAnnotationClassParameter = ((owner as? IrValueParameter)?.parent as? IrConstructor)?.parentClassOrNull?.kind == ClassKind.ANNOTATION_CLASS val extractType = if (isAnnotationClassParameter) kClassToJavaClass(e.type) else e.type @@ -3482,7 +3805,7 @@ open class KotlinFileExtractor( tw.writeStatementEnclosingExpr(it, enclosingStmt) } - private fun extractThisAccess(e: IrGetValue, exprParent: ExprParent, callable: Label) { + private fun extractThisAccess(e: IrGetValue, thisParamParent: IrDeclarationParent, exprParent: ExprParent, callable: Label) { val containingDeclaration = declarationStack.peek().first val locId = tw.getLocation(e) @@ -3494,6 +3817,20 @@ open class KotlinFileExtractor( extractStaticTypeAccessQualifier(containingDeclaration, varAccessId, locId, callable, exprParent.enclosingStmt) } } else { + if (thisParamParent is IrFunction) { + val overriddenAttributes = declarationStack.findOverriddenAttributes(thisParamParent) + val replaceWithParamIdx = overriddenAttributes?.valueParameters?.indexOf(e.symbol.owner) + if (replaceWithParamIdx != null && replaceWithParamIdx != -1) { + // Use of 'this' in a function where the dispatch receiver is passed like an ordinary parameter, + // such as a `$default` static function that substitutes in default arguments as needed. + val paramDeclarerId = overriddenAttributes.id ?: useDeclarationParent(thisParamParent, false) + val extensionParamOffset = if (thisParamParent.extensionReceiverParameter != null) 1 else 0 + val replacementParamId = tw.getLabelFor(getValueParameterLabel(paramDeclarerId, replaceWithParamIdx + extensionParamOffset)) + extractVariableAccess(replacementParamId, e.type, locId, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) + return + } + } + val id = extractThisAccess(e.type, callable, exprParent.parent, exprParent.idx, exprParent.enclosingStmt, locId) fun extractTypeAccess(parent: IrClass) { @@ -5048,5 +5385,6 @@ open class KotlinFileExtractor( DELEGATED_PROPERTY_SETTER(7), JVMSTATIC_PROXY_METHOD(8), JVMOVERLOADS_METHOD(9), + DEFAULT_ARGUMENTS_METHOD(10) } } diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index 957450474c5..5873b06c280 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -1043,9 +1043,9 @@ open class KotlinUsesExtractor( f.parent, maybeParentId, getFunctionShortName(f).nameInDB, - maybeParameterList ?: f.valueParameters, + (maybeParameterList ?: f.valueParameters).map { it.type }, getAdjustedReturnType(f), - f.extensionReceiverParameter, + f.extensionReceiverParameter?.type, getFunctionTypeParameters(f), classTypeArgsIncludingOuterClasses, overridesCollectionsMethodWithAlteredParameterTypes(f), @@ -1067,12 +1067,12 @@ open class KotlinUsesExtractor( maybeParentId: Label?, // The name of the function; normally f.name.asString(). name: String, - // The value parameters that the functions takes; normally f.valueParameters. - parameters: List, + // The types of the value parameters that the functions takes; normally f.valueParameters.map { it.type }. + parameterTypes: List, // The return type of the function; normally f.returnType. returnType: IrType, - // The extension receiver of the function, if any; normally f.extensionReceiverParameter. - extensionReceiverParameter: IrValueParameter?, + // The extension receiver of the function, if any; normally f.extensionReceiverParameter?.type. + extensionParamType: IrType?, // The type parameters of the function. This does not include type parameters of enclosing classes. functionTypeParameters: List, // The type arguments of enclosing classes of the function. @@ -1089,11 +1089,7 @@ open class KotlinUsesExtractor( prefix: String = "callable" ): String { val parentId = maybeParentId ?: useDeclarationParent(parent, false, classTypeArgsIncludingOuterClasses, true) - val allParams = if (extensionReceiverParameter == null) { - parameters - } else { - listOf(extensionReceiverParameter) + parameters - } + val allParamTypes = if (extensionParamType == null) parameterTypes else listOf(extensionParamType) + parameterTypes val substitutionMap = classTypeArgsIncludingOuterClasses?.let { notNullArgs -> if (notNullArgs.isEmpty()) { @@ -1103,11 +1099,11 @@ open class KotlinUsesExtractor( enclosingClass?.let { notNullClass -> makeTypeGenericSubstitutionMap(notNullClass, notNullArgs) } } } - val getIdForFunctionLabel = { it: IndexedValue -> + val getIdForFunctionLabel = { it: IndexedValue -> // Kotlin rewrites certain Java collections types adding additional generic constraints-- for example, // Collection.remove(Object) because Collection.remove(Collection::E) in the Kotlin universe. // If this has happened, erase the type again to get the correct Java signature. - val maybeAmendedForCollections = if (overridesCollectionsMethod) eraseCollectionsMethodParameterType(it.value.type, name, it.index) else it.value.type + val maybeAmendedForCollections = if (overridesCollectionsMethod) eraseCollectionsMethodParameterType(it.value, name, it.index) else it.value // Add any wildcard types that the Kotlin compiler would add in the Java lowering of this function: val withAddedWildcards = addJavaLoweringWildcards(maybeAmendedForCollections, addParameterWildcardsByDefault, javaSignature?.let { sig -> getJavaValueParameterType(sig, it.index) }) // Now substitute any class type parameters in: @@ -1117,7 +1113,7 @@ open class KotlinUsesExtractor( val maybeErased = if (functionTypeParameters.isEmpty()) maybeSubbed else erase(maybeSubbed) "{${useType(maybeErased).javaResult.id}}" } - val paramTypeIds = allParams.withIndex().joinToString(separator = ",", transform = getIdForFunctionLabel) + val paramTypeIds = allParamTypes.withIndex().joinToString(separator = ",", transform = getIdForFunctionLabel) val labelReturnType = if (name == "") pluginContext.irBuiltIns.unitType @@ -1551,7 +1547,7 @@ open class KotlinUsesExtractor( * Note that `Array` is retained (with `T` itself erased) because these are expected to be lowered to Java * arrays, which are not generic. */ - private fun erase (t: IrType): IrType { + fun erase (t: IrType): IrType { if (t is IrSimpleType) { val classifier = t.classifier val owner = classifier.owner @@ -1578,6 +1574,8 @@ open class KotlinUsesExtractor( private fun eraseTypeParameter(t: IrTypeParameter) = erase(t.superTypes[0]) + fun getValueParameterLabel(parentId: Label?, idx: Int) = "@\"params;{$parentId};$idx\"" + /** * Gets the label for `vp` in the context of function instance `parent`, or in that of its declaring function if * `parent` is null. @@ -1607,7 +1605,7 @@ open class KotlinUsesExtractor( logger.error("Unexpected negative index for parameter") } - return "@\"params;{$parentId};$idx\"" + return getValueParameterLabel(parentId, idx) } @@ -1669,7 +1667,7 @@ open class KotlinUsesExtractor( val returnType = getter?.returnType ?: setter?.valueParameters?.singleOrNull()?.type ?: pluginContext.irBuiltIns.unitType val typeParams = getFunctionTypeParameters(func) - getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext, typeParams, classTypeArgsIncludingOuterClasses, overridesCollectionsMethod = false, javaSignature = null, addParameterWildcardsByDefault = false, prefix = "property") + getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext.type, typeParams, classTypeArgsIncludingOuterClasses, overridesCollectionsMethod = false, javaSignature = null, addParameterWildcardsByDefault = false, prefix = "property") } } diff --git a/java/ql/lib/semmle/code/java/Element.qll b/java/ql/lib/semmle/code/java/Element.qll index d2cbfbc120e..0120cdc158f 100644 --- a/java/ql/lib/semmle/code/java/Element.qll +++ b/java/ql/lib/semmle/code/java/Element.qll @@ -65,6 +65,8 @@ class Element extends @element, Top { i = 8 and result = "Proxy static method for a @JvmStatic-annotated function or property" or i = 9 and result = "Forwarder for a @JvmOverloads-annotated function" + or + i = 10 and result = "Forwarder for Kotlin calls that need default arguments filling in" ) } } diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected new file mode 100644 index 00000000000..068b34f79b4 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -0,0 +1,849 @@ +test.kt: +# 0| [CompilationUnit] test +# 0| 1: [Class] TestKt +# 1| 1: [Method] sink +# 1| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 1| 0: [Parameter] a +# 1| 0: [TypeAccess] Object +# 1| 5: [BlockStmt] { ... } +# 3| 2: [Class] TestMember +# 3| 1: [Constructor] TestMember +# 3| 5: [BlockStmt] { ... } +# 3| 0: [SuperConstructorInvocationStmt] super(...) +# 3| 1: [BlockStmt] { ... } +# 5| 2: [Method] f +# 5| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 5| 0: [Parameter] x +# 5| 0: [TypeAccess] String +# 5| 1: [Parameter] y +# 5| 0: [TypeAccess] String +# 5| 2: [Parameter] z +# 5| 0: [TypeAccess] String +# 5| 5: [BlockStmt] { ... } +# 6| 0: [ExprStmt] ; +# 6| 0: [MethodAccess] sink(...) +# 6| -1: [TypeAccess] TestKt +# 6| 0: [VarAccess] y +# 5| 3: [Method] f$default +# 5| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 5| 0: [Parameter] p0 +# 5| 0: [TypeAccess] TestMember +# 5| 1: [Parameter] p1 +# 5| 0: [TypeAccess] String +# 5| 2: [Parameter] p2 +# 5| 0: [TypeAccess] String +# 5| 3: [Parameter] p3 +# 5| 0: [TypeAccess] String +# 5| 4: [Parameter] p4 +# 5| 0: [TypeAccess] int +# 5| 5: [Parameter] p5 +# 5| 0: [TypeAccess] Object +# 5| 5: [BlockStmt] { ... } +# 5| 0: [IfStmt] if (...) +# 5| 0: [EQExpr] ... == ... +# 5| 0: [AndBitwiseExpr] ... & ... +# 5| 0: [IntegerLiteral] 2 +# 5| 1: [VarAccess] p4 +# 5| 1: [IntegerLiteral] 0 +# 5| 1: [ExprStmt] ; +# 5| 0: [AssignExpr] ...=... +# 5| 0: [VarAccess] p2 +# 5| 1: [VarAccess] p1 +# 5| 1: [IfStmt] if (...) +# 5| 0: [EQExpr] ... == ... +# 5| 0: [AndBitwiseExpr] ... & ... +# 5| 0: [IntegerLiteral] 4 +# 5| 1: [VarAccess] p4 +# 5| 1: [IntegerLiteral] 0 +# 5| 1: [ExprStmt] ; +# 5| 0: [AssignExpr] ...=... +# 5| 0: [VarAccess] p3 +# 5| 1: [StringLiteral] hello world +# 5| 2: [ReturnStmt] return ... +# 5| 0: [MethodAccess] f(...) +# 5| -1: [VarAccess] p0 +# 5| 0: [VarAccess] p1 +# 5| 1: [VarAccess] p2 +# 5| 2: [VarAccess] p3 +# 9| 4: [Method] user +# 9| 3: [TypeAccess] Unit +# 9| 5: [BlockStmt] { ... } +# 10| 0: [ExprStmt] ; +# 10| 0: [MethodAccess] f$default(...) +# 10| -1: [TypeAccess] TestMember +# 10| 0: [ThisAccess] this +# 10| 1: [StringLiteral] member sunk +# 1| 2: [NullLiteral] null +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 1 +# 1| 5: [NullLiteral] null +# 11| 1: [ExprStmt] ; +# 11| 0: [MethodAccess] f$default(...) +# 11| -1: [TypeAccess] TestMember +# 11| 0: [ThisAccess] this +# 11| 1: [StringLiteral] member sunk fp +# 11| 2: [StringLiteral] member sunk 2 +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 3 +# 1| 5: [NullLiteral] null +# 12| 2: [ExprStmt] ; +# 12| 0: [MethodAccess] f(...) +# 12| -1: [ThisAccess] this +# 12| 0: [StringLiteral] not sunk +# 12| 1: [StringLiteral] member sunk 3 +# 12| 2: [StringLiteral] not sunk +# 17| 3: [Class] TestExtensionMember +# 17| 1: [Constructor] TestExtensionMember +# 17| 5: [BlockStmt] { ... } +# 17| 0: [SuperConstructorInvocationStmt] super(...) +# 17| 1: [BlockStmt] { ... } +# 19| 2: [ExtensionMethod] f +# 19| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 19| 0: [Parameter] +# 19| 0: [TypeAccess] String +# 19| 1: [Parameter] x +# 19| 0: [TypeAccess] String +# 19| 2: [Parameter] y +# 19| 0: [TypeAccess] String +# 19| 3: [Parameter] z +# 19| 0: [TypeAccess] String +# 19| 5: [BlockStmt] { ... } +# 20| 0: [ExprStmt] ; +# 20| 0: [MethodAccess] sink(...) +# 20| -1: [TypeAccess] TestKt +# 20| 0: [ExtensionReceiverAccess] this +# 21| 1: [ExprStmt] ; +# 21| 0: [MethodAccess] sink(...) +# 21| -1: [TypeAccess] TestKt +# 21| 0: [VarAccess] y +# 19| 3: [Method] f$default +# 19| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 19| 0: [Parameter] p0 +# 19| 0: [TypeAccess] String +# 19| 1: [Parameter] p1 +# 19| 0: [TypeAccess] TestExtensionMember +# 19| 2: [Parameter] p2 +# 19| 0: [TypeAccess] String +# 19| 3: [Parameter] p3 +# 19| 0: [TypeAccess] String +# 19| 4: [Parameter] p4 +# 19| 0: [TypeAccess] String +# 19| 5: [Parameter] p5 +# 19| 0: [TypeAccess] int +# 19| 6: [Parameter] p6 +# 19| 0: [TypeAccess] Object +# 19| 5: [BlockStmt] { ... } +# 19| 0: [IfStmt] if (...) +# 19| 0: [EQExpr] ... == ... +# 19| 0: [AndBitwiseExpr] ... & ... +# 19| 0: [IntegerLiteral] 2 +# 19| 1: [VarAccess] p5 +# 19| 1: [IntegerLiteral] 0 +# 19| 1: [ExprStmt] ; +# 19| 0: [AssignExpr] ...=... +# 19| 0: [VarAccess] p3 +# 19| 1: [VarAccess] p2 +# 19| 1: [IfStmt] if (...) +# 19| 0: [EQExpr] ... == ... +# 19| 0: [AndBitwiseExpr] ... & ... +# 19| 0: [IntegerLiteral] 4 +# 19| 1: [VarAccess] p5 +# 19| 1: [IntegerLiteral] 0 +# 19| 1: [ExprStmt] ; +# 19| 0: [AssignExpr] ...=... +# 19| 0: [VarAccess] p4 +# 19| 1: [StringLiteral] hello world +# 19| 2: [ReturnStmt] return ... +# 19| 0: [MethodAccess] f(...) +# 19| -1: [VarAccess] p1 +# 19| 0: [VarAccess] p0 +# 19| 1: [VarAccess] p2 +# 19| 2: [VarAccess] p3 +# 19| 3: [VarAccess] p4 +# 24| 4: [Method] user +# 24| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 24| 0: [Parameter] sunk +# 24| 0: [TypeAccess] String +# 24| 5: [BlockStmt] { ... } +# 25| 0: [ExprStmt] ; +# 25| 0: [MethodAccess] f$default(...) +# 25| -1: [TypeAccess] TestExtensionMember +# 25| 0: [VarAccess] sunk +# 25| 1: [ThisAccess] this +# 25| 2: [StringLiteral] extension sunk +# 1| 3: [NullLiteral] null +# 1| 4: [NullLiteral] null +# 1| 5: [IntegerLiteral] 1 +# 1| 6: [NullLiteral] null +# 26| 1: [ExprStmt] ; +# 26| 0: [MethodAccess] f$default(...) +# 26| -1: [TypeAccess] TestExtensionMember +# 26| 0: [VarAccess] sunk +# 26| 1: [ThisAccess] this +# 26| 2: [StringLiteral] extension sunk fp +# 26| 3: [StringLiteral] extension sunk 2 +# 1| 4: [NullLiteral] null +# 1| 5: [IntegerLiteral] 3 +# 1| 6: [NullLiteral] null +# 27| 2: [ExprStmt] ; +# 27| 0: [MethodAccess] f(...) +# 27| -1: [ThisAccess] this +# 27| 0: [VarAccess] sunk +# 27| 1: [StringLiteral] not sunk +# 27| 2: [StringLiteral] extension sunk 3 +# 27| 3: [StringLiteral] not sunk +# 32| 4: [Class] TestStaticMember +# 32| 1: [Constructor] TestStaticMember +# 32| 5: [BlockStmt] { ... } +# 32| 0: [SuperConstructorInvocationStmt] super(...) +# 32| 1: [BlockStmt] { ... } +# 34| 2: [Method] f +# 34| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 34| 0: [Parameter] x +# 34| 0: [TypeAccess] String +# 34| 1: [Parameter] y +# 34| 0: [TypeAccess] String +# 34| 2: [Parameter] z +# 34| 0: [TypeAccess] String +# 34| 5: [BlockStmt] { ... } +# 35| 0: [ExprStmt] ; +# 35| 0: [MethodAccess] sink(...) +# 35| -1: [TypeAccess] TestKt +# 35| 0: [VarAccess] y +# 34| 3: [Method] f$default +# 34| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 34| 0: [Parameter] p0 +# 34| 0: [TypeAccess] String +# 34| 1: [Parameter] p1 +# 34| 0: [TypeAccess] String +# 34| 2: [Parameter] p2 +# 34| 0: [TypeAccess] String +# 34| 3: [Parameter] p3 +# 34| 0: [TypeAccess] int +# 34| 4: [Parameter] p4 +# 34| 0: [TypeAccess] Object +# 34| 5: [BlockStmt] { ... } +# 34| 0: [IfStmt] if (...) +# 34| 0: [EQExpr] ... == ... +# 34| 0: [AndBitwiseExpr] ... & ... +# 34| 0: [IntegerLiteral] 2 +# 34| 1: [VarAccess] p3 +# 34| 1: [IntegerLiteral] 0 +# 34| 1: [ExprStmt] ; +# 34| 0: [AssignExpr] ...=... +# 34| 0: [VarAccess] p1 +# 34| 1: [VarAccess] p0 +# 34| 1: [IfStmt] if (...) +# 34| 0: [EQExpr] ... == ... +# 34| 0: [AndBitwiseExpr] ... & ... +# 34| 0: [IntegerLiteral] 4 +# 34| 1: [VarAccess] p3 +# 34| 1: [IntegerLiteral] 0 +# 34| 1: [ExprStmt] ; +# 34| 0: [AssignExpr] ...=... +# 34| 0: [VarAccess] p2 +# 34| 1: [StringLiteral] hello world +# 34| 2: [ReturnStmt] return ... +# 34| 0: [MethodAccess] f(...) +# 34| -1: [TypeAccess] TestStaticMember +# 34| 0: [VarAccess] p0 +# 34| 1: [VarAccess] p1 +# 34| 2: [VarAccess] p2 +# 38| 4: [Method] user +# 38| 3: [TypeAccess] Unit +# 38| 5: [BlockStmt] { ... } +# 39| 0: [ExprStmt] ; +# 39| 0: [MethodAccess] f$default(...) +# 39| -1: [TypeAccess] TestStaticMember +# 39| 0: [StringLiteral] static sunk +# 1| 1: [NullLiteral] null +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 1 +# 1| 4: [NullLiteral] null +# 40| 1: [ExprStmt] ; +# 40| 0: [MethodAccess] f$default(...) +# 40| -1: [TypeAccess] TestStaticMember +# 40| 0: [StringLiteral] static sunk fp +# 40| 1: [StringLiteral] static sunk 2 +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 3 +# 1| 4: [NullLiteral] null +# 41| 2: [ExprStmt] ; +# 41| 0: [MethodAccess] f(...) +# 41| -1: [TypeAccess] TestStaticMember +# 41| 0: [StringLiteral] not sunk +# 41| 1: [StringLiteral] static sunk 3 +# 41| 2: [StringLiteral] not sunk +# 46| 5: [Class] ExtendMe +# 46| 1: [Constructor] ExtendMe +# 46| 5: [BlockStmt] { ... } +# 46| 0: [SuperConstructorInvocationStmt] super(...) +# 46| 1: [BlockStmt] { ... } +# 48| 2: [Method] f +# 48| 3: [TypeAccess] String +#-----| 4: (Parameters) +# 48| 0: [Parameter] x +# 48| 0: [TypeAccess] String +# 48| 5: [BlockStmt] { ... } +# 48| 0: [ReturnStmt] return ... +# 48| 0: [VarAccess] x +# 52| 6: [Class] TestReceiverReferences +# 52| 1: [Constructor] TestReceiverReferences +# 52| 5: [BlockStmt] { ... } +# 52| 0: [SuperConstructorInvocationStmt] super(...) +# 52| 1: [BlockStmt] { ... } +# 54| 2: [Method] g +# 54| 3: [TypeAccess] String +#-----| 4: (Parameters) +# 54| 0: [Parameter] x +# 54| 0: [TypeAccess] String +# 54| 5: [BlockStmt] { ... } +# 54| 0: [ReturnStmt] return ... +# 54| 0: [VarAccess] x +# 56| 3: [ExtensionMethod] test +# 56| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 56| 0: [Parameter] +# 56| 0: [TypeAccess] ExtendMe +# 56| 1: [Parameter] x +# 56| 0: [TypeAccess] String +# 56| 2: [Parameter] y +# 56| 0: [TypeAccess] String +# 56| 3: [Parameter] z +# 56| 0: [TypeAccess] String +# 56| 5: [BlockStmt] { ... } +# 57| 0: [ExprStmt] ; +# 57| 0: [MethodAccess] sink(...) +# 57| -1: [TypeAccess] TestKt +# 57| 0: [VarAccess] y +# 56| 4: [Method] test$default +# 56| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 56| 0: [Parameter] p0 +# 56| 0: [TypeAccess] ExtendMe +# 56| 1: [Parameter] p1 +# 56| 0: [TypeAccess] TestReceiverReferences +# 56| 2: [Parameter] p2 +# 56| 0: [TypeAccess] String +# 56| 3: [Parameter] p3 +# 56| 0: [TypeAccess] String +# 56| 4: [Parameter] p4 +# 56| 0: [TypeAccess] String +# 56| 5: [Parameter] p5 +# 56| 0: [TypeAccess] int +# 56| 6: [Parameter] p6 +# 56| 0: [TypeAccess] Object +# 56| 5: [BlockStmt] { ... } +# 56| 0: [IfStmt] if (...) +# 56| 0: [EQExpr] ... == ... +# 56| 0: [AndBitwiseExpr] ... & ... +# 56| 0: [IntegerLiteral] 2 +# 56| 1: [VarAccess] p5 +# 56| 1: [IntegerLiteral] 0 +# 56| 1: [ExprStmt] ; +# 56| 0: [AssignExpr] ...=... +# 56| 0: [VarAccess] p3 +# 56| 1: [MethodAccess] f(...) +# 56| -1: [VarAccess] p0 +# 56| 0: [MethodAccess] g(...) +# 56| -1: [VarAccess] p1 +# 56| 0: [VarAccess] p2 +# 56| 1: [IfStmt] if (...) +# 56| 0: [EQExpr] ... == ... +# 56| 0: [AndBitwiseExpr] ... & ... +# 56| 0: [IntegerLiteral] 4 +# 56| 1: [VarAccess] p5 +# 56| 1: [IntegerLiteral] 0 +# 56| 1: [ExprStmt] ; +# 56| 0: [AssignExpr] ...=... +# 56| 0: [VarAccess] p4 +# 56| 1: [StringLiteral] hello world +# 56| 2: [ReturnStmt] return ... +# 56| 0: [MethodAccess] test(...) +# 56| -1: [VarAccess] p1 +# 56| 0: [VarAccess] p0 +# 56| 1: [VarAccess] p2 +# 56| 2: [VarAccess] p3 +# 56| 3: [VarAccess] p4 +# 60| 5: [Method] user +# 60| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 60| 0: [Parameter] t +# 60| 0: [TypeAccess] ExtendMe +# 60| 5: [BlockStmt] { ... } +# 61| 0: [ExprStmt] ; +# 61| 0: [MethodAccess] test$default(...) +# 61| -1: [TypeAccess] TestReceiverReferences +# 61| 0: [VarAccess] t +# 61| 1: [ThisAccess] this +# 61| 2: [StringLiteral] receiver refs sunk +# 1| 3: [NullLiteral] null +# 1| 4: [NullLiteral] null +# 1| 5: [IntegerLiteral] 1 +# 1| 6: [NullLiteral] null +# 62| 1: [ExprStmt] ; +# 62| 0: [MethodAccess] test$default(...) +# 62| -1: [TypeAccess] TestReceiverReferences +# 62| 0: [VarAccess] t +# 62| 1: [ThisAccess] this +# 62| 2: [StringLiteral] receiver refs sunk fp +# 62| 3: [StringLiteral] receiver refs sunk 2 +# 1| 4: [NullLiteral] null +# 1| 5: [IntegerLiteral] 3 +# 1| 6: [NullLiteral] null +# 63| 2: [ExprStmt] ; +# 63| 0: [MethodAccess] test(...) +# 63| -1: [ThisAccess] this +# 63| 0: [VarAccess] t +# 63| 1: [StringLiteral] not sunk +# 63| 2: [StringLiteral] receiver refs sunk 3 +# 63| 3: [StringLiteral] not sunk +# 68| 7: [Class] TestConstructor +# 68| 1: [Constructor] TestConstructor +#-----| 4: (Parameters) +# 68| 0: [Parameter] x +# 68| 0: [TypeAccess] String +# 68| 1: [Parameter] y +# 68| 0: [TypeAccess] String +# 68| 2: [Parameter] z +# 68| 0: [TypeAccess] String +# 68| 5: [BlockStmt] { ... } +# 68| 0: [SuperConstructorInvocationStmt] super(...) +# 68| 1: [BlockStmt] { ... } +# 71| 0: [ExprStmt] ; +# 71| 0: [MethodAccess] sink(...) +# 71| -1: [TypeAccess] TestKt +# 71| 0: [VarAccess] y +# 68| 2: [Constructor] TestConstructor +#-----| 4: (Parameters) +# 68| 0: [Parameter] p0 +# 68| 0: [TypeAccess] String +# 68| 1: [Parameter] p1 +# 68| 0: [TypeAccess] String +# 68| 2: [Parameter] p2 +# 68| 0: [TypeAccess] String +# 68| 3: [Parameter] p3 +# 68| 0: [TypeAccess] int +# 68| 4: [Parameter] p4 +# 68| 0: [TypeAccess] DefaultConstructorMarker +# 68| 5: [BlockStmt] { ... } +# 68| 0: [IfStmt] if (...) +# 68| 0: [EQExpr] ... == ... +# 68| 0: [AndBitwiseExpr] ... & ... +# 68| 0: [IntegerLiteral] 2 +# 68| 1: [VarAccess] p3 +# 68| 1: [IntegerLiteral] 0 +# 68| 1: [ExprStmt] ; +# 68| 0: [AssignExpr] ...=... +# 68| 0: [VarAccess] p1 +# 68| 1: [VarAccess] p0 +# 68| 1: [IfStmt] if (...) +# 68| 0: [EQExpr] ... == ... +# 68| 0: [AndBitwiseExpr] ... & ... +# 68| 0: [IntegerLiteral] 4 +# 68| 1: [VarAccess] p3 +# 68| 1: [IntegerLiteral] 0 +# 68| 1: [ExprStmt] ; +# 68| 0: [AssignExpr] ...=... +# 68| 0: [VarAccess] p2 +# 68| 1: [StringLiteral] hello world +# 68| 2: [ThisConstructorInvocationStmt] this(...) +# 68| 0: [VarAccess] p0 +# 68| 1: [VarAccess] p1 +# 68| 2: [VarAccess] p2 +# 74| 3: [Method] user +# 74| 3: [TypeAccess] Unit +# 74| 5: [BlockStmt] { ... } +# 75| 0: [ExprStmt] ; +# 75| 0: [ImplicitCoercionToUnitExpr] +# 75| 0: [TypeAccess] Unit +# 75| 1: [ClassInstanceExpr] new TestConstructor(...) +# 75| -3: [TypeAccess] TestConstructor +# 75| 0: [StringLiteral] constructor sunk +# 1| 1: [NullLiteral] null +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 1 +# 1| 4: [NullLiteral] null +# 76| 1: [ExprStmt] ; +# 76| 0: [ImplicitCoercionToUnitExpr] +# 76| 0: [TypeAccess] Unit +# 76| 1: [ClassInstanceExpr] new TestConstructor(...) +# 76| -3: [TypeAccess] TestConstructor +# 76| 0: [StringLiteral] constructor sunk fp +# 76| 1: [StringLiteral] constructor sunk 2 +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 3 +# 1| 4: [NullLiteral] null +# 77| 2: [ExprStmt] ; +# 77| 0: [ImplicitCoercionToUnitExpr] +# 77| 0: [TypeAccess] Unit +# 77| 1: [ClassInstanceExpr] new TestConstructor(...) +# 77| -3: [TypeAccess] TestConstructor +# 77| 0: [StringLiteral] not sunk +# 77| 1: [StringLiteral] constructor sunk 3 +# 77| 2: [StringLiteral] not sunk +# 82| 8: [Class] TestLocal +# 82| 1: [Constructor] TestLocal +# 82| 5: [BlockStmt] { ... } +# 82| 0: [SuperConstructorInvocationStmt] super(...) +# 82| 1: [BlockStmt] { ... } +# 84| 2: [Method] enclosing +# 84| 3: [TypeAccess] Unit +# 84| 5: [BlockStmt] { ... } +# 86| 0: [LocalTypeDeclStmt] class ... +# 86| 0: [LocalClass] +# 86| 1: [Constructor] +# 86| 5: [BlockStmt] { ... } +# 86| 0: [SuperConstructorInvocationStmt] super(...) +# 86| 2: [Method] f +# 86| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 86| 0: [Parameter] x +# 86| 0: [TypeAccess] String +# 86| 1: [Parameter] y +# 86| 0: [TypeAccess] String +# 86| 2: [Parameter] z +# 86| 0: [TypeAccess] String +# 86| 5: [BlockStmt] { ... } +# 87| 0: [ExprStmt] ; +# 87| 0: [MethodAccess] sink(...) +# 87| -1: [TypeAccess] TestKt +# 87| 0: [VarAccess] y +# 86| 3: [Method] f$default +# 86| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 86| 0: [Parameter] p0 +# 86| 0: [TypeAccess] String +# 86| 1: [Parameter] p1 +# 86| 0: [TypeAccess] String +# 86| 2: [Parameter] p2 +# 86| 0: [TypeAccess] String +# 86| 3: [Parameter] p3 +# 86| 0: [TypeAccess] int +# 86| 4: [Parameter] p4 +# 86| 0: [TypeAccess] Object +# 86| 5: [BlockStmt] { ... } +# 86| 0: [IfStmt] if (...) +# 86| 0: [EQExpr] ... == ... +# 86| 0: [AndBitwiseExpr] ... & ... +# 86| 0: [IntegerLiteral] 2 +# 86| 1: [VarAccess] p3 +# 86| 1: [IntegerLiteral] 0 +# 86| 1: [ExprStmt] ; +# 86| 0: [AssignExpr] ...=... +# 86| 0: [VarAccess] p1 +# 86| 1: [VarAccess] p0 +# 86| 1: [IfStmt] if (...) +# 86| 0: [EQExpr] ... == ... +# 86| 0: [AndBitwiseExpr] ... & ... +# 86| 0: [IntegerLiteral] 4 +# 86| 1: [VarAccess] p3 +# 86| 1: [IntegerLiteral] 0 +# 86| 1: [ExprStmt] ; +# 86| 0: [AssignExpr] ...=... +# 86| 0: [VarAccess] p2 +# 86| 1: [StringLiteral] hello world +# 86| 2: [ReturnStmt] return ... +# 86| 0: [MethodAccess] f(...) +# 86| -1: [ClassInstanceExpr] new (...) +# 86| -3: [TypeAccess] Object +# 86| 0: [VarAccess] p0 +# 86| 1: [VarAccess] p1 +# 86| 2: [VarAccess] p2 +# 90| 1: [LocalTypeDeclStmt] class ... +# 90| 0: [LocalClass] +# 90| 1: [Constructor] +# 90| 5: [BlockStmt] { ... } +# 90| 0: [SuperConstructorInvocationStmt] super(...) +# 90| 2: [Method] user +# 90| 3: [TypeAccess] Unit +# 90| 5: [BlockStmt] { ... } +# 91| 0: [ExprStmt] ; +# 91| 0: [MethodAccess] f$default(...) +# 91| -1: [ClassInstanceExpr] new (...) +# 91| -3: [TypeAccess] Object +# 91| 0: [StringLiteral] local sunk +# 1| 1: [NullLiteral] null +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 1 +# 1| 4: [NullLiteral] null +# 92| 1: [ExprStmt] ; +# 92| 0: [MethodAccess] f$default(...) +# 92| -1: [ClassInstanceExpr] new (...) +# 92| -3: [TypeAccess] Object +# 92| 0: [StringLiteral] local sunk fp +# 92| 1: [StringLiteral] local sunk 2 +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 3 +# 1| 4: [NullLiteral] null +# 93| 2: [ExprStmt] ; +# 93| 0: [MethodAccess] f(...) +# 93| -1: [ClassInstanceExpr] new (...) +# 93| -3: [TypeAccess] Object +# 93| 0: [StringLiteral] not sunk +# 93| 1: [StringLiteral] local sunk 3 +# 93| 2: [StringLiteral] not sunk +# 100| 9: [Class] TestLocalClass +# 100| 1: [Constructor] TestLocalClass +# 100| 5: [BlockStmt] { ... } +# 100| 0: [SuperConstructorInvocationStmt] super(...) +# 100| 1: [BlockStmt] { ... } +# 102| 2: [Method] enclosingFunction +# 102| 3: [TypeAccess] Unit +# 102| 5: [BlockStmt] { ... } +# 104| 0: [LocalTypeDeclStmt] class ... +# 104| 0: [LocalClass] EnclosingLocalClass +# 104| 1: [Constructor] EnclosingLocalClass +# 104| 5: [BlockStmt] { ... } +# 104| 0: [SuperConstructorInvocationStmt] super(...) +# 104| 1: [BlockStmt] { ... } +# 106| 2: [Method] f +# 106| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 106| 0: [Parameter] x +# 106| 0: [TypeAccess] String +# 106| 1: [Parameter] y +# 106| 0: [TypeAccess] String +# 106| 2: [Parameter] z +# 106| 0: [TypeAccess] String +# 106| 5: [BlockStmt] { ... } +# 107| 0: [ExprStmt] ; +# 107| 0: [MethodAccess] sink(...) +# 107| -1: [TypeAccess] TestKt +# 107| 0: [VarAccess] y +# 106| 3: [Method] f$default +# 106| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 106| 0: [Parameter] p0 +# 106| 0: [TypeAccess] EnclosingLocalClass +# 106| 1: [Parameter] p1 +# 106| 0: [TypeAccess] String +# 106| 2: [Parameter] p2 +# 106| 0: [TypeAccess] String +# 106| 3: [Parameter] p3 +# 106| 0: [TypeAccess] String +# 106| 4: [Parameter] p4 +# 106| 0: [TypeAccess] int +# 106| 5: [Parameter] p5 +# 106| 0: [TypeAccess] Object +# 106| 5: [BlockStmt] { ... } +# 106| 0: [IfStmt] if (...) +# 106| 0: [EQExpr] ... == ... +# 106| 0: [AndBitwiseExpr] ... & ... +# 106| 0: [IntegerLiteral] 2 +# 106| 1: [VarAccess] p4 +# 106| 1: [IntegerLiteral] 0 +# 106| 1: [ExprStmt] ; +# 106| 0: [AssignExpr] ...=... +# 106| 0: [VarAccess] p2 +# 106| 1: [VarAccess] p1 +# 106| 1: [IfStmt] if (...) +# 106| 0: [EQExpr] ... == ... +# 106| 0: [AndBitwiseExpr] ... & ... +# 106| 0: [IntegerLiteral] 4 +# 106| 1: [VarAccess] p4 +# 106| 1: [IntegerLiteral] 0 +# 106| 1: [ExprStmt] ; +# 106| 0: [AssignExpr] ...=... +# 106| 0: [VarAccess] p3 +# 106| 1: [StringLiteral] hello world +# 106| 2: [ReturnStmt] return ... +# 106| 0: [MethodAccess] f(...) +# 106| -1: [VarAccess] p0 +# 106| 0: [VarAccess] p1 +# 106| 1: [VarAccess] p2 +# 106| 2: [VarAccess] p3 +# 110| 4: [Method] user +# 110| 3: [TypeAccess] Unit +# 110| 5: [BlockStmt] { ... } +# 111| 0: [ExprStmt] ; +# 111| 0: [MethodAccess] f$default(...) +# 111| -1: [TypeAccess] EnclosingLocalClass +# 111| 0: [ThisAccess] this +# 111| 1: [StringLiteral] local sunk +# 1| 2: [NullLiteral] null +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 1 +# 1| 5: [NullLiteral] null +# 112| 1: [ExprStmt] ; +# 112| 0: [MethodAccess] f$default(...) +# 112| -1: [TypeAccess] EnclosingLocalClass +# 112| 0: [ThisAccess] this +# 112| 1: [StringLiteral] local sunk fp +# 112| 2: [StringLiteral] local sunk 2 +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 3 +# 1| 5: [NullLiteral] null +# 113| 2: [ExprStmt] ; +# 113| 0: [MethodAccess] f(...) +# 113| -1: [ThisAccess] this +# 113| 0: [StringLiteral] not sunk +# 113| 1: [StringLiteral] local sunk 3 +# 113| 2: [StringLiteral] not sunk +# 122| 10: [Class,GenericType,ParameterizedType] TestGeneric +#-----| -2: (Generic Parameters) +# 122| 0: [TypeVariable] T +# 122| 1: [Constructor] TestGeneric +# 122| 5: [BlockStmt] { ... } +# 122| 0: [SuperConstructorInvocationStmt] super(...) +# 122| 1: [BlockStmt] { ... } +# 124| 2: [Method] f +# 124| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 124| 0: [Parameter] x +# 124| 0: [TypeAccess] T +# 124| 1: [Parameter] y +# 124| 0: [TypeAccess] T +# 124| 2: [Parameter] z +# 124| 0: [TypeAccess] T +# 124| 5: [BlockStmt] { ... } +# 125| 0: [ExprStmt] ; +# 125| 0: [MethodAccess] sink(...) +# 125| -1: [TypeAccess] TestKt +# 125| 0: [VarAccess] y +# 124| 3: [Method] f$default +# 124| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 124| 0: [Parameter] p0 +# 124| 0: [TypeAccess] TestGeneric<> +# 124| 1: [Parameter] p1 +# 124| 0: [TypeAccess] Object +# 124| 2: [Parameter] p2 +# 124| 0: [TypeAccess] Object +# 124| 3: [Parameter] p3 +# 124| 0: [TypeAccess] Object +# 124| 4: [Parameter] p4 +# 124| 0: [TypeAccess] int +# 124| 5: [Parameter] p5 +# 124| 0: [TypeAccess] Object +# 124| 5: [BlockStmt] { ... } +# 124| 0: [IfStmt] if (...) +# 124| 0: [EQExpr] ... == ... +# 124| 0: [AndBitwiseExpr] ... & ... +# 124| 0: [IntegerLiteral] 2 +# 124| 1: [VarAccess] p4 +# 124| 1: [IntegerLiteral] 0 +# 124| 1: [ExprStmt] ; +# 124| 0: [AssignExpr] ...=... +# 124| 0: [VarAccess] p2 +# 124| 1: [VarAccess] p1 +# 124| 1: [IfStmt] if (...) +# 124| 0: [EQExpr] ... == ... +# 124| 0: [AndBitwiseExpr] ... & ... +# 124| 0: [IntegerLiteral] 4 +# 124| 1: [VarAccess] p4 +# 124| 1: [IntegerLiteral] 0 +# 124| 1: [ExprStmt] ; +# 124| 0: [AssignExpr] ...=... +# 124| 0: [VarAccess] p3 +# 124| 1: [NullLiteral] null +# 124| 2: [ReturnStmt] return ... +# 124| 0: [MethodAccess] f(...) +# 124| -1: [VarAccess] p0 +# 124| 0: [VarAccess] p1 +# 124| 1: [VarAccess] p2 +# 124| 2: [VarAccess] p3 +# 128| 4: [Method] user +# 128| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 128| 0: [Parameter] tgs +# 128| 0: [TypeAccess] TestGeneric +# 128| 0: [TypeAccess] String +# 128| 1: [Parameter] tcs +# 128| 0: [TypeAccess] TestGeneric +# 128| 0: [TypeAccess] CharSequence +# 128| 5: [BlockStmt] { ... } +# 129| 0: [ExprStmt] ; +# 129| 0: [MethodAccess] f$default(...) +# 129| -1: [TypeAccess] TestGeneric<> +# 129| 0: [VarAccess] tgs +# 129| 1: [StringLiteral] generic sunk +# 1| 2: [NullLiteral] null +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 1 +# 1| 5: [NullLiteral] null +# 130| 1: [ExprStmt] ; +# 130| 0: [MethodAccess] f$default(...) +# 130| -1: [TypeAccess] TestGeneric<> +# 130| 0: [VarAccess] tcs +# 130| 1: [StringLiteral] generic sunk fp +# 130| 2: [StringLiteral] generic sunk 2 +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 3 +# 1| 5: [NullLiteral] null +# 131| 2: [ExprStmt] ; +# 131| 0: [MethodAccess] f(...) +# 131| -1: [VarAccess] tgs +# 131| 0: [StringLiteral] not sunk +# 131| 1: [StringLiteral] generic sunk 3 +# 131| 2: [StringLiteral] not sunk +# 132| 3: [ExprStmt] ; +# 132| 0: [MethodAccess] f(...) +# 132| -1: [VarAccess] tcs +# 132| 0: [StringLiteral] not sunk +# 132| 1: [StringLiteral] generic sunk 3 +# 132| 2: [StringLiteral] not sunk +# 135| 5: [Method] testReturn +# 135| 3: [TypeAccess] T +#-----| 4: (Parameters) +# 135| 0: [Parameter] t1 +# 135| 0: [TypeAccess] T +# 135| 1: [Parameter] t2 +# 135| 0: [TypeAccess] T +# 135| 5: [BlockStmt] { ... } +# 135| 0: [ReturnStmt] return ... +# 135| 0: [VarAccess] t1 +# 135| 6: [Method] testReturn$default +# 135| 3: [TypeAccess] Object +#-----| 4: (Parameters) +# 135| 0: [Parameter] p0 +# 135| 0: [TypeAccess] TestGeneric<> +# 135| 1: [Parameter] p1 +# 135| 0: [TypeAccess] Object +# 135| 2: [Parameter] p2 +# 135| 0: [TypeAccess] Object +# 135| 3: [Parameter] p3 +# 135| 0: [TypeAccess] int +# 135| 4: [Parameter] p4 +# 135| 0: [TypeAccess] Object +# 135| 5: [BlockStmt] { ... } +# 135| 0: [IfStmt] if (...) +# 135| 0: [EQExpr] ... == ... +# 135| 0: [AndBitwiseExpr] ... & ... +# 135| 0: [IntegerLiteral] 2 +# 135| 1: [VarAccess] p3 +# 135| 1: [IntegerLiteral] 0 +# 135| 1: [ExprStmt] ; +# 135| 0: [AssignExpr] ...=... +# 135| 0: [VarAccess] p2 +# 135| 1: [NullLiteral] null +# 135| 1: [ReturnStmt] return ... +# 135| 0: [MethodAccess] testReturn(...) +# 135| -1: [VarAccess] p0 +# 135| 0: [VarAccess] p1 +# 135| 1: [VarAccess] p2 +# 137| 7: [Method] testReturnUser +# 137| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 137| 0: [Parameter] tgs +# 137| 0: [TypeAccess] TestGeneric +# 137| 0: [TypeAccess] String +# 137| 5: [BlockStmt] { ... } +# 138| 0: [ExprStmt] ; +# 138| 0: [MethodAccess] sink(...) +# 138| -1: [TypeAccess] TestKt +# 138| 0: [MethodAccess] testReturn$default(...) +# 138| -1: [TypeAccess] TestGeneric<> +# 138| 0: [VarAccess] tgs +# 138| 1: [StringLiteral] sunk return value +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 1 +# 1| 4: [NullLiteral] null diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.qlref b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.qlref new file mode 100644 index 00000000000..c7fd5faf239 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/java/PrintAst.ql \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.expected new file mode 100644 index 00000000000..37b80612273 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.expected @@ -0,0 +1,2 @@ +shouldBeSunkButIsnt +shouldntBeSunkButIs diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.ql b/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.ql new file mode 100644 index 00000000000..28151ecdc85 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.ql @@ -0,0 +1,34 @@ +import java +import semmle.code.java.dataflow.DataFlow + +class ShouldNotBeSunk extends StringLiteral { + ShouldNotBeSunk() { this.getValue().matches("%not sunk%") } +} + +class ShouldBeSunk extends StringLiteral { + ShouldBeSunk() { + this.getValue().matches("%sunk%") and + not this instanceof ShouldNotBeSunk + } +} + +class Config extends DataFlow::Configuration { + Config() { this = "Config" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr() instanceof ShouldBeSunk or + n.asExpr() instanceof ShouldNotBeSunk + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().getName() = "sink" + } +} + +predicate isSunk(StringLiteral sl) { + exists(Config c, DataFlow::Node source | c.hasFlow(source, _) and sl = source.asExpr()) +} + +query predicate shouldBeSunkButIsnt(ShouldBeSunk src) { not isSunk(src) } + +query predicate shouldntBeSunkButIs(ShouldNotBeSunk src) { isSunk(src) } diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt new file mode 100644 index 00000000000..144664f0a07 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt @@ -0,0 +1,141 @@ +fun sink(a: Any?) { } + +class TestMember { + + fun f(x: String, y: String = x, z: String = "hello world") { + sink(y) + } + + fun user() { + f("member sunk") + f("member sunk fp", "member sunk 2") + f("not sunk", "member sunk 3", "not sunk") + } + +} + +class TestExtensionMember { + + fun String.f(x: String, y: String = x, z: String = "hello world") { + sink(this) + sink(y) + } + + fun user(sunk: String) { + sunk.f("extension sunk") + sunk.f("extension sunk fp", "extension sunk 2") + sunk.f("not sunk", "extension sunk 3", "not sunk") + } + +} + +object TestStaticMember { + + @JvmStatic fun f(x: String, y: String = x, z: String = "hello world") { + sink(y) + } + + fun user() { + f("static sunk") + f("static sunk fp", "static sunk 2") + f("not sunk", "static sunk 3", "not sunk") + } + +} + +class ExtendMe { + + fun f(x: String) = x + +} + +class TestReceiverReferences { + + fun g(x: String) = x + + fun ExtendMe.test(x: String, y: String = this.f(this@TestReceiverReferences.g(x)), z: String = "hello world") { + sink(y) + } + + fun user(t: ExtendMe) { + t.test("receiver refs sunk") + t.test("receiver refs sunk fp", "receiver refs sunk 2") + t.test("not sunk", "receiver refs sunk 3", "not sunk") + } + +} + +class TestConstructor(x: String, y: String = x, z: String = "hello world") { + + init { + sink(y) + } + + fun user() { + TestConstructor("constructor sunk") + TestConstructor("constructor sunk fp", "constructor sunk 2") + TestConstructor("not sunk", "constructor sunk 3", "not sunk") + } + +} + +class TestLocal { + + fun enclosing() { + + fun f(x: String, y: String = x, z: String = "hello world") { + sink(y) + } + + fun user() { + f("local sunk") + f("local sunk fp", "local sunk 2") + f("not sunk", "local sunk 3", "not sunk") + } + + } + +} + +class TestLocalClass { + + fun enclosingFunction() { + + class EnclosingLocalClass { + + fun f(x: String, y: String = x, z: String = "hello world") { + sink(y) + } + + fun user() { + f("local sunk") + f("local sunk fp", "local sunk 2") + f("not sunk", "local sunk 3", "not sunk") + } + + } + + } + +} + +class TestGeneric { + + fun f(x: T, y: T = x, z: T? = null) { + sink(y) + } + + fun user(tgs: TestGeneric, tcs: TestGeneric) { + tgs.f("generic sunk") + tcs.f("generic sunk fp", "generic sunk 2") + tgs.f("not sunk", "generic sunk 3", "not sunk") + tcs.f("not sunk", "generic sunk 3", "not sunk") + } + + fun testReturn(t1: T, t2: T? = null) = t1 + + fun testReturnUser(tgs: TestGeneric) { + sink(tgs.testReturn("sunk return value")) + } + +} From 6cc74da00431acc5ead87b8eba60f4c457a3e124 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 4 Oct 2022 17:21:21 +0100 Subject: [PATCH 051/107] Defaults function extraction: respect the extract-type-accesses flag --- .../src/main/kotlin/KotlinFileExtractor.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index d5615a1cfa9..8aec0a0acd7 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -835,12 +835,12 @@ open class KotlinFileExtractor( forceExtractFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses).also { // The defaults-forwarder function is a static utility, not a member, so we only need to extract this for the unspecialised instance of this class. if (classTypeArgsIncludingOuterClasses.isNullOrEmpty()) - extractDefaultsFunction(f, parentId, extractBody) + extractDefaultsFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses) extractGeneratedOverloads(f, parentId, null, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses) } } - private fun extractDefaultsFunction(f: IrFunction, parentId: Label, extractBody: Boolean) { + private fun extractDefaultsFunction(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean) { if (f.valueParameters.none { it.defaultValue != null }) return @@ -852,7 +852,8 @@ open class KotlinFileExtractor( val allParamTypeResults = parameterTypes.mapIndexed { i, paramType -> val paramId = tw.getLabelFor(getValueParameterLabel(id, i)) extractValueParameter(paramId, paramType, "p$i", locId, id, i, paramId, isVararg = false, syntheticParameterNames = true, isCrossinline = false, isNoinline = false).also { - extractTypeAccess(useType(paramType), locId, paramId, -1) + if (extractMethodAndParameterTypeAccesses) + extractTypeAccess(useType(paramType), locId, paramId, -1) } } val paramsSignature = allParamTypeResults.joinToString(separator = ",", prefix = "(", postfix = ")") { it.javaResult.signature } @@ -863,7 +864,7 @@ open class KotlinFileExtractor( extractConstructor(constrId, shortName, paramsSignature, parentId, constrId) } else { val methodId = id.cast() - extractMethod(methodId, locId, shortName, erase(f.returnType), paramsSignature, parentId, methodId, origin = null, extractTypeAccess = true) + extractMethod(methodId, locId, shortName, erase(f.returnType), paramsSignature, parentId, methodId, origin = null, extractTypeAccess = extractMethodAndParameterTypeAccesses) addModifiers(id, "static") } tw.writeHasLocation(id, locId) From 720cf5682b4fb83d80b16b7d2bcb1534a32bd401 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 4 Oct 2022 17:21:53 +0100 Subject: [PATCH 052/107] Exclude enum constructor invocations from defaults handling These seem to provide null arguments even though the constructor doesn't provide defaults, presumably for completion by a later compiler phase. --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 8aec0a0acd7..23b7af20659 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -2938,7 +2938,9 @@ open class KotlinFileExtractor( } val locId = tw.getLocation(e) val valueArgs = (0 until e.valueArgumentsCount).map { e.getValueArgument(it) } - val anyDefaultArgs = valueArgs.any { it == null } + // For now, don't try to use default methods for enum constructor calls, + // which have null arguments even though the parameters don't give default values. + val anyDefaultArgs = e !is IrEnumConstructorCall && valueArgs.any { it == null } val id = if (anyDefaultArgs) { extractNewExpr(getDefaultsMethodLabel(e.symbol.owner).cast(), type, locId, parent, idx, callable, enclosingStmt).also { extractDefaultsCallArguments(it, e.symbol.owner, callable, enclosingStmt, valueArgs, null, null) From 6119670be88cbf7a55ef85d1c60be136a2d5030f Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 4 Oct 2022 17:22:57 +0100 Subject: [PATCH 053/107] Suppress use of function type parameters in the context of building a $defaults method These methods have erased signatures and no type parameters, so anything that refers to one must itself be erased. For signatures this would be easy, but for potentially deep default expressions these types can occur in various places and need erasing at each occurence. --- .../src/main/kotlin/KotlinFileExtractor.kt | 4 ++-- .../src/main/kotlin/KotlinUsesExtractor.kt | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 23b7af20659..b03c84af571 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -878,7 +878,7 @@ open class KotlinFileExtractor( // n + o'th parameter, where `o` is the parameter offset caused by adding any dispatch receiver to the parameter list. // Note we don't need to add the extension receiver here because `useValueParameter` always assumes an extension receiver // will be prepended if one exists. - DeclarationStackAdjuster(f, OverriddenFunctionAttributes(id, id, locId, nonSyntheticParams)).use { + DeclarationStackAdjuster(f, OverriddenFunctionAttributes(id, id, locId, nonSyntheticParams, typeParameters = listOf())).use { val realParamsVarId = getValueParameterLabel(id, parameterTypes.size - 2) val intType = pluginContext.irBuiltIns.intType val paramIdxOffset = listOf(dispatchReceiver, f.extensionReceiverParameter).count { it != null } @@ -5363,7 +5363,7 @@ open class KotlinFileExtractor( stack.firstOrNull { it.first == f } ?.second } - data class OverriddenFunctionAttributes(val id: Label? = null, val sourceDeclarationId: Label? = null, val sourceLoc: Label? = null, val valueParameters: List? = null) + data class OverriddenFunctionAttributes(val id: Label? = null, val sourceDeclarationId: Label? = null, val sourceLoc: Label? = null, val valueParameters: List? = null, val typeParameters: List? = null) private fun peekDeclStackAsDeclarationParent(elementToReportOn: IrElement): IrDeclarationParent? { val trapWriter = tw diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index 5873b06c280..3d3bc361ae1 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -658,6 +658,19 @@ open class KotlinUsesExtractor( RETURN, GENERIC_ARGUMENT, OTHER } + private fun isOnDeclarationStackWithoutTypeParameters(f: IrFunction) = + this is KotlinFileExtractor && this.declarationStack.findOverriddenAttributes(f)?.typeParameters?.isEmpty() == true + + private fun isUnavailableTypeParameter(t: IrType) = + t is IrSimpleType && t.classifier.owner.let { owner -> + owner is IrTypeParameter && owner.parent.let { parent -> + parent is IrFunction && isOnDeclarationStackWithoutTypeParameters(parent) + } + } + + private fun argIsUnavailableTypeParameter(t: IrTypeArgument) = + t is IrTypeProjection && isUnavailableTypeParameter(t.type) + private fun useSimpleType(s: IrSimpleType, context: TypeContext): TypeResults { if (s.abbreviation != null) { // TODO: Extract this information @@ -729,11 +742,13 @@ open class KotlinUsesExtractor( } owner is IrClass -> { - val args = if (s.isRawType()) null else s.arguments + val args = if (s.isRawType() || s.arguments.any { argIsUnavailableTypeParameter(it) }) null else s.arguments return useSimpleTypeClass(owner, args, s.isNullable()) } owner is IrTypeParameter -> { + if (isUnavailableTypeParameter(s)) + return useType(erase(s), context) val javaResult = useTypeParameter(owner) val aClassId = makeClass("kotlin", "TypeParam") // TODO: Wrong val kotlinResult = if (true) TypeResult(fakeKotlinType(), "TODO", "TODO") else From 03c895853bdcbbd24403610a5841b6263bd6fcd5 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 4 Oct 2022 17:24:52 +0100 Subject: [PATCH 054/107] Clarify test and accept test changes --- .../jvmoverloads-annotation/PrintAst.expected | 459 +++++++++++++++++- .../jvmoverloads-annotation/test.expected | 9 + .../jvmoverloads_flow/test.expected | 48 +- .../library-tests/jvmoverloads_flow/test.ql | 2 +- 4 files changed, 479 insertions(+), 39 deletions(-) diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected index 44e1e5f5950..4c7b75edc3a 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected @@ -69,6 +69,56 @@ test.kt: # 45| 5: [BlockStmt] { ... } # 45| 0: [ReturnStmt] return ... # 45| 0: [VarAccess] a +# 45| 5: [Method] testExtensionFunction$default +# 45| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 45| 0: [Parameter] p0 +# 45| 0: [TypeAccess] Test +# 45| 1: [Parameter] p1 +# 45| 0: [TypeAccess] int +# 45| 2: [Parameter] p2 +# 45| 0: [TypeAccess] String +# 45| 3: [Parameter] p3 +# 45| 0: [TypeAccess] double +# 45| 4: [Parameter] p4 +# 45| 0: [TypeAccess] float +# 45| 5: [Parameter] p5 +# 45| 0: [TypeAccess] boolean +# 45| 6: [Parameter] p6 +# 45| 0: [TypeAccess] int +# 45| 7: [Parameter] p7 +# 45| 0: [TypeAccess] Object +# 45| 5: [BlockStmt] { ... } +# 45| 0: [IfStmt] if (...) +# 45| 0: [EQExpr] ... == ... +# 45| 0: [AndBitwiseExpr] ... & ... +# 45| 0: [IntegerLiteral] 2 +# 45| 1: [VarAccess] p6 +# 45| 1: [IntegerLiteral] 0 +# 45| 1: [ExprStmt] ; +# 45| 0: [AssignExpr] ...=... +# 45| 0: [VarAccess] p2 +# 45| 1: [MethodAccess] getString(...) +# 45| -1: [TypeAccess] TestKt +# 45| 1: [IfStmt] if (...) +# 45| 0: [EQExpr] ... == ... +# 45| 0: [AndBitwiseExpr] ... & ... +# 45| 0: [IntegerLiteral] 8 +# 45| 1: [VarAccess] p6 +# 45| 1: [IntegerLiteral] 0 +# 45| 1: [ExprStmt] ; +# 45| 0: [AssignExpr] ...=... +# 45| 0: [VarAccess] p4 +# 45| 1: [FloatLiteral] 1.0 +# 45| 2: [ReturnStmt] return ... +# 45| 0: [MethodAccess] testExtensionFunction(...) +# 45| -1: [TypeAccess] TestKt +# 45| 0: [VarAccess] p0 +# 45| 1: [VarAccess] p1 +# 45| 2: [VarAccess] p2 +# 45| 3: [VarAccess] p3 +# 45| 4: [VarAccess] p4 +# 45| 5: [VarAccess] p5 # 3| 2: [Class] Test # 3| 1: [Constructor] Test # 3| 5: [BlockStmt] { ... } @@ -129,7 +179,54 @@ test.kt: # 6| 5: [BlockStmt] { ... } # 6| 0: [ReturnStmt] return ... # 6| 0: [VarAccess] a -# 9| 5: [Method] testMemberFunction +# 6| 5: [Method] testStaticFunction$default +# 6| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 6| 0: [Parameter] p0 +# 6| 0: [TypeAccess] int +# 6| 1: [Parameter] p1 +# 6| 0: [TypeAccess] String +# 6| 2: [Parameter] p2 +# 6| 0: [TypeAccess] double +# 6| 3: [Parameter] p3 +# 6| 0: [TypeAccess] float +# 6| 4: [Parameter] p4 +# 6| 0: [TypeAccess] boolean +# 6| 5: [Parameter] p5 +# 6| 0: [TypeAccess] int +# 6| 6: [Parameter] p6 +# 6| 0: [TypeAccess] Object +# 6| 5: [BlockStmt] { ... } +# 6| 0: [IfStmt] if (...) +# 6| 0: [EQExpr] ... == ... +# 6| 0: [AndBitwiseExpr] ... & ... +# 6| 0: [IntegerLiteral] 2 +# 6| 1: [VarAccess] p5 +# 6| 1: [IntegerLiteral] 0 +# 6| 1: [ExprStmt] ; +# 6| 0: [AssignExpr] ...=... +# 6| 0: [VarAccess] p1 +# 6| 1: [MethodAccess] getString(...) +# 6| -1: [TypeAccess] TestKt +# 6| 1: [IfStmt] if (...) +# 6| 0: [EQExpr] ... == ... +# 6| 0: [AndBitwiseExpr] ... & ... +# 6| 0: [IntegerLiteral] 8 +# 6| 1: [VarAccess] p5 +# 6| 1: [IntegerLiteral] 0 +# 6| 1: [ExprStmt] ; +# 6| 0: [AssignExpr] ...=... +# 6| 0: [VarAccess] p3 +# 6| 1: [FloatLiteral] 1.0 +# 6| 2: [ReturnStmt] return ... +# 6| 0: [MethodAccess] testStaticFunction(...) +# 6| -1: [TypeAccess] Test +# 6| 0: [VarAccess] p0 +# 6| 1: [VarAccess] p1 +# 6| 2: [VarAccess] p2 +# 6| 3: [VarAccess] p3 +# 6| 4: [VarAccess] p4 +# 9| 6: [Method] testMemberFunction # 9| 3: [TypeAccess] int #-----| 4: (Parameters) # 9| 0: [Parameter] a @@ -148,7 +245,7 @@ test.kt: # 9| 2: [VarAccess] c # 9| 3: [FloatLiteral] 1.0 # 9| 4: [VarAccess] e -# 9| 6: [Method] testMemberFunction +# 9| 7: [Method] testMemberFunction # 9| 3: [TypeAccess] int #-----| 4: (Parameters) # 9| 0: [Parameter] a @@ -168,7 +265,7 @@ test.kt: # 9| 2: [VarAccess] c # 9| 3: [FloatLiteral] 1.0 # 9| 4: [VarAccess] e -# 9| 7: [Method] testMemberFunction +# 9| 8: [Method] testMemberFunction # 9| 3: [TypeAccess] int #-----| 4: (Parameters) # 9| 0: [Parameter] a @@ -184,7 +281,56 @@ test.kt: # 9| 5: [BlockStmt] { ... } # 9| 0: [ReturnStmt] return ... # 9| 0: [VarAccess] a -# 12| 8: [ExtensionMethod] testMemberExtensionFunction +# 9| 9: [Method] testMemberFunction$default +# 9| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 9| 0: [Parameter] p0 +# 9| 0: [TypeAccess] Test +# 9| 1: [Parameter] p1 +# 9| 0: [TypeAccess] int +# 9| 2: [Parameter] p2 +# 9| 0: [TypeAccess] String +# 9| 3: [Parameter] p3 +# 9| 0: [TypeAccess] double +# 9| 4: [Parameter] p4 +# 9| 0: [TypeAccess] float +# 9| 5: [Parameter] p5 +# 9| 0: [TypeAccess] boolean +# 9| 6: [Parameter] p6 +# 9| 0: [TypeAccess] int +# 9| 7: [Parameter] p7 +# 9| 0: [TypeAccess] Object +# 9| 5: [BlockStmt] { ... } +# 9| 0: [IfStmt] if (...) +# 9| 0: [EQExpr] ... == ... +# 9| 0: [AndBitwiseExpr] ... & ... +# 9| 0: [IntegerLiteral] 2 +# 9| 1: [VarAccess] p6 +# 9| 1: [IntegerLiteral] 0 +# 9| 1: [ExprStmt] ; +# 9| 0: [AssignExpr] ...=... +# 9| 0: [VarAccess] p2 +# 9| 1: [MethodAccess] getString(...) +# 9| -1: [TypeAccess] TestKt +# 9| 1: [IfStmt] if (...) +# 9| 0: [EQExpr] ... == ... +# 9| 0: [AndBitwiseExpr] ... & ... +# 9| 0: [IntegerLiteral] 8 +# 9| 1: [VarAccess] p6 +# 9| 1: [IntegerLiteral] 0 +# 9| 1: [ExprStmt] ; +# 9| 0: [AssignExpr] ...=... +# 9| 0: [VarAccess] p4 +# 9| 1: [FloatLiteral] 1.0 +# 9| 2: [ReturnStmt] return ... +# 9| 0: [MethodAccess] testMemberFunction(...) +# 9| -1: [VarAccess] p0 +# 9| 0: [VarAccess] p1 +# 9| 1: [VarAccess] p2 +# 9| 2: [VarAccess] p3 +# 9| 3: [VarAccess] p4 +# 9| 4: [VarAccess] p5 +# 12| 10: [ExtensionMethod] testMemberExtensionFunction # 12| 3: [TypeAccess] int #-----| 4: (Parameters) # 12| 0: [Parameter] @@ -206,7 +352,7 @@ test.kt: # 12| 3: [VarAccess] c # 12| 4: [FloatLiteral] 1.0 # 12| 5: [VarAccess] e -# 12| 9: [ExtensionMethod] testMemberExtensionFunction +# 12| 11: [ExtensionMethod] testMemberExtensionFunction # 12| 3: [TypeAccess] int #-----| 4: (Parameters) # 12| 0: [Parameter] @@ -229,7 +375,7 @@ test.kt: # 12| 3: [VarAccess] c # 12| 4: [FloatLiteral] 1.0 # 12| 5: [VarAccess] e -# 12| 10: [ExtensionMethod] testMemberExtensionFunction +# 12| 12: [ExtensionMethod] testMemberExtensionFunction # 12| 3: [TypeAccess] int #-----| 4: (Parameters) # 12| 0: [Parameter] @@ -247,6 +393,58 @@ test.kt: # 12| 5: [BlockStmt] { ... } # 12| 0: [ReturnStmt] return ... # 12| 0: [VarAccess] a +# 12| 13: [Method] testMemberExtensionFunction$default +# 12| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 12| 0: [Parameter] p0 +# 12| 0: [TypeAccess] Test2 +# 12| 1: [Parameter] p1 +# 12| 0: [TypeAccess] Test +# 12| 2: [Parameter] p2 +# 12| 0: [TypeAccess] int +# 12| 3: [Parameter] p3 +# 12| 0: [TypeAccess] String +# 12| 4: [Parameter] p4 +# 12| 0: [TypeAccess] double +# 12| 5: [Parameter] p5 +# 12| 0: [TypeAccess] float +# 12| 6: [Parameter] p6 +# 12| 0: [TypeAccess] boolean +# 12| 7: [Parameter] p7 +# 12| 0: [TypeAccess] int +# 12| 8: [Parameter] p8 +# 12| 0: [TypeAccess] Object +# 12| 5: [BlockStmt] { ... } +# 12| 0: [IfStmt] if (...) +# 12| 0: [EQExpr] ... == ... +# 12| 0: [AndBitwiseExpr] ... & ... +# 12| 0: [IntegerLiteral] 2 +# 12| 1: [VarAccess] p7 +# 12| 1: [IntegerLiteral] 0 +# 12| 1: [ExprStmt] ; +# 12| 0: [AssignExpr] ...=... +# 12| 0: [VarAccess] p3 +# 12| 1: [MethodAccess] getString(...) +# 12| -1: [TypeAccess] TestKt +# 12| 1: [IfStmt] if (...) +# 12| 0: [EQExpr] ... == ... +# 12| 0: [AndBitwiseExpr] ... & ... +# 12| 0: [IntegerLiteral] 8 +# 12| 1: [VarAccess] p7 +# 12| 1: [IntegerLiteral] 0 +# 12| 1: [ExprStmt] ; +# 12| 0: [AssignExpr] ...=... +# 12| 0: [VarAccess] p5 +# 12| 1: [FloatLiteral] 1.0 +# 12| 2: [ReturnStmt] return ... +# 12| 0: [MethodAccess] testMemberExtensionFunction(...) +# 12| -1: [VarAccess] p1 +# 12| 0: [VarAccess] p0 +# 12| 1: [VarAccess] p2 +# 12| 2: [VarAccess] p3 +# 12| 3: [VarAccess] p4 +# 12| 4: [VarAccess] p5 +# 12| 5: [VarAccess] p6 # 16| 3: [Class] Test2 # 16| 1: [Constructor] Test2 #-----| 4: (Parameters) @@ -296,7 +494,51 @@ test.kt: # 16| 5: [BlockStmt] { ... } # 16| 0: [SuperConstructorInvocationStmt] super(...) # 16| 1: [BlockStmt] { ... } -# 18| 4: [Class] Companion +# 16| 4: [Constructor] Test2 +#-----| 4: (Parameters) +# 16| 0: [Parameter] p0 +# 16| 0: [TypeAccess] int +# 16| 1: [Parameter] p1 +# 16| 0: [TypeAccess] String +# 16| 2: [Parameter] p2 +# 16| 0: [TypeAccess] double +# 16| 3: [Parameter] p3 +# 16| 0: [TypeAccess] float +# 16| 4: [Parameter] p4 +# 16| 0: [TypeAccess] boolean +# 16| 5: [Parameter] p5 +# 16| 0: [TypeAccess] int +# 16| 6: [Parameter] p6 +# 16| 0: [TypeAccess] DefaultConstructorMarker +# 16| 5: [BlockStmt] { ... } +# 16| 0: [IfStmt] if (...) +# 16| 0: [EQExpr] ... == ... +# 16| 0: [AndBitwiseExpr] ... & ... +# 16| 0: [IntegerLiteral] 2 +# 16| 1: [VarAccess] p5 +# 16| 1: [IntegerLiteral] 0 +# 16| 1: [ExprStmt] ; +# 16| 0: [AssignExpr] ...=... +# 16| 0: [VarAccess] p1 +# 16| 1: [MethodAccess] getString(...) +# 16| -1: [TypeAccess] TestKt +# 16| 1: [IfStmt] if (...) +# 16| 0: [EQExpr] ... == ... +# 16| 0: [AndBitwiseExpr] ... & ... +# 16| 0: [IntegerLiteral] 8 +# 16| 1: [VarAccess] p5 +# 16| 1: [IntegerLiteral] 0 +# 16| 1: [ExprStmt] ; +# 16| 0: [AssignExpr] ...=... +# 16| 0: [VarAccess] p3 +# 16| 1: [FloatLiteral] 1.0 +# 16| 2: [ThisConstructorInvocationStmt] this(...) +# 16| 0: [VarAccess] p0 +# 16| 1: [VarAccess] p1 +# 16| 2: [VarAccess] p2 +# 16| 3: [VarAccess] p3 +# 16| 4: [VarAccess] p4 +# 18| 5: [Class] Companion # 18| 1: [Constructor] Companion # 18| 5: [BlockStmt] { ... } # 18| 0: [SuperConstructorInvocationStmt] super(...) @@ -356,7 +598,56 @@ test.kt: # 21| 5: [BlockStmt] { ... } # 21| 0: [ReturnStmt] return ... # 21| 0: [VarAccess] a -# 24| 5: [Method] testStaticCompanionFunction +# 21| 5: [Method] testCompanionFunction$default +# 21| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 21| 0: [Parameter] p0 +# 21| 0: [TypeAccess] Companion +# 21| 1: [Parameter] p1 +# 21| 0: [TypeAccess] int +# 21| 2: [Parameter] p2 +# 21| 0: [TypeAccess] String +# 21| 3: [Parameter] p3 +# 21| 0: [TypeAccess] double +# 21| 4: [Parameter] p4 +# 21| 0: [TypeAccess] float +# 21| 5: [Parameter] p5 +# 21| 0: [TypeAccess] boolean +# 21| 6: [Parameter] p6 +# 21| 0: [TypeAccess] int +# 21| 7: [Parameter] p7 +# 21| 0: [TypeAccess] Object +# 21| 5: [BlockStmt] { ... } +# 21| 0: [IfStmt] if (...) +# 21| 0: [EQExpr] ... == ... +# 21| 0: [AndBitwiseExpr] ... & ... +# 21| 0: [IntegerLiteral] 2 +# 21| 1: [VarAccess] p6 +# 21| 1: [IntegerLiteral] 0 +# 21| 1: [ExprStmt] ; +# 21| 0: [AssignExpr] ...=... +# 21| 0: [VarAccess] p2 +# 21| 1: [MethodAccess] getString(...) +# 21| -1: [TypeAccess] TestKt +# 21| 1: [IfStmt] if (...) +# 21| 0: [EQExpr] ... == ... +# 21| 0: [AndBitwiseExpr] ... & ... +# 21| 0: [IntegerLiteral] 8 +# 21| 1: [VarAccess] p6 +# 21| 1: [IntegerLiteral] 0 +# 21| 1: [ExprStmt] ; +# 21| 0: [AssignExpr] ...=... +# 21| 0: [VarAccess] p4 +# 21| 1: [FloatLiteral] 1.0 +# 21| 2: [ReturnStmt] return ... +# 21| 0: [MethodAccess] testCompanionFunction(...) +# 21| -1: [VarAccess] p0 +# 21| 0: [VarAccess] p1 +# 21| 1: [VarAccess] p2 +# 21| 2: [VarAccess] p3 +# 21| 3: [VarAccess] p4 +# 21| 4: [VarAccess] p5 +# 24| 6: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -375,7 +666,7 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [FloatLiteral] 1.0 # 24| 4: [VarAccess] e -# 24| 6: [Method] testStaticCompanionFunction +# 24| 7: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -395,7 +686,7 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [FloatLiteral] 1.0 # 24| 4: [VarAccess] e -# 24| 7: [Method] testStaticCompanionFunction +# 24| 8: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -411,7 +702,56 @@ test.kt: # 24| 5: [BlockStmt] { ... } # 24| 0: [ReturnStmt] return ... # 24| 0: [VarAccess] a -# 24| 5: [Method] testStaticCompanionFunction +# 24| 9: [Method] testStaticCompanionFunction$default +# 24| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 24| 0: [Parameter] p0 +# 24| 0: [TypeAccess] Companion +# 24| 1: [Parameter] p1 +# 24| 0: [TypeAccess] int +# 24| 2: [Parameter] p2 +# 24| 0: [TypeAccess] String +# 24| 3: [Parameter] p3 +# 24| 0: [TypeAccess] double +# 24| 4: [Parameter] p4 +# 24| 0: [TypeAccess] float +# 24| 5: [Parameter] p5 +# 24| 0: [TypeAccess] boolean +# 24| 6: [Parameter] p6 +# 24| 0: [TypeAccess] int +# 24| 7: [Parameter] p7 +# 24| 0: [TypeAccess] Object +# 24| 5: [BlockStmt] { ... } +# 24| 0: [IfStmt] if (...) +# 24| 0: [EQExpr] ... == ... +# 24| 0: [AndBitwiseExpr] ... & ... +# 24| 0: [IntegerLiteral] 2 +# 24| 1: [VarAccess] p6 +# 24| 1: [IntegerLiteral] 0 +# 24| 1: [ExprStmt] ; +# 24| 0: [AssignExpr] ...=... +# 24| 0: [VarAccess] p2 +# 24| 1: [MethodAccess] getString(...) +# 24| -1: [TypeAccess] TestKt +# 24| 1: [IfStmt] if (...) +# 24| 0: [EQExpr] ... == ... +# 24| 0: [AndBitwiseExpr] ... & ... +# 24| 0: [IntegerLiteral] 8 +# 24| 1: [VarAccess] p6 +# 24| 1: [IntegerLiteral] 0 +# 24| 1: [ExprStmt] ; +# 24| 0: [AssignExpr] ...=... +# 24| 0: [VarAccess] p4 +# 24| 1: [FloatLiteral] 1.0 +# 24| 2: [ReturnStmt] return ... +# 24| 0: [MethodAccess] testStaticCompanionFunction(...) +# 24| -1: [VarAccess] p0 +# 24| 0: [VarAccess] p1 +# 24| 1: [VarAccess] p2 +# 24| 2: [VarAccess] p3 +# 24| 3: [VarAccess] p4 +# 24| 4: [VarAccess] p5 +# 24| 6: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -430,7 +770,7 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [FloatLiteral] 1.0 # 24| 4: [VarAccess] e -# 24| 6: [Method] testStaticCompanionFunction +# 24| 7: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -450,7 +790,7 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [FloatLiteral] 1.0 # 24| 4: [VarAccess] e -# 24| 7: [Method] testStaticCompanionFunction +# 24| 8: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -515,7 +855,47 @@ test.kt: # 30| 5: [BlockStmt] { ... } # 30| 0: [SuperConstructorInvocationStmt] super(...) # 30| 1: [BlockStmt] { ... } -# 33| 4: [Method] testMemberFunction +# 30| 4: [Constructor] GenericTest +#-----| 4: (Parameters) +# 30| 0: [Parameter] p0 +# 30| 0: [TypeAccess] int +# 30| 1: [Parameter] p1 +# 30| 0: [TypeAccess] Object +# 30| 2: [Parameter] p2 +# 30| 0: [TypeAccess] String +# 30| 3: [Parameter] p3 +# 30| 0: [TypeAccess] Object +# 30| 4: [Parameter] p4 +# 30| 0: [TypeAccess] int +# 30| 5: [Parameter] p5 +# 30| 0: [TypeAccess] DefaultConstructorMarker +# 30| 5: [BlockStmt] { ... } +# 30| 0: [IfStmt] if (...) +# 30| 0: [EQExpr] ... == ... +# 30| 0: [AndBitwiseExpr] ... & ... +# 30| 0: [IntegerLiteral] 1 +# 30| 1: [VarAccess] p4 +# 30| 1: [IntegerLiteral] 0 +# 30| 1: [ExprStmt] ; +# 30| 0: [AssignExpr] ...=... +# 30| 0: [VarAccess] p0 +# 30| 1: [IntegerLiteral] 1 +# 30| 1: [IfStmt] if (...) +# 30| 0: [EQExpr] ... == ... +# 30| 0: [AndBitwiseExpr] ... & ... +# 30| 0: [IntegerLiteral] 4 +# 30| 1: [VarAccess] p4 +# 30| 1: [IntegerLiteral] 0 +# 30| 1: [ExprStmt] ; +# 30| 0: [AssignExpr] ...=... +# 30| 0: [VarAccess] p2 +# 30| 1: [StringLiteral] Hello world +# 30| 2: [ThisConstructorInvocationStmt] this(...) +# 30| 0: [VarAccess] p0 +# 30| 1: [VarAccess] p1 +# 30| 2: [VarAccess] p2 +# 30| 3: [VarAccess] p3 +# 33| 5: [Method] testMemberFunction # 33| 3: [TypeAccess] int #-----| 4: (Parameters) # 33| 0: [Parameter] b @@ -530,7 +910,7 @@ test.kt: # 33| 1: [VarAccess] b # 33| 2: [StringLiteral] Hello world # 33| 3: [VarAccess] d -# 33| 5: [Method] testMemberFunction +# 33| 6: [Method] testMemberFunction # 33| 3: [TypeAccess] int #-----| 4: (Parameters) # 33| 0: [Parameter] a @@ -547,7 +927,7 @@ test.kt: # 33| 1: [VarAccess] b # 33| 2: [StringLiteral] Hello world # 33| 3: [VarAccess] d -# 33| 6: [Method] testMemberFunction +# 33| 7: [Method] testMemberFunction # 33| 3: [TypeAccess] int #-----| 4: (Parameters) # 33| 0: [Parameter] a @@ -561,7 +941,52 @@ test.kt: # 33| 5: [BlockStmt] { ... } # 33| 0: [ReturnStmt] return ... # 33| 0: [VarAccess] a -# 35| 7: [Method] useSpecialised +# 33| 8: [Method] testMemberFunction$default +# 33| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 33| 0: [Parameter] p0 +# 33| 0: [TypeAccess] GenericTest<> +# 33| 1: [Parameter] p1 +# 33| 0: [TypeAccess] int +# 33| 2: [Parameter] p2 +# 33| 0: [TypeAccess] Object +# 33| 3: [Parameter] p3 +# 33| 0: [TypeAccess] String +# 33| 4: [Parameter] p4 +# 33| 0: [TypeAccess] Object +# 33| 5: [Parameter] p5 +# 33| 0: [TypeAccess] int +# 33| 6: [Parameter] p6 +# 33| 0: [TypeAccess] Object +# 33| 5: [BlockStmt] { ... } +# 33| 0: [IfStmt] if (...) +# 33| 0: [EQExpr] ... == ... +# 33| 0: [AndBitwiseExpr] ... & ... +# 33| 0: [IntegerLiteral] 1 +# 33| 1: [VarAccess] p5 +# 33| 1: [IntegerLiteral] 0 +# 33| 1: [ExprStmt] ; +# 33| 0: [AssignExpr] ...=... +# 33| 0: [VarAccess] p1 +# 33| 1: [IntegerLiteral] 1 +# 33| 1: [IfStmt] if (...) +# 33| 0: [EQExpr] ... == ... +# 33| 0: [AndBitwiseExpr] ... & ... +# 33| 0: [IntegerLiteral] 4 +# 33| 1: [VarAccess] p5 +# 33| 1: [IntegerLiteral] 0 +# 33| 1: [ExprStmt] ; +# 33| 0: [AssignExpr] ...=... +# 33| 0: [VarAccess] p3 +# 33| 1: [StringLiteral] Hello world +# 33| 2: [ReturnStmt] return ... +# 33| 0: [MethodAccess] testMemberFunction(...) +# 33| -1: [VarAccess] p0 +# 33| 0: [VarAccess] p1 +# 33| 1: [VarAccess] p2 +# 33| 2: [VarAccess] p3 +# 33| 3: [VarAccess] p4 +# 35| 9: [Method] useSpecialised # 35| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 35| 0: [Parameter] spec1 diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected index 7f77cb28b81..00654e8929f 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected @@ -16,19 +16,24 @@ | test.kt:0:0:0:0 | TestKt | test.kt:45:1:45:112 | testExtensionFunction | testExtensionFunction(Test,int,double,boolean) | | test.kt:0:0:0:0 | TestKt | test.kt:45:1:45:112 | testExtensionFunction | testExtensionFunction(Test,int,java.lang.String,double,boolean) | | test.kt:0:0:0:0 | TestKt | test.kt:45:1:45:112 | testExtensionFunction | testExtensionFunction(Test,int,java.lang.String,double,float,boolean) | +| test.kt:0:0:0:0 | TestKt | test.kt:45:1:45:112 | testExtensionFunction$default | testExtensionFunction$default(Test,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:3:1:14:1 | Test | test.kt:3:1:14:1 | Test | Test() | | test.kt:3:1:14:1 | Test | test.kt:6:3:6:106 | testStaticFunction | testStaticFunction(int,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:6:3:6:106 | testStaticFunction | testStaticFunction(int,java.lang.String,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:6:3:6:106 | testStaticFunction | testStaticFunction(int,java.lang.String,double,float,boolean) | +| test.kt:3:1:14:1 | Test | test.kt:6:3:6:106 | testStaticFunction$default | testStaticFunction$default(int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:3:1:14:1 | Test | test.kt:9:3:9:106 | testMemberFunction | testMemberFunction(int,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:9:3:9:106 | testMemberFunction | testMemberFunction(int,java.lang.String,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:9:3:9:106 | testMemberFunction | testMemberFunction(int,java.lang.String,double,float,boolean) | +| test.kt:3:1:14:1 | Test | test.kt:9:3:9:106 | testMemberFunction$default | testMemberFunction$default(Test,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,java.lang.String,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,java.lang.String,double,float,boolean) | +| test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction$default | testMemberExtensionFunction$default(Test2,Test,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,java.lang.String,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,java.lang.String,double,float,boolean) | +| test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,java.lang.String,double,float,boolean,int,kotlin.jvm.internal.DefaultConstructorMarker) | | test.kt:16:1:28:1 | Test2 | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,java.lang.String,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,java.lang.String,double,float,boolean) | @@ -36,13 +41,17 @@ | test.kt:18:3:26:3 | Companion | test.kt:21:5:21:111 | testCompanionFunction | testCompanionFunction(int,double,boolean) | | test.kt:18:3:26:3 | Companion | test.kt:21:5:21:111 | testCompanionFunction | testCompanionFunction(int,java.lang.String,double,boolean) | | test.kt:18:3:26:3 | Companion | test.kt:21:5:21:111 | testCompanionFunction | testCompanionFunction(int,java.lang.String,double,float,boolean) | +| test.kt:18:3:26:3 | Companion | test.kt:21:5:21:111 | testCompanionFunction$default | testCompanionFunction$default(Test2.Companion,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:18:3:26:3 | Companion | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,double,boolean) | | test.kt:18:3:26:3 | Companion | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,java.lang.String,double,boolean) | | test.kt:18:3:26:3 | Companion | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,java.lang.String,double,float,boolean) | +| test.kt:18:3:26:3 | Companion | test.kt:24:5:24:117 | testStaticCompanionFunction$default | testStaticCompanionFunction$default(Test2.Companion,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:30:43:42:1 | GenericTest | GenericTest(int,java.lang.Object,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:30:43:42:1 | GenericTest | GenericTest(int,java.lang.Object,java.lang.String,java.lang.Object) | +| test.kt:30:1:42:1 | GenericTest | test.kt:30:43:42:1 | GenericTest | GenericTest(int,java.lang.Object,java.lang.String,java.lang.Object,int,kotlin.jvm.internal.DefaultConstructorMarker) | | test.kt:30:1:42:1 | GenericTest | test.kt:30:43:42:1 | GenericTest | GenericTest(java.lang.Object,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:33:3:33:84 | testMemberFunction | testMemberFunction(int,java.lang.Object,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:33:3:33:84 | testMemberFunction | testMemberFunction(int,java.lang.Object,java.lang.String,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:33:3:33:84 | testMemberFunction | testMemberFunction(java.lang.Object,java.lang.Object) | +| test.kt:30:1:42:1 | GenericTest | test.kt:33:3:33:84 | testMemberFunction$default | testMemberFunction$default(GenericTest,int,java.lang.Object,java.lang.String,java.lang.Object,int,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:35:3:40:3 | useSpecialised | useSpecialised(GenericTest,GenericTest) | diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.expected b/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.expected index 831de93ea2d..d2740fc010a 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.expected @@ -1,21 +1,27 @@ -| User.java:9:30:9:37 | source(...) | test.kt:13:97:13:97 | s | -| User.java:10:30:10:37 | source(...) | test.kt:13:97:13:97 | s | -| User.java:14:37:14:44 | source(...) | test.kt:25:105:25:105 | s | -| User.java:15:37:15:44 | source(...) | test.kt:25:105:25:105 | s | -| User.java:19:28:19:35 | source(...) | test.kt:33:97:33:97 | s | -| User.java:20:28:20:35 | source(...) | test.kt:33:97:33:97 | s | -| User.java:24:28:24:35 | source(...) | test.kt:43:93:43:93 | s | -| User.java:25:28:25:35 | source(...) | test.kt:43:93:43:93 | s | -| User.java:29:45:29:52 | source(...) | test.kt:58:10:58:10 | s | -| User.java:30:45:30:52 | source(...) | test.kt:58:10:58:10 | s | -| User.java:34:61:34:68 | source(...) | test.kt:74:10:74:10 | s | -| User.java:35:61:35:68 | source(...) | test.kt:74:10:74:10 | s | -| User.java:38:28:38:35 | source(...) | test.kt:84:10:84:10 | y | -| User.java:39:20:39:27 | source(...) | test.kt:84:10:84:10 | y | -| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | -| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | -| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | -| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | -| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | -| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | -| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | +| User.java:9:30:9:37 | source(...) | test.kt:13:97:13:97 | s | User.java:5:22:5:25 | test | +| User.java:10:30:10:37 | source(...) | test.kt:13:97:13:97 | s | User.java:5:22:5:25 | test | +| User.java:14:37:14:44 | source(...) | test.kt:25:105:25:105 | s | User.java:5:22:5:25 | test | +| User.java:15:37:15:44 | source(...) | test.kt:25:105:25:105 | s | User.java:5:22:5:25 | test | +| User.java:19:28:19:35 | source(...) | test.kt:33:97:33:97 | s | User.java:5:22:5:25 | test | +| User.java:20:28:20:35 | source(...) | test.kt:33:97:33:97 | s | User.java:5:22:5:25 | test | +| User.java:24:28:24:35 | source(...) | test.kt:43:93:43:93 | s | User.java:5:22:5:25 | test | +| User.java:25:28:25:35 | source(...) | test.kt:43:93:43:93 | s | User.java:5:22:5:25 | test | +| User.java:29:45:29:52 | source(...) | test.kt:58:10:58:10 | s | User.java:5:22:5:25 | test | +| User.java:30:45:30:52 | source(...) | test.kt:58:10:58:10 | s | User.java:5:22:5:25 | test | +| User.java:34:61:34:68 | source(...) | test.kt:74:10:74:10 | s | User.java:5:22:5:25 | test | +| User.java:35:61:35:68 | source(...) | test.kt:74:10:74:10 | s | User.java:5:22:5:25 | test | +| User.java:38:28:38:35 | source(...) | test.kt:84:10:84:10 | y | User.java:5:22:5:25 | test | +| User.java:39:20:39:27 | source(...) | test.kt:84:10:84:10 | y | User.java:5:22:5:25 | test | +| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | test.kt:10:3:10:87 | taintSuppliedAsDefault | +| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | test.kt:10:3:10:87 | taintSuppliedAsDefault$default | +| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic | +| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic | +| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic$default | +| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | test.kt:30:3:30:87 | taintSuppliedAsDefault | +| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | test.kt:30:3:30:87 | taintSuppliedAsDefault$default | +| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | test.kt:40:3:40:83 | taintSuppliedAsDefault | +| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | test.kt:40:3:40:83 | taintSuppliedAsDefault$default | +| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | test.kt:47:55:53:1 | ConstructorTaintsByDefault | +| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | test.kt:47:55:53:1 | ConstructorTaintsByDefault | +| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | test.kt:63:65:69:1 | GenericConstructorTaintsByDefault | +| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | test.kt:63:65:69:1 | GenericConstructorTaintsByDefault | diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.ql b/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.ql index 4ed01f80da8..05bdca7b7c9 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.ql +++ b/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.ql @@ -15,4 +15,4 @@ class Config extends DataFlow::Configuration { from Config c, DataFlow::Node source, DataFlow::Node sink where c.hasFlow(source, sink) -select source, sink +select source, sink, source.getEnclosingCallable() From be655432d6404d5b9e06f3d99c72d8cfde81d59f Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 4 Oct 2022 10:01:09 +0100 Subject: [PATCH 055/107] Use new terse extraction functions where applicable --- .../src/main/kotlin/KotlinFileExtractor.kt | 215 ++++++------------ 1 file changed, 65 insertions(+), 150 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index b03c84af571..f239db907ac 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -389,9 +389,7 @@ open class KotlinFileExtractor( addModifiers(obinitId, "private") // add body: - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, obinitId, 0, obinitId) - tw.writeHasLocation(blockId, locId) + val blockId = extractBlockBody(obinitId, locId) extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } @@ -707,10 +705,7 @@ open class KotlinFileExtractor( tw.writeHasLocation(clinitId, locId) // add and return body block: - Pair(tw.getFreshIdLabel().also({ - tw.writeStmts_block(it, clinitId, 0, clinitId) - tw.writeHasLocation(it, locId) - }), clinitId) + Pair(extractBlockBody(clinitId, locId), clinitId) } } } @@ -775,32 +770,18 @@ open class KotlinFileExtractor( val expr = initializer.expression val declLocId = tw.getLocation(f) - val stmtId = tw.getFreshIdLabel() - tw.writeStmts_exprstmt(stmtId, blockAndFunctionId.first, idx++, blockAndFunctionId.second) - tw.writeHasLocation(stmtId, declLocId) - val assignmentId = tw.getFreshIdLabel() - val type = useType(if (isAnnotationClassField) kClassToJavaClass(expr.type) else expr.type) - tw.writeExprs_assignexpr(assignmentId, type.javaResult.id, stmtId, 0) - tw.writeExprsKotlinType(assignmentId, type.kotlinResult.id) - tw.writeHasLocation(assignmentId, declLocId) - tw.writeCallableEnclosingExpr(assignmentId, blockAndFunctionId.second) - tw.writeStatementEnclosingExpr(assignmentId, stmtId) - tw.writeKtInitializerAssignment(assignmentId) - - val lhsId = tw.getFreshIdLabel() - tw.writeExprs_varaccess(lhsId, lhsType.javaResult.id, assignmentId, 0) - tw.writeExprsKotlinType(lhsId, lhsType.kotlinResult.id) - tw.writeHasLocation(lhsId, declLocId) - tw.writeCallableEnclosingExpr(lhsId, blockAndFunctionId.second) - tw.writeStatementEnclosingExpr(lhsId, stmtId) - - tw.writeVariableBinding(lhsId, vId) - - if (static) { - extractStaticTypeAccessQualifier(f, lhsId, declLocId, blockAndFunctionId.second, stmtId) + extractExpressionStmt(declLocId, blockAndFunctionId.first, idx++, blockAndFunctionId.second).also { stmtId -> + val type = if (isAnnotationClassField) kClassToJavaClass(expr.type) else expr.type + extractAssignExpr(type, declLocId, stmtId, 0, blockAndFunctionId.second, stmtId).also { assignmentId -> + tw.writeKtInitializerAssignment(assignmentId) + extractVariableAccess(vId, lhsType, declLocId, assignmentId, 0, blockAndFunctionId.second, stmtId).also { lhsId -> + if (static) { + extractStaticTypeAccessQualifier(f, lhsId, declLocId, blockAndFunctionId.second, stmtId) + } + } + extractExpressionExpr(expr, blockAndFunctionId.second, assignmentId, 1, stmtId) + } } - - extractExpressionExpr(expr, blockAndFunctionId.second, assignmentId, 1, stmtId) } for (decl in declarations) { @@ -993,10 +974,7 @@ open class KotlinFileExtractor( // Create a synthetic function body that calls the real function supplying default arguments where required: if (f is IrConstructor) { - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, overloadId, 0, overloadId) - tw.writeHasLocation(blockId, realFunctionLocId) - + val blockId = extractBlockBody(overloadId, realFunctionLocId) val constructorCallId = tw.getFreshIdLabel() tw.writeStmts_constructorinvocationstmt(constructorCallId, blockId, 0, overloadId) tw.writeHasLocation(constructorCallId, realFunctionLocId) @@ -1356,11 +1334,8 @@ open class KotlinFileExtractor( } } - fun extractExpressionBody(callable: Label, locId: Label): Label { - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, callable, 0, callable) - tw.writeHasLocation(blockId, locId) - + fun extractExpressionBody(callable: Label, locId: Label): Label { + val blockId = extractBlockBody(callable, locId) return tw.getFreshIdLabel().also { returnId -> tw.writeStmts_returnstmt(returnId, blockId, 0, callable) tw.writeHasLocation(returnId, locId) @@ -2664,15 +2639,7 @@ open class KotlinFileExtractor( tw.writeStatementEnclosingExpr(initId, enclosingStmt) it.elements.forEachIndexed { i, arg -> extractVarargElement(arg, callable, initId, i, enclosingStmt) } - val dim = it.elements.size - val dimId = tw.getFreshIdLabel() - val dimType = useType(pluginContext.irBuiltIns.intType) - tw.writeExprs_integerliteral(dimId, dimType.javaResult.id, id, 0) - tw.writeExprsKotlinType(dimId, dimType.kotlinResult.id) - tw.writeHasLocation(dimId, locId) - tw.writeCallableEnclosingExpr(dimId, callable) - tw.writeStatementEnclosingExpr(dimId, enclosingStmt) - tw.writeNamestrings(dim.toString(), dim.toString(), dimId) + extractConstantInteger(it.elements.size, locId, id, 0, callable, enclosingStmt) } } } @@ -2744,27 +2711,21 @@ open class KotlinFileExtractor( if (array != null && arrayIdx != null && assignedValue != null) { - val assignId = tw.getFreshIdLabel() - val type = useType(c.type) val locId = tw.getLocation(c) - tw.writeExprs_assignexpr(assignId, type.javaResult.id, parent, idx) - tw.writeExprsKotlinType(assignId, type.kotlinResult.id) - tw.writeHasLocation(assignId, locId) - tw.writeCallableEnclosingExpr(assignId, callable) - tw.writeStatementEnclosingExpr(assignId, enclosingStmt) + extractAssignExpr(c.type, locId, parent, idx, callable, enclosingStmt).also { assignId -> + tw.getFreshIdLabel().also { arrayAccessId -> + val arrayType = useType(array.type) + tw.writeExprs_arrayaccess(arrayAccessId, arrayType.javaResult.id, assignId, 0) + tw.writeExprsKotlinType(arrayAccessId, arrayType.kotlinResult.id) + tw.writeHasLocation(arrayAccessId, locId) + tw.writeCallableEnclosingExpr(arrayAccessId, callable) + tw.writeStatementEnclosingExpr(arrayAccessId, enclosingStmt) - val arrayAccessId = tw.getFreshIdLabel() - val arrayType = useType(array.type) - tw.writeExprs_arrayaccess(arrayAccessId, arrayType.javaResult.id, assignId, 0) - tw.writeExprsKotlinType(arrayAccessId, arrayType.kotlinResult.id) - tw.writeHasLocation(arrayAccessId, locId) - tw.writeCallableEnclosingExpr(arrayAccessId, callable) - tw.writeStatementEnclosingExpr(arrayAccessId, enclosingStmt) - - extractExpressionExpr(array, callable, arrayAccessId, 0, enclosingStmt) - extractExpressionExpr(arrayIdx, callable, arrayAccessId, 1, enclosingStmt) - - extractExpressionExpr(assignedValue, callable, assignId, 1, enclosingStmt) + extractExpressionExpr(array, callable, arrayAccessId, 0, enclosingStmt) + extractExpressionExpr(arrayIdx, callable, arrayAccessId, 1, enclosingStmt) + } + extractExpressionExpr(assignedValue, callable, assignId, 1, enclosingStmt) + } } else { logger.errorElement("Unexpected Array.set function signature", c) @@ -3002,16 +2963,12 @@ open class KotlinFileExtractor( } inner class StmtParent(val parent: Label, val idx: Int): StmtExprParent() { - override fun stmt(e: IrExpression, callable: Label): StmtParent { - return this - } - override fun expr(e: IrExpression, callable: Label): ExprParent { - val id = tw.getFreshIdLabel() - val locId = tw.getLocation(e) - tw.writeStmts_exprstmt(id, parent, idx, callable) - tw.writeHasLocation(id, locId) - return ExprParent(id, 0, id) - } + override fun stmt(e: IrExpression, callable: Label) = this + + override fun expr(e: IrExpression, callable: Label) = + extractExpressionStmt(tw.getLocation(e), parent, idx, callable).let { id -> + ExprParent(id, 0, id) + } } inner class ExprParent(val parent: Label, val idx: Int, val enclosingStmt: Label): StmtExprParent() { override fun stmt(e: IrExpression, callable: Label): StmtParent { @@ -3798,9 +3755,8 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(irType, locId, it, 0) } - private fun extractThisAccess(irType: IrType, callable: Label, parent: Label, idx: Int, enclosingStmt: Label, locId: Label) = + private fun extractThisAccess(type: TypeResults, callable: Label, parent: Label, idx: Int, enclosingStmt: Label, locId: Label) = tw.getFreshIdLabel().also { - val type = useType(irType) tw.writeExprs_thisaccess(it, type.javaResult.id, parent, idx) tw.writeExprsKotlinType(it, type.kotlinResult.id) tw.writeHasLocation(it, locId) @@ -3808,6 +3764,9 @@ open class KotlinFileExtractor( tw.writeStatementEnclosingExpr(it, enclosingStmt) } + private fun extractThisAccess(irType: IrType, callable: Label, parent: Label, idx: Int, enclosingStmt: Label, locId: Label) = + extractThisAccess(useType(irType), callable, parent, idx, enclosingStmt, locId) + private fun extractThisAccess(e: IrGetValue, thisParamParent: IrDeclarationParent, exprParent: ExprParent, callable: Label) { val containingDeclaration = declarationStack.peek().first val locId = tw.getLocation(e) @@ -3866,9 +3825,8 @@ open class KotlinFileExtractor( } } - private fun extractVariableAccess(variable: Label?, irType: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + private fun extractVariableAccess(variable: Label?, type: TypeResults, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = tw.getFreshIdLabel().also { - val type = useType(irType) tw.writeExprs_varaccess(it, type.javaResult.id, parent, idx) tw.writeExprsKotlinType(it, type.kotlinResult.id) tw.writeHasLocation(it, locId) @@ -3880,6 +3838,9 @@ open class KotlinFileExtractor( } } + private fun extractVariableAccess(variable: Label?, irType: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + extractVariableAccess(variable, useType(irType), locId, parent, idx, callable, enclosingStmt) + private fun extractLoop( loop: IrLoop, stmtExprParent: StmtExprParent, @@ -3953,33 +3914,16 @@ open class KotlinFileExtractor( stmtIdx: Int ) { val paramId = tw.getFreshIdLabel() - val paramTypeRes = extractValueParameter(paramId, paramType, paramName, locId, ids.constructor, paramIdx, paramId, syntheticParameterNames = false, isVararg = false, isNoinline = false, isCrossinline = false) + extractValueParameter(paramId, paramType, paramName, locId, ids.constructor, paramIdx, paramId, syntheticParameterNames = false, isVararg = false, isNoinline = false, isCrossinline = false) - val assignmentStmtId = tw.getFreshIdLabel() - tw.writeStmts_exprstmt(assignmentStmtId, ids.constructorBlock, stmtIdx, ids.constructor) - tw.writeHasLocation(assignmentStmtId, locId) - - val assignmentId = tw.getFreshIdLabel() - tw.writeExprs_assignexpr(assignmentId, paramTypeRes.javaResult.id, assignmentStmtId, 0) - tw.writeExprsKotlinType(assignmentId, paramTypeRes.kotlinResult.id) - writeExpressionMetadataToTrapFile(assignmentId, ids.constructor, assignmentStmtId) - - val lhsId = tw.getFreshIdLabel() - tw.writeExprs_varaccess(lhsId, paramTypeRes.javaResult.id, assignmentId, 0) - tw.writeExprsKotlinType(lhsId, paramTypeRes.kotlinResult.id) - tw.writeVariableBinding(lhsId, fieldId) - writeExpressionMetadataToTrapFile(lhsId, ids.constructor, assignmentStmtId) - - val thisId = tw.getFreshIdLabel() - tw.writeExprs_thisaccess(thisId, ids.type.javaResult.id, lhsId, -1) - tw.writeExprsKotlinType(thisId, ids.type.kotlinResult.id) - writeExpressionMetadataToTrapFile(thisId, ids.constructor, assignmentStmtId) - - val rhsId = tw.getFreshIdLabel() - tw.writeExprs_varaccess(rhsId, paramTypeRes.javaResult.id, assignmentId, 1) - tw.writeExprsKotlinType(rhsId, paramTypeRes.kotlinResult.id) - tw.writeVariableBinding(rhsId, paramId) - writeExpressionMetadataToTrapFile(rhsId, ids.constructor, assignmentStmtId) + extractExpressionStmt(locId, ids.constructorBlock, stmtIdx, ids.constructor).also { assignmentStmtId -> + extractAssignExpr(paramType, locId, assignmentStmtId, 0, ids.constructor, assignmentStmtId).also { assignmentId -> + extractVariableAccess(fieldId, paramType, locId, assignmentId, 0, ids.constructor, assignmentStmtId).also { lhsId -> + extractThisAccess(ids.type, ids.constructor, lhsId, -1, assignmentStmtId, locId) + } + extractVariableAccess(paramId, paramType, locId, assignmentId, 1, ids.constructor, assignmentStmtId) + } + } } } @@ -4037,35 +3981,22 @@ open class KotlinFileExtractor( } protected fun writeThisAccess(parent: Label, callable: Label, stmt: Label) { - val thisId = tw.getFreshIdLabel() - tw.writeExprs_thisaccess(thisId, ids.type.javaResult.id, parent, -1) - tw.writeExprsKotlinType(thisId, ids.type.kotlinResult.id) - writeExpressionMetadataToTrapFile(thisId, callable, stmt) + extractThisAccess(ids.type, callable, parent, -1, stmt, locId) } fun extractFieldWriteOfReflectionTarget( labels: FunctionLabels, // labels of the containing function target: IrFieldSymbol, // the target field being accessed) ) { - // ...; - val exprStmtId = tw.getFreshIdLabel() - tw.writeStmts_exprstmt(exprStmtId, labels.blockId, 0, labels.methodId) - tw.writeHasLocation(exprStmtId, locId) - val fieldType = useType(target.owner.type) - // ... = ... - val assignExprId = tw.getFreshIdLabel() - tw.writeExprs_assignexpr(assignExprId, fieldType.javaResult.id, exprStmtId, 0) - tw.writeExprsKotlinType(assignExprId, fieldType.kotlinResult.id) - writeExpressionMetadataToTrapFile(assignExprId, labels.methodId, exprStmtId) - - // LHS - extractFieldAccess(fieldType, assignExprId, exprStmtId, labels, target) - - // RHS - val p = labels.parameters.first() - writeVariableAccessInFunctionBody(p.second, 1, p.first, assignExprId, labels.methodId, exprStmtId) + extractExpressionStmt(locId, labels.blockId, 0, labels.methodId).also { exprStmtId -> + extractAssignExpr(target.owner.type, locId, exprStmtId, 0, labels.methodId, exprStmtId).also { assignExprId -> + extractFieldAccess(fieldType, assignExprId, exprStmtId, labels, target) + val p = labels.parameters.first() + writeVariableAccessInFunctionBody(p.second, 1, p.first, assignExprId, labels.methodId, exprStmtId) + } + } } fun extractFieldReturnOfReflectionTarget( @@ -4641,12 +4572,7 @@ open class KotlinFileExtractor( addModifiers(methodId, "public") addModifiers(methodId, "override") - // Block - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, methodId, 0, methodId) - tw.writeHasLocation(blockId, locId) - - return FunctionLabels(methodId, blockId, parameters) + return FunctionLabels(methodId, extractBlockBody(methodId, locId), parameters) } /* @@ -4688,10 +4614,7 @@ open class KotlinFileExtractor( tw.writeCallableBinding(callId, calledMethodId) // this access - val thisId = tw.getFreshIdLabel() - tw.writeExprs_thisaccess(thisId, ids.type.javaResult.id, callId, -1) - tw.writeExprsKotlinType(thisId, ids.type.kotlinResult.id) - extractCommonExpr(thisId) + extractThisAccess(ids.type, funLabels.methodId, callId, -1, retId, locId) addArgumentsToInvocationInInvokeNBody(parameters.map { it.type }, funLabels, retId, callId, locId, ::extractCommonExpr) } @@ -4953,13 +4876,7 @@ open class KotlinFileExtractor( tw.writeExprsKotlinType(initId, at.kotlinResult.id) extractCommonExpr(initId) - val dim = arraySize.toString() - val dimId = tw.getFreshIdLabel() - val dimType = useType(pluginContext.irBuiltIns.intType) - tw.writeExprs_integerliteral(dimId, dimType.javaResult.id, arrayCreationId, 0) - tw.writeExprsKotlinType(dimId, dimType.kotlinResult.id) - extractCommonExpr(dimId) - tw.writeNamestrings(dim, dim, dimId) + extractConstantInteger(arraySize, locId, arrayCreationId, 0, enclosingCallable, enclosingStmt) return initId } @@ -5158,9 +5075,7 @@ open class KotlinFileExtractor( } //body - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, ids.function, 0, ids.function) - tw.writeHasLocation(blockId, locId) + val blockId = extractBlockBody(ids.function, locId) //return stmt val returnId = tw.getFreshIdLabel() From 3452dcbcedb078bb905f4fc76d94f6f1b0b89d2e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 5 Oct 2022 14:45:09 +0100 Subject: [PATCH 056/107] Fix class type parameter erasure within $default methods --- .../src/main/kotlin/KotlinFileExtractor.kt | 19 ++- .../src/main/kotlin/KotlinUsesExtractor.kt | 9 +- .../parameter-defaults/PrintAst.expected | 151 ++++++++++++++++++ .../parameter-defaults/erasure.expected | 0 .../parameter-defaults/erasure.ql | 13 ++ .../library-tests/parameter-defaults/test.kt | 13 ++ 6 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/erasure.expected create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index f239db907ac..3498c6dd66f 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -859,7 +859,10 @@ open class KotlinFileExtractor( // n + o'th parameter, where `o` is the parameter offset caused by adding any dispatch receiver to the parameter list. // Note we don't need to add the extension receiver here because `useValueParameter` always assumes an extension receiver // will be prepended if one exists. - DeclarationStackAdjuster(f, OverriddenFunctionAttributes(id, id, locId, nonSyntheticParams, typeParameters = listOf())).use { + // Note we have to get the real function ID here before entering this block, because otherwise we'll misrepresent the signature of a generic + // function without its type variables -- for example, trying to address `f(T, List)` as `f(Object, List)`. + val realFunctionId = useFunction(f) + DeclarationStackAdjuster(f, OverriddenFunctionAttributes(id, id, locId, nonSyntheticParams, typeParameters = listOf(), isStatic = true)).use { val realParamsVarId = getValueParameterLabel(id, parameterTypes.size - 2) val intType = pluginContext.irBuiltIns.intType val paramIdxOffset = listOf(dispatchReceiver, f.extensionReceiverParameter).count { it != null } @@ -889,7 +892,6 @@ open class KotlinFileExtractor( } } // Now call the real function: - val realFunctionId = useFunction(f) if (f is IrConstructor) { tw.getFreshIdLabel().also { thisCallId -> tw.writeStmts_constructorinvocationstmt(thisCallId, blockId, nextStmt++, id) @@ -5275,10 +5277,19 @@ open class KotlinFileExtractor( fun peek() = stack.peek() fun findOverriddenAttributes(f: IrFunction) = - stack.firstOrNull { it.first == f } ?.second + stack.lastOrNull { it.first == f } ?.second + + fun findFirst(f: (Pair) -> Boolean) = + stack.findLast(f) } - data class OverriddenFunctionAttributes(val id: Label? = null, val sourceDeclarationId: Label? = null, val sourceLoc: Label? = null, val valueParameters: List? = null, val typeParameters: List? = null) + data class OverriddenFunctionAttributes( + val id: Label? = null, + val sourceDeclarationId: Label? = null, + val sourceLoc: Label? = null, + val valueParameters: List? = null, + val typeParameters: List? = null, + val isStatic: Boolean? = null) private fun peekDeclStackAsDeclarationParent(elementToReportOn: IrElement): IrDeclarationParent? { val trapWriter = tw diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index 3d3bc361ae1..da87bfe1169 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -661,10 +661,17 @@ open class KotlinUsesExtractor( private fun isOnDeclarationStackWithoutTypeParameters(f: IrFunction) = this is KotlinFileExtractor && this.declarationStack.findOverriddenAttributes(f)?.typeParameters?.isEmpty() == true + private fun isStaticFunctionOnStackBeforeClass(c: IrClass) = + this is KotlinFileExtractor && (this.declarationStack.findFirst { it.first == c || it.second?.isStatic == true })?.second?.isStatic == true + private fun isUnavailableTypeParameter(t: IrType) = t is IrSimpleType && t.classifier.owner.let { owner -> owner is IrTypeParameter && owner.parent.let { parent -> - parent is IrFunction && isOnDeclarationStackWithoutTypeParameters(parent) + when (parent) { + is IrFunction -> isOnDeclarationStackWithoutTypeParameters(parent) + is IrClass -> isStaticFunctionOnStackBeforeClass(parent) + else -> false + } } } diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected index 068b34f79b4..9977957a14a 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -847,3 +847,154 @@ test.kt: # 1| 2: [NullLiteral] null # 1| 3: [IntegerLiteral] 1 # 1| 4: [NullLiteral] null +# 143| 12: [Class,GenericType,ParameterizedType] TestGenericFunction +#-----| -2: (Generic Parameters) +# 143| 0: [TypeVariable] T +# 143| 1: [Constructor] TestGenericFunction +# 143| 5: [BlockStmt] { ... } +# 143| 0: [SuperConstructorInvocationStmt] super(...) +# 143| 1: [BlockStmt] { ... } +# 145| 2: [Method] f +#-----| 2: (Generic Parameters) +# 145| 0: [TypeVariable] S +# 145| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 145| 0: [Parameter] x +# 145| 0: [TypeAccess] S +# 145| 1: [Parameter] y +# 145| 0: [TypeAccess] T +# 145| 2: [Parameter] def1 +# 145| 0: [TypeAccess] T +# 145| 3: [Parameter] def2 +# 145| 0: [TypeAccess] List +# 145| 0: [WildcardTypeAccess] ? ... +# 145| 0: [TypeAccess] T +# 145| 4: [Parameter] def3 +# 145| 0: [TypeAccess] S +# 145| 5: [Parameter] def4 +# 145| 0: [TypeAccess] List +# 145| 0: [WildcardTypeAccess] ? ... +# 145| 0: [TypeAccess] S +# 145| 5: [BlockStmt] { ... } +# 146| 0: [ExprStmt] ; +# 146| 0: [MethodAccess] sink(...) +# 146| -1: [TypeAccess] TestKt +# 146| 0: [VarAccess] y +# 145| 3: [Method] f$default +# 145| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 145| 0: [Parameter] p0 +# 145| 0: [TypeAccess] TestGenericFunction<> +# 145| 1: [Parameter] p1 +# 145| 0: [TypeAccess] Object +# 145| 2: [Parameter] p2 +# 145| 0: [TypeAccess] Object +# 145| 3: [Parameter] p3 +# 145| 0: [TypeAccess] Object +# 145| 4: [Parameter] p4 +# 145| 0: [TypeAccess] List<> +# 145| 5: [Parameter] p5 +# 145| 0: [TypeAccess] Object +# 145| 6: [Parameter] p6 +# 145| 0: [TypeAccess] List<> +# 145| 7: [Parameter] p7 +# 145| 0: [TypeAccess] int +# 145| 8: [Parameter] p8 +# 145| 0: [TypeAccess] Object +# 145| 5: [BlockStmt] { ... } +# 145| 0: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 2 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p2 +# 145| 1: [VarAccess] p1 +# 145| 1: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 4 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p3 +# 145| 1: [NullLiteral] null +# 145| 2: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 8 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p4 +# 145| 1: [MethodAccess] listOf(...) +# 145| -2: [TypeAccess] Object +# 145| -1: [TypeAccess] CollectionsKt +# 145| 0: [VarAccess] p2 +# 145| 3: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 16 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p5 +# 145| 1: [NullLiteral] null +# 145| 4: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 32 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p6 +# 145| 1: [MethodAccess] listOf(...) +# 145| -2: [TypeAccess] Object +# 145| -1: [TypeAccess] CollectionsKt +# 145| 0: [VarAccess] p1 +# 145| 5: [ReturnStmt] return ... +# 145| 0: [MethodAccess] f(...) +# 145| -1: [VarAccess] p0 +# 145| 0: [VarAccess] p1 +# 145| 1: [VarAccess] p2 +# 145| 2: [VarAccess] p3 +# 145| 3: [VarAccess] p4 +# 145| 4: [VarAccess] p5 +# 145| 5: [VarAccess] p6 +# 149| 4: [Method] user +# 149| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 149| 0: [Parameter] inst +# 149| 0: [TypeAccess] TestGenericFunction +# 149| 0: [TypeAccess] String +# 149| 5: [BlockStmt] { ... } +# 150| 0: [ExprStmt] ; +# 150| 0: [MethodAccess] f$default(...) +# 150| -1: [TypeAccess] TestGenericFunction<> +# 150| 0: [VarAccess] inst +# 150| 1: [StringLiteral] generic function sunk +# 1| 2: [NullLiteral] null +# 1| 3: [NullLiteral] null +# 1| 4: [NullLiteral] null +# 1| 5: [NullLiteral] null +# 1| 6: [NullLiteral] null +# 1| 7: [IntegerLiteral] 1 +# 1| 8: [NullLiteral] null +# 151| 1: [ExprStmt] ; +# 151| 0: [MethodAccess] f$default(...) +# 151| -1: [TypeAccess] TestGenericFunction<> +# 151| 0: [VarAccess] inst +# 151| 1: [StringLiteral] generic function sunk fp +# 151| 2: [StringLiteral] generic function sunk 2 +# 1| 3: [NullLiteral] null +# 1| 4: [NullLiteral] null +# 1| 5: [NullLiteral] null +# 1| 6: [NullLiteral] null +# 1| 7: [IntegerLiteral] 3 +# 1| 8: [NullLiteral] null diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql b/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql new file mode 100644 index 00000000000..b53a83e436c --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql @@ -0,0 +1,13 @@ +import java + +// This checks that all type parameter references are erased in the context of a $default function. +predicate containsTypeVariables(Type t) { + t != t.getErasure() and + not t.getErasure().(GenericType).getRawType() = t +} + +from Expr e +where + e.getEnclosingCallable().getName().matches("%$default") and + containsTypeVariables(e.getType()) +select e, e.getType() diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt index 144664f0a07..e875307d1c0 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt @@ -139,3 +139,16 @@ class TestGeneric { } } + +class TestGenericFunction { + + fun f(x: S, y: T = x, def1: T? = null, def2: List = listOf(y), def3: S? = null, def4: List? = listOf(x)) { + sink(y) + } + + fun user(inst: TestGenericFunction) { + inst.f("generic function sunk") + inst.f("generic function sunk fp", "generic function sunk 2") + } + +} From b79d273de4a77b7bebca960fbd89655e9c1c5fec Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 5 Oct 2022 15:06:55 +0100 Subject: [PATCH 057/107] When calling a $default method, ensure the real method gets extracted --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 3498c6dd66f..0a1dc5466e1 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1718,6 +1718,10 @@ open class KotlinFileExtractor( extensionReceiver: IrExpression? ) { val callTarget = syntacticCallTarget.target.realOverrideTarget + if (isExternalDeclaration(callTarget)) { + // Ensure the real target gets extracted, as we might not every directly touch it thanks to this call being redirected to a $default method. + useFunction(callTarget) + } val defaultMethodLabel = getDefaultsMethodLabel(callTarget) val id = extractMethodAccessWithoutArgs(callsite.type, locId, enclosingCallable, callsiteParent, childIdx, enclosingStmt, defaultMethodLabel) From bec948682d01f4b87179d4b1a056b6c608ea953a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 5 Oct 2022 15:21:25 +0100 Subject: [PATCH 058/107] Fix calls to static methods defined in association with local functions These are a bit weird since they involve static calls to unnamed synthetic class members, but while unwriteable as Java they ought to work as a database description. --- .../kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- .../library-tests/parameter-defaults/PrintAst.expected | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 0a1dc5466e1..a49691924b1 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1726,7 +1726,7 @@ open class KotlinFileExtractor( val id = extractMethodAccessWithoutArgs(callsite.type, locId, enclosingCallable, callsiteParent, childIdx, enclosingStmt, defaultMethodLabel) if (callTarget.isLocalFunction()) { - extractNewExprForLocalFunction(getLocallyVisibleFunctionLabels(callTarget), id, locId, enclosingCallable, enclosingStmt) + extractTypeAccess(getLocallyVisibleFunctionLabels(callTarget).type, locId, id, -1, enclosingCallable, enclosingStmt) } else { extractStaticTypeAccessQualifierUnchecked(callTarget.parent, id, locId, enclosingCallable, enclosingStmt) } diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected index 9977957a14a..86a8d5c9c2b 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -568,8 +568,7 @@ test.kt: # 90| 5: [BlockStmt] { ... } # 91| 0: [ExprStmt] ; # 91| 0: [MethodAccess] f$default(...) -# 91| -1: [ClassInstanceExpr] new (...) -# 91| -3: [TypeAccess] Object +# 91| -1: [TypeAccess] # 91| 0: [StringLiteral] local sunk # 1| 1: [NullLiteral] null # 1| 2: [NullLiteral] null @@ -577,8 +576,7 @@ test.kt: # 1| 4: [NullLiteral] null # 92| 1: [ExprStmt] ; # 92| 0: [MethodAccess] f$default(...) -# 92| -1: [ClassInstanceExpr] new (...) -# 92| -3: [TypeAccess] Object +# 92| -1: [TypeAccess] # 92| 0: [StringLiteral] local sunk fp # 92| 1: [StringLiteral] local sunk 2 # 1| 2: [NullLiteral] null From 5e182755a53086b5e629bebfea19583d441636d5 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 5 Oct 2022 15:27:48 +0100 Subject: [PATCH 059/107] Fix generated $default method visibilities --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index a49691924b1..3c1c2f9cabf 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -849,7 +849,10 @@ open class KotlinFileExtractor( addModifiers(id, "static") } tw.writeHasLocation(id, locId) - addModifiers(id, "public") + if (f.visibility != DescriptorVisibilities.PRIVATE && f.visibility != DescriptorVisibilities.PRIVATE_TO_THIS) { + // Private methods have package-private (default) visibility $default methods; all other visibilities seem to produce a public $default method. + addModifiers(id, "public") + } tw.writeCompiler_generated(id, CompilerGeneratedKinds.DEFAULT_ARGUMENTS_METHOD.kind) if (extractBody) { From 34b83f01d013ee8db522748c9fb33b631609cee2 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 5 Oct 2022 15:30:37 +0100 Subject: [PATCH 060/107] Fix naming of internal default methods --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 3c1c2f9cabf..2bf11f03999 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1683,7 +1683,7 @@ open class KotlinFileExtractor( } } } else { - f.name.asString() + "\$default" + getFunctionShortName(f).nameInDB + "\$default" } private fun getDefaultsMethodLabel(f: IrFunction): Label { From 764c139e3ea2d59bc6f1dd4876b5dc911d1381f3 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 6 Oct 2022 11:03:45 +0100 Subject: [PATCH 061/107] Visibility consistency query: allow $default methods to have package-private (default) visibility --- java/ql/consistency-queries/visibility.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/consistency-queries/visibility.ql b/java/ql/consistency-queries/visibility.ql index 1b6744cea1d..8de022f3607 100644 --- a/java/ql/consistency-queries/visibility.ql +++ b/java/ql/consistency-queries/visibility.ql @@ -19,5 +19,6 @@ where // TODO: This ought to have visibility information not m.getName() = "" and count(visibility(m)) != 1 and - not (count(visibility(m)) = 2 and visibility(m) = "public" and visibility(m) = "internal") // This is a reasonable result, since the JVM symbol is declared public, but Kotlin metadata flags it as internal + not (count(visibility(m)) = 2 and visibility(m) = "public" and visibility(m) = "internal") and // This is a reasonable result, since the JVM symbol is declared public, but Kotlin metadata flags it as internal + not (count(visibility(m)) = 0 and m.getName().matches("%$default")) // This is a reasonable result because the $default forwarder methods corresponding to private methods are package-private. select m, concat(visibility(m), ", ") From 020f29a1ab9d155e23f3493f57c4f120dcaa3be6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 6 Oct 2022 11:04:53 +0100 Subject: [PATCH 062/107] Add visibility tests --- .../parameter-defaults/PrintAst.expected | 169 ++++++++++++++++++ .../library-tests/parameter-defaults/test.kt | 9 + 2 files changed, 178 insertions(+) diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected index 86a8d5c9c2b..ed590470d20 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -996,3 +996,172 @@ test.kt: # 1| 6: [NullLiteral] null # 1| 7: [IntegerLiteral] 3 # 1| 8: [NullLiteral] null +# 156| 14: [Class] VisibilityTests +# 156| 1: [Constructor] VisibilityTests +# 156| 5: [BlockStmt] { ... } +# 156| 0: [SuperConstructorInvocationStmt] super(...) +# 156| 1: [BlockStmt] { ... } +# 158| 2: [Method] f +# 158| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 158| 0: [Parameter] x +# 158| 0: [TypeAccess] int +# 158| 1: [Parameter] y +# 158| 0: [TypeAccess] int +# 158| 5: [BlockStmt] { ... } +# 158| 0: [ReturnStmt] return ... +# 158| 0: [AddExpr] ... + ... +# 158| 0: [VarAccess] x +# 158| 1: [VarAccess] y +# 158| 3: [Method] f$default +# 158| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 158| 0: [Parameter] p0 +# 158| 0: [TypeAccess] VisibilityTests +# 158| 1: [Parameter] p1 +# 158| 0: [TypeAccess] int +# 158| 2: [Parameter] p2 +# 158| 0: [TypeAccess] int +# 158| 3: [Parameter] p3 +# 158| 0: [TypeAccess] int +# 158| 4: [Parameter] p4 +# 158| 0: [TypeAccess] Object +# 158| 5: [BlockStmt] { ... } +# 158| 0: [IfStmt] if (...) +# 158| 0: [EQExpr] ... == ... +# 158| 0: [AndBitwiseExpr] ... & ... +# 158| 0: [IntegerLiteral] 2 +# 158| 1: [VarAccess] p3 +# 158| 1: [IntegerLiteral] 0 +# 158| 1: [ExprStmt] ; +# 158| 0: [AssignExpr] ...=... +# 158| 0: [VarAccess] p2 +# 158| 1: [IntegerLiteral] 0 +# 158| 1: [ReturnStmt] return ... +# 158| 0: [MethodAccess] f(...) +# 158| -1: [VarAccess] p0 +# 158| 0: [VarAccess] p1 +# 158| 1: [VarAccess] p2 +# 159| 4: [Method] g$main +# 159| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 159| 0: [Parameter] x +# 159| 0: [TypeAccess] int +# 159| 1: [Parameter] y +# 159| 0: [TypeAccess] int +# 159| 5: [BlockStmt] { ... } +# 159| 0: [ReturnStmt] return ... +# 159| 0: [AddExpr] ... + ... +# 159| 0: [VarAccess] x +# 159| 1: [VarAccess] y +# 159| 5: [Method] g$main$default +# 159| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 159| 0: [Parameter] p0 +# 159| 0: [TypeAccess] VisibilityTests +# 159| 1: [Parameter] p1 +# 159| 0: [TypeAccess] int +# 159| 2: [Parameter] p2 +# 159| 0: [TypeAccess] int +# 159| 3: [Parameter] p3 +# 159| 0: [TypeAccess] int +# 159| 4: [Parameter] p4 +# 159| 0: [TypeAccess] Object +# 159| 5: [BlockStmt] { ... } +# 159| 0: [IfStmt] if (...) +# 159| 0: [EQExpr] ... == ... +# 159| 0: [AndBitwiseExpr] ... & ... +# 159| 0: [IntegerLiteral] 2 +# 159| 1: [VarAccess] p3 +# 159| 1: [IntegerLiteral] 0 +# 159| 1: [ExprStmt] ; +# 159| 0: [AssignExpr] ...=... +# 159| 0: [VarAccess] p2 +# 159| 1: [IntegerLiteral] 0 +# 159| 1: [ReturnStmt] return ... +# 159| 0: [MethodAccess] g$main(...) +# 159| -1: [VarAccess] p0 +# 159| 0: [VarAccess] p1 +# 159| 1: [VarAccess] p2 +# 160| 6: [Method] h +# 160| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 160| 0: [Parameter] x +# 160| 0: [TypeAccess] int +# 160| 1: [Parameter] y +# 160| 0: [TypeAccess] int +# 160| 5: [BlockStmt] { ... } +# 160| 0: [ReturnStmt] return ... +# 160| 0: [AddExpr] ... + ... +# 160| 0: [VarAccess] x +# 160| 1: [VarAccess] y +# 160| 7: [Method] h$default +# 160| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 160| 0: [Parameter] p0 +# 160| 0: [TypeAccess] VisibilityTests +# 160| 1: [Parameter] p1 +# 160| 0: [TypeAccess] int +# 160| 2: [Parameter] p2 +# 160| 0: [TypeAccess] int +# 160| 3: [Parameter] p3 +# 160| 0: [TypeAccess] int +# 160| 4: [Parameter] p4 +# 160| 0: [TypeAccess] Object +# 160| 5: [BlockStmt] { ... } +# 160| 0: [IfStmt] if (...) +# 160| 0: [EQExpr] ... == ... +# 160| 0: [AndBitwiseExpr] ... & ... +# 160| 0: [IntegerLiteral] 2 +# 160| 1: [VarAccess] p3 +# 160| 1: [IntegerLiteral] 0 +# 160| 1: [ExprStmt] ; +# 160| 0: [AssignExpr] ...=... +# 160| 0: [VarAccess] p2 +# 160| 1: [IntegerLiteral] 0 +# 160| 1: [ReturnStmt] return ... +# 160| 0: [MethodAccess] h(...) +# 160| -1: [VarAccess] p0 +# 160| 0: [VarAccess] p1 +# 160| 1: [VarAccess] p2 +# 161| 8: [Method] i +# 161| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 161| 0: [Parameter] x +# 161| 0: [TypeAccess] int +# 161| 1: [Parameter] y +# 161| 0: [TypeAccess] int +# 161| 5: [BlockStmt] { ... } +# 161| 0: [ReturnStmt] return ... +# 161| 0: [AddExpr] ... + ... +# 161| 0: [VarAccess] x +# 161| 1: [VarAccess] y +# 161| 9: [Method] i$default +# 161| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 161| 0: [Parameter] p0 +# 161| 0: [TypeAccess] VisibilityTests +# 161| 1: [Parameter] p1 +# 161| 0: [TypeAccess] int +# 161| 2: [Parameter] p2 +# 161| 0: [TypeAccess] int +# 161| 3: [Parameter] p3 +# 161| 0: [TypeAccess] int +# 161| 4: [Parameter] p4 +# 161| 0: [TypeAccess] Object +# 161| 5: [BlockStmt] { ... } +# 161| 0: [IfStmt] if (...) +# 161| 0: [EQExpr] ... == ... +# 161| 0: [AndBitwiseExpr] ... & ... +# 161| 0: [IntegerLiteral] 2 +# 161| 1: [VarAccess] p3 +# 161| 1: [IntegerLiteral] 0 +# 161| 1: [ExprStmt] ; +# 161| 0: [AssignExpr] ...=... +# 161| 0: [VarAccess] p2 +# 161| 1: [IntegerLiteral] 0 +# 161| 1: [ReturnStmt] return ... +# 161| 0: [MethodAccess] i(...) +# 161| -1: [VarAccess] p0 +# 161| 0: [VarAccess] p1 +# 161| 1: [VarAccess] p2 diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt index e875307d1c0..aa8684e8e70 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt @@ -152,3 +152,12 @@ class TestGenericFunction { } } + +class VisibilityTests { + + fun f(x: Int, y: Int = 0) = x + y + internal fun g(x: Int, y: Int = 0) = x + y + protected fun h(x: Int, y: Int = 0) = x + y + private fun i(x: Int, y: Int = 0) = x + y + +} From 86e5e4c4bc6f6673d9c4dd71e26cc936592f7e52 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 6 Oct 2022 11:05:10 +0100 Subject: [PATCH 063/107] Accept test changes --- .../PrintAst.expected | 63 +++++++++++++++---- .../data-classes/PrintAst.expected | 57 ++++++++++++++--- .../data-classes/callees.expected | 1 + .../library-tests/methods/exprs.expected | 28 +++++++++ .../library-tests/methods/methods.expected | 1 + .../library-tests/methods/parameters.expected | 5 ++ .../multiple_extensions/calls.expected | 2 +- .../reflection/reflection.expected | 1 + 8 files changed, 138 insertions(+), 20 deletions(-) diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected index 1d4c7983c61..68363f41329 100644 --- a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected @@ -65,7 +65,48 @@ app/src/main/kotlin/testProject/App.kt: # 0| -3: [TypeAccess] Project # 0| 0: [VarAccess] name # 0| 1: [VarAccess] language -# 0| 5: [Method] equals +# 0| 5: [Method] copy$default +# 0| 3: [TypeAccess] Project +#-----| 4: (Parameters) +# 0| 0: [Parameter] p0 +# 0| 0: [TypeAccess] Project +# 0| 1: [Parameter] p1 +# 0| 0: [TypeAccess] String +# 0| 2: [Parameter] p2 +# 0| 0: [TypeAccess] int +# 0| 3: [Parameter] p3 +# 0| 0: [TypeAccess] int +# 0| 4: [Parameter] p4 +# 0| 0: [TypeAccess] Object +# 0| 5: [BlockStmt] { ... } +# 0| 0: [IfStmt] if (...) +# 0| 0: [EQExpr] ... == ... +# 0| 0: [AndBitwiseExpr] ... & ... +# 0| 0: [IntegerLiteral] 1 +# 0| 1: [VarAccess] p3 +# 0| 1: [IntegerLiteral] 0 +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] p1 +# 0| 1: [VarAccess] p0.name +# 0| -1: [VarAccess] p0 +# 0| 1: [IfStmt] if (...) +# 0| 0: [EQExpr] ... == ... +# 0| 0: [AndBitwiseExpr] ... & ... +# 0| 0: [IntegerLiteral] 2 +# 0| 1: [VarAccess] p3 +# 0| 1: [IntegerLiteral] 0 +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] p2 +# 0| 1: [VarAccess] p0.language +# 0| -1: [VarAccess] p0 +# 0| 2: [ReturnStmt] return ... +# 0| 0: [MethodAccess] copy(...) +# 0| -1: [VarAccess] p0 +# 0| 0: [VarAccess] p1 +# 0| 1: [VarAccess] p2 +# 0| 6: [Method] equals # 0| 3: [TypeAccess] boolean #-----| 4: (Parameters) # 0| 0: [Parameter] other @@ -114,7 +155,7 @@ app/src/main/kotlin/testProject/App.kt: # 0| 0: [BooleanLiteral] false # 0| 5: [ReturnStmt] return ... # 0| 0: [BooleanLiteral] true -# 0| 6: [Method] hashCode +# 0| 7: [Method] hashCode # 0| 3: [TypeAccess] int # 0| 5: [BlockStmt] { ... } # 0| 0: [LocalVariableDeclStmt] var ...; @@ -134,7 +175,7 @@ app/src/main/kotlin/testProject/App.kt: # 0| -1: [ThisAccess] this # 0| 2: [ReturnStmt] return ... # 0| 0: [VarAccess] result -# 0| 7: [Method] toString +# 0| 8: [Method] toString # 0| 3: [TypeAccess] String # 0| 5: [BlockStmt] { ... } # 0| 0: [ReturnStmt] return ... @@ -148,7 +189,7 @@ app/src/main/kotlin/testProject/App.kt: # 0| 5: [VarAccess] this.language # 0| -1: [ThisAccess] this # 0| 6: [StringLiteral] ) -# 0| 8: [Method] write$Self +# 0| 9: [Method] write$Self # 0| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 0| 0: [Parameter] self @@ -172,7 +213,7 @@ app/src/main/kotlin/testProject/App.kt: # 7| 1: [IntegerLiteral] 1 # 7| 2: [MethodAccess] getLanguage(...) # 7| -1: [VarAccess] self -# 7| 9: [Class] $serializer +# 7| 10: [Class] $serializer # 0| 1: [FieldDeclaration] SerialDescriptor descriptor; # 0| -1: [TypeAccess] SerialDescriptor # 0| 2: [Method] childSerializers @@ -384,7 +425,7 @@ app/src/main/kotlin/testProject/App.kt: # 7| -1: [ThisAccess] $serializer.this # 7| 0: [TypeAccess] $serializer # 7| 1: [VarAccess] tmp0_serialDesc -# 7| 10: [Class] Companion +# 7| 11: [Class] Companion # 0| 1: [Method] serializer # 0| 3: [TypeAccess] KSerializer # 0| 0: [TypeAccess] Project @@ -395,7 +436,7 @@ app/src/main/kotlin/testProject/App.kt: # 7| 5: [BlockStmt] { ... } # 7| 0: [SuperConstructorInvocationStmt] super(...) # 7| 1: [BlockStmt] { ... } -# 8| 11: [Constructor] Project +# 8| 12: [Constructor] Project #-----| 4: (Parameters) # 8| 0: [Parameter] name # 8| 0: [TypeAccess] String @@ -410,21 +451,21 @@ app/src/main/kotlin/testProject/App.kt: # 8| 1: [ExprStmt] ; # 8| 0: [KtInitializerAssignExpr] ...=... # 8| 0: [VarAccess] language -# 8| 12: [FieldDeclaration] String name; +# 8| 13: [FieldDeclaration] String name; # 8| -1: [TypeAccess] String # 8| 0: [VarAccess] name -# 8| 13: [Method] getName +# 8| 14: [Method] getName # 8| 3: [TypeAccess] String # 8| 5: [BlockStmt] { ... } # 8| 0: [ReturnStmt] return ... # 8| 0: [VarAccess] this.name # 8| -1: [ThisAccess] this -# 8| 14: [Method] getLanguage +# 8| 15: [Method] getLanguage # 8| 3: [TypeAccess] int # 8| 5: [BlockStmt] { ... } # 8| 0: [ReturnStmt] return ... # 8| 0: [VarAccess] this.language # 8| -1: [ThisAccess] this -# 8| 15: [FieldDeclaration] int language; +# 8| 16: [FieldDeclaration] int language; # 8| -1: [TypeAccess] int # 8| 0: [VarAccess] language diff --git a/java/ql/test/kotlin/library-tests/data-classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/data-classes/PrintAst.expected index b850cf492e7..d52888544dc 100644 --- a/java/ql/test/kotlin/library-tests/data-classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/data-classes/PrintAst.expected @@ -28,7 +28,48 @@ dc.kt: # 0| -3: [TypeAccess] ProtoMapValue # 0| 0: [VarAccess] bytes # 0| 1: [VarAccess] strs -# 0| 4: [Method] equals +# 0| 4: [Method] copy$default +# 0| 3: [TypeAccess] ProtoMapValue +#-----| 4: (Parameters) +# 0| 0: [Parameter] p0 +# 0| 0: [TypeAccess] ProtoMapValue +# 0| 1: [Parameter] p1 +# 0| 0: [TypeAccess] byte[] +# 0| 2: [Parameter] p2 +# 0| 0: [TypeAccess] String[] +# 0| 3: [Parameter] p3 +# 0| 0: [TypeAccess] int +# 0| 4: [Parameter] p4 +# 0| 0: [TypeAccess] Object +# 0| 5: [BlockStmt] { ... } +# 0| 0: [IfStmt] if (...) +# 0| 0: [EQExpr] ... == ... +# 0| 0: [AndBitwiseExpr] ... & ... +# 0| 0: [IntegerLiteral] 1 +# 0| 1: [VarAccess] p3 +# 0| 1: [IntegerLiteral] 0 +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] p1 +# 0| 1: [VarAccess] p0.bytes +# 0| -1: [VarAccess] p0 +# 0| 1: [IfStmt] if (...) +# 0| 0: [EQExpr] ... == ... +# 0| 0: [AndBitwiseExpr] ... & ... +# 0| 0: [IntegerLiteral] 2 +# 0| 1: [VarAccess] p3 +# 0| 1: [IntegerLiteral] 0 +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] p2 +# 0| 1: [VarAccess] p0.strs +# 0| -1: [VarAccess] p0 +# 0| 2: [ReturnStmt] return ... +# 0| 0: [MethodAccess] copy(...) +# 0| -1: [VarAccess] p0 +# 0| 0: [VarAccess] p1 +# 0| 1: [VarAccess] p2 +# 0| 5: [Method] equals # 0| 3: [TypeAccess] boolean #-----| 4: (Parameters) # 0| 0: [Parameter] other @@ -77,7 +118,7 @@ dc.kt: # 0| 0: [BooleanLiteral] false # 0| 5: [ReturnStmt] return ... # 0| 0: [BooleanLiteral] true -# 0| 5: [Method] hashCode +# 0| 6: [Method] hashCode # 0| 3: [TypeAccess] int # 0| 5: [BlockStmt] { ... } # 0| 0: [LocalVariableDeclStmt] var ...; @@ -99,7 +140,7 @@ dc.kt: # 0| -1: [ThisAccess] this # 0| 2: [ReturnStmt] return ... # 0| 0: [VarAccess] result -# 0| 6: [Method] toString +# 0| 7: [Method] toString # 0| 3: [TypeAccess] String # 0| 5: [BlockStmt] { ... } # 0| 0: [ReturnStmt] return ... @@ -117,7 +158,7 @@ dc.kt: # 0| 0: [VarAccess] this.strs # 0| -1: [ThisAccess] this # 0| 6: [StringLiteral] ) -# 1| 7: [Constructor] ProtoMapValue +# 1| 8: [Constructor] ProtoMapValue #-----| 4: (Parameters) # 1| 0: [Parameter] bytes # 1| 0: [TypeAccess] byte[] @@ -133,20 +174,20 @@ dc.kt: # 1| 1: [ExprStmt] ; # 1| 0: [KtInitializerAssignExpr] ...=... # 1| 0: [VarAccess] strs -# 1| 8: [FieldDeclaration] byte[] bytes; +# 1| 9: [FieldDeclaration] byte[] bytes; # 1| -1: [TypeAccess] byte[] # 1| 0: [VarAccess] bytes -# 1| 9: [Method] getBytes +# 1| 10: [Method] getBytes # 1| 3: [TypeAccess] byte[] # 1| 5: [BlockStmt] { ... } # 1| 0: [ReturnStmt] return ... # 1| 0: [VarAccess] this.bytes # 1| -1: [ThisAccess] this -# 1| 10: [FieldDeclaration] String[] strs; +# 1| 11: [FieldDeclaration] String[] strs; # 1| -1: [TypeAccess] String[] # 1| 0: [TypeAccess] String # 1| 0: [VarAccess] strs -# 1| 11: [Method] getStrs +# 1| 12: [Method] getStrs # 1| 3: [TypeAccess] String[] # 1| 0: [TypeAccess] String # 1| 5: [BlockStmt] { ... } diff --git a/java/ql/test/kotlin/library-tests/data-classes/callees.expected b/java/ql/test/kotlin/library-tests/data-classes/callees.expected index 7e7250a1d18..f16c4ffb435 100644 --- a/java/ql/test/kotlin/library-tests/data-classes/callees.expected +++ b/java/ql/test/kotlin/library-tests/data-classes/callees.expected @@ -1,3 +1,4 @@ +| dc.kt:0:0:0:0 | copy(...) | ProtoMapValue.copy | | dc.kt:0:0:0:0 | hashCode(...) | java.util.Arrays.hashCode | | dc.kt:0:0:0:0 | hashCode(...) | java.util.Arrays.hashCode | | dc.kt:0:0:0:0 | new ProtoMapValue(...) | ProtoMapValue.ProtoMapValue | diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index 82122a7e9af..77033a11bbe 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -12,27 +12,42 @@ | clinit.kt:3:1:3:24 | int | TypeAccess | | clinit.kt:3:1:3:24 | int | TypeAccess | | clinit.kt:3:24:3:24 | 0 | IntegerLiteral | +| dataClass.kt:0:0:0:0 | 0 | IntegerLiteral | +| dataClass.kt:0:0:0:0 | 0 | IntegerLiteral | +| dataClass.kt:0:0:0:0 | 1 | IntegerLiteral | +| dataClass.kt:0:0:0:0 | 2 | IntegerLiteral | | dataClass.kt:0:0:0:0 | 31 | IntegerLiteral | | dataClass.kt:0:0:0:0 | "..." | StringTemplateExpr | | dataClass.kt:0:0:0:0 | (...)... | CastExpr | | dataClass.kt:0:0:0:0 | ) | StringLiteral | | dataClass.kt:0:0:0:0 | , | StringLiteral | | dataClass.kt:0:0:0:0 | ... !is ... | NotInstanceOfExpr | +| dataClass.kt:0:0:0:0 | ... & ... | AndBitwiseExpr | +| dataClass.kt:0:0:0:0 | ... & ... | AndBitwiseExpr | | dataClass.kt:0:0:0:0 | ... (value not-equals) ... | ValueNEExpr | | dataClass.kt:0:0:0:0 | ... (value not-equals) ... | ValueNEExpr | | dataClass.kt:0:0:0:0 | ... * ... | MulExpr | | dataClass.kt:0:0:0:0 | ... + ... | AddExpr | | dataClass.kt:0:0:0:0 | ... == ... | EQExpr | +| dataClass.kt:0:0:0:0 | ... == ... | EQExpr | +| dataClass.kt:0:0:0:0 | ... == ... | EQExpr | | dataClass.kt:0:0:0:0 | ...=... | AssignExpr | +| dataClass.kt:0:0:0:0 | ...=... | AssignExpr | +| dataClass.kt:0:0:0:0 | ...=... | AssignExpr | +| dataClass.kt:0:0:0:0 | DataClass | TypeAccess | +| dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass( | StringLiteral | | dataClass.kt:0:0:0:0 | Object | TypeAccess | +| dataClass.kt:0:0:0:0 | Object | TypeAccess | +| dataClass.kt:0:0:0:0 | String | TypeAccess | | dataClass.kt:0:0:0:0 | String | TypeAccess | | dataClass.kt:0:0:0:0 | String | TypeAccess | | dataClass.kt:0:0:0:0 | boolean | TypeAccess | +| dataClass.kt:0:0:0:0 | copy(...) | MethodAccess | | dataClass.kt:0:0:0:0 | false | BooleanLiteral | | dataClass.kt:0:0:0:0 | false | BooleanLiteral | | dataClass.kt:0:0:0:0 | false | BooleanLiteral | @@ -40,10 +55,23 @@ | dataClass.kt:0:0:0:0 | hashCode(...) | MethodAccess | | dataClass.kt:0:0:0:0 | int | TypeAccess | | dataClass.kt:0:0:0:0 | int | TypeAccess | +| dataClass.kt:0:0:0:0 | int | TypeAccess | +| dataClass.kt:0:0:0:0 | int | TypeAccess | | dataClass.kt:0:0:0:0 | new DataClass(...) | ClassInstanceExpr | | dataClass.kt:0:0:0:0 | other | VarAccess | | dataClass.kt:0:0:0:0 | other | VarAccess | | dataClass.kt:0:0:0:0 | other | VarAccess | +| dataClass.kt:0:0:0:0 | p0 | VarAccess | +| dataClass.kt:0:0:0:0 | p0 | VarAccess | +| dataClass.kt:0:0:0:0 | p0 | VarAccess | +| dataClass.kt:0:0:0:0 | p0.x | VarAccess | +| dataClass.kt:0:0:0:0 | p0.y | VarAccess | +| dataClass.kt:0:0:0:0 | p1 | VarAccess | +| dataClass.kt:0:0:0:0 | p1 | VarAccess | +| dataClass.kt:0:0:0:0 | p2 | VarAccess | +| dataClass.kt:0:0:0:0 | p2 | VarAccess | +| dataClass.kt:0:0:0:0 | p3 | VarAccess | +| dataClass.kt:0:0:0:0 | p3 | VarAccess | | dataClass.kt:0:0:0:0 | result | LocalVariableDeclExpr | | dataClass.kt:0:0:0:0 | result | VarAccess | | dataClass.kt:0:0:0:0 | result | VarAccess | diff --git a/java/ql/test/kotlin/library-tests/methods/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index e68bc650ce6..69c8e1ab214 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -5,6 +5,7 @@ methods | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component1 | component1() | public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component2 | component2() | public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | copy | copy(int,java.lang.String) | public | Compiler generated | +| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | copy$default | copy$default(DataClass,int,java.lang.String,int,java.lang.Object) | public, static | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | equals | equals(java.lang.Object) | override, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | hashCode | hashCode() | override, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | toString | toString() | override, public | Compiler generated | diff --git a/java/ql/test/kotlin/library-tests/methods/parameters.expected b/java/ql/test/kotlin/library-tests/methods/parameters.expected index 2b35e69e502..7e76cdcb55b 100644 --- a/java/ql/test/kotlin/library-tests/methods/parameters.expected +++ b/java/ql/test/kotlin/library-tests/methods/parameters.expected @@ -1,6 +1,11 @@ | clinit.kt:3:1:3:24 | setTopLevelInt | clinit.kt:3:1:3:24 | | 0 | | dataClass.kt:0:0:0:0 | copy | dataClass.kt:1:22:1:31 | x | 0 | | dataClass.kt:0:0:0:0 | copy | dataClass.kt:1:34:1:46 | y | 1 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p0 | 0 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p1 | 1 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p2 | 2 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p3 | 3 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p4 | 4 | | dataClass.kt:0:0:0:0 | equals | dataClass.kt:0:0:0:0 | other | 0 | | dataClass.kt:1:34:1:46 | setY | dataClass.kt:1:34:1:46 | | 0 | | delegates.kt:4:18:6:5 | get | delegates.kt:4:18:6:5 | a0 | 0 | diff --git a/java/ql/test/kotlin/library-tests/multiple_extensions/calls.expected b/java/ql/test/kotlin/library-tests/multiple_extensions/calls.expected index dd9c60f1a80..cb0e0eaf085 100644 --- a/java/ql/test/kotlin/library-tests/multiple_extensions/calls.expected +++ b/java/ql/test/kotlin/library-tests/multiple_extensions/calls.expected @@ -1,4 +1,4 @@ | PropertyReferenceDelegatesKt | getValue(KProperty0, Object, KProperty) | | PropertyReferenceDelegatesKt | getValue(KProperty1, T, KProperty) | | StringsKt | removePrefix(String, CharSequence) | -| StringsKt | startsWith(String, String, boolean) | +| StringsKt | startsWith$default(String, String, boolean, int, Object) | diff --git a/java/ql/test/kotlin/library-tests/reflection/reflection.expected b/java/ql/test/kotlin/library-tests/reflection/reflection.expected index 12bbfb4db98..523ebd93d44 100644 --- a/java/ql/test/kotlin/library-tests/reflection/reflection.expected +++ b/java/ql/test/kotlin/library-tests/reflection/reflection.expected @@ -233,6 +233,7 @@ compGenerated | file:///Class2.class:0:0:0:0 | getValue | 3 | | file:///Class2.class:0:0:0:0 | getValue | 3 | | file:///KTypeProjection.class:0:0:0:0 | contravariant | 8 | +| file:///KTypeProjection.class:0:0:0:0 | copy$default | 10 | | file:///KTypeProjection.class:0:0:0:0 | covariant | 8 | | file:///KTypeProjection.class:0:0:0:0 | invariant | 8 | | reflection.kt:33:9:33:23 | getP0 | 3 | From 0024e54e63aacd6501d6e857ba60cd742193e0c9 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 6 Oct 2022 12:55:17 +0100 Subject: [PATCH 064/107] Make method private --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 2bf11f03999..61470c7df52 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1624,7 +1624,7 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(pluginContext.irBuiltIns.anyType, locId, idNewexpr, -3, enclosingCallable, enclosingStmt) } - fun extractMethodAccessWithoutArgs( + private fun extractMethodAccessWithoutArgs( returnType: IrType, locId: Label, enclosingCallable: Label, From 1d8547d4c12113a5151dfe4cf16d5759f1341700 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 6 Oct 2022 12:57:56 +0100 Subject: [PATCH 065/107] Avoid using count(...) = 0 --- java/ql/consistency-queries/visibility.ql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/consistency-queries/visibility.ql b/java/ql/consistency-queries/visibility.ql index 8de022f3607..eea402017d5 100644 --- a/java/ql/consistency-queries/visibility.ql +++ b/java/ql/consistency-queries/visibility.ql @@ -10,6 +10,8 @@ string visibility(Method m) { result = "internal" and m.isInternal() } +predicate hasPackagePrivateVisibility(Method m) { not exists(visibility(m)) } + // TODO: This ought to check more than just methods from Method m where @@ -20,5 +22,5 @@ where not m.getName() = "" and count(visibility(m)) != 1 and not (count(visibility(m)) = 2 and visibility(m) = "public" and visibility(m) = "internal") and // This is a reasonable result, since the JVM symbol is declared public, but Kotlin metadata flags it as internal - not (count(visibility(m)) = 0 and m.getName().matches("%$default")) // This is a reasonable result because the $default forwarder methods corresponding to private methods are package-private. + not (hasPackagePrivateVisibility(m) and m.getName().matches("%$default")) // This is a reasonable result because the $default forwarder methods corresponding to private methods are package-private. select m, concat(visibility(m), ", ") From fcf24f7671f0db2b7c791b68392f80eb4f7aab95 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 6 Oct 2022 12:59:43 +0100 Subject: [PATCH 066/107] Fix typo --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 61470c7df52..fc28db0a3b0 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1665,7 +1665,7 @@ open class KotlinFileExtractor( ) ?: pluginContext.irBuiltIns.anyType private fun getDefaultsMethodArgTypes(f: IrFunction) = - // The $default method has type ([extensionReceiver], [dispatchReciever], paramTypes..., int, Object) + // The $default method has type ([extensionReceiver], [dispatchReceiver], paramTypes..., int, Object) // All parameter types are erased. The trailing int is a mask indicating which parameter values are real // and which should be replaced by defaults. The final Object parameter is apparently always null. ( From c1fae91a1f04dab306abf7832bdb0b6d4d6abd46 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Thu, 6 Oct 2022 15:19:11 +0200 Subject: [PATCH 067/107] have rb/meta/taint-steps print only one for each file, to limit the size of the output --- ruby/ql/src/queries/meta/TaintSteps.ql | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ruby/ql/src/queries/meta/TaintSteps.ql b/ruby/ql/src/queries/meta/TaintSteps.ql index dfcf2dc9e77..c86a6ba1d3a 100644 --- a/ruby/ql/src/queries/meta/TaintSteps.ql +++ b/ruby/ql/src/queries/meta/TaintSteps.ql @@ -14,8 +14,10 @@ import codeql.ruby.dataflow.internal.TaintTrackingPublic predicate relevantStep(DataFlow::Node pred, DataFlow::Node succ) { localTaintStep(pred, succ) } -from DataFlow::Node pred, int numOfSuccessors +from File file, int numSteps where - relevantStep(pred, _) and - numOfSuccessors = count(DataFlow::Node succ | relevantStep(pred, succ)) -select pred, "Step to " + numOfSuccessors + " other nodes." + numSteps = + strictcount(DataFlow::Node pred, DataFlow::Node succ | + relevantStep(pred, succ) and pred.getLocation().getFile() = file + ) +select file, "File has " + numSteps + " taint steps." From 289843eb83582e8f665814d1da34a8597188e940 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 6 Oct 2022 16:00:56 +0100 Subject: [PATCH 068/107] Remove accidentally duplicated test This was moved to a unit test, but the integration test version was somehow retained. --- .../kotlin/jvmoverloads_flow/User.java | 39 ---------- .../kotlin/jvmoverloads_flow/test.expected | 19 ----- .../kotlin/jvmoverloads_flow/test.kt | 78 ------------------- .../kotlin/jvmoverloads_flow/test.py | 4 - .../kotlin/jvmoverloads_flow/test.ql | 18 ----- 5 files changed, 158 deletions(-) delete mode 100644 java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/User.java delete mode 100644 java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.expected delete mode 100644 java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.kt delete mode 100644 java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.py delete mode 100644 java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.ql diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/User.java b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/User.java deleted file mode 100644 index a5bc5ccfeee..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/User.java +++ /dev/null @@ -1,39 +0,0 @@ -public class User { - - public static String source() { return "taint"; } - - public static void test(Test2 t2, GenericTest gt) { - - Test.taintSuppliedAsDefault(1, "no taint", 2); - Test.taintSuppliedAsDefault(1, 2); - Test.noTaintByDefault(1, source(), 2, 3); - Test.noTaintByDefault(1, source(), 2); - - Test2.taintSuppliedAsDefaultStatic(1, "no taint", 2); - Test2.taintSuppliedAsDefaultStatic(1, 2); - Test2.noTaintByDefaultStatic(1, source(), 2, 3); - Test2.noTaintByDefaultStatic(1, source(), 2); - - t2.taintSuppliedAsDefault(1, "no taint", 2); - t2.taintSuppliedAsDefault(1, 2); - t2.noTaintByDefault(1, source(), 2, 3); - t2.noTaintByDefault(1, source(), 2); - - gt.taintSuppliedAsDefault(1, "no taint", 2); - gt.taintSuppliedAsDefault(1, 2); - gt.noTaintByDefault(1, source(), 2, 3); - gt.noTaintByDefault(1, source(), 2); - - new ConstructorTaintsByDefault(1, "no taint", 2); - new ConstructorTaintsByDefault(1, 2); - new ConstructorDoesNotTaintByDefault(1, source(), 2, 3); - new ConstructorDoesNotTaintByDefault(1, source(), 2); - - new GenericConstructorTaintsByDefault(1, "no taint", 2); - new GenericConstructorTaintsByDefault(1, 2); - new GenericConstructorDoesNotTaintByDefault(1, source(), 2, 3); - new GenericConstructorDoesNotTaintByDefault(1, source(), 2); - - } - -} diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.expected b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.expected deleted file mode 100644 index 6d9ee0d2718..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.expected +++ /dev/null @@ -1,19 +0,0 @@ -| User.java:9:30:9:37 | source(...) | test.kt:13:97:13:97 | s | -| User.java:10:30:10:37 | source(...) | test.kt:13:97:13:97 | s | -| User.java:14:37:14:44 | source(...) | test.kt:25:105:25:105 | s | -| User.java:15:37:15:44 | source(...) | test.kt:25:105:25:105 | s | -| User.java:19:28:19:35 | source(...) | test.kt:33:97:33:97 | s | -| User.java:20:28:20:35 | source(...) | test.kt:33:97:33:97 | s | -| User.java:24:28:24:35 | source(...) | test.kt:43:93:43:93 | s | -| User.java:25:28:25:35 | source(...) | test.kt:43:93:43:93 | s | -| User.java:29:45:29:52 | source(...) | test.kt:58:10:58:10 | s | -| User.java:30:45:30:52 | source(...) | test.kt:58:10:58:10 | s | -| User.java:34:61:34:68 | source(...) | test.kt:74:10:74:10 | s | -| User.java:35:61:35:68 | source(...) | test.kt:74:10:74:10 | s | -| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | -| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | -| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | -| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | -| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | -| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | -| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.kt b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.kt deleted file mode 100644 index a0e43a6717d..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.kt +++ /dev/null @@ -1,78 +0,0 @@ -fun getString() = "Hello world" - -fun source() = "tainted" - -fun sink(s: String) { } - -object Test { - - @JvmOverloads @JvmStatic - fun taintSuppliedAsDefault(before: Int, s: String = source(), after: Int) { sink(s) } - - @JvmOverloads @JvmStatic - fun noTaintByDefault(before: Int, s: String = "no taint", after: Int, after2: Int = 1) { sink(s) } - -} - -public class Test2 { - - companion object { - - @JvmOverloads @JvmStatic - fun taintSuppliedAsDefaultStatic(before: Int, s: String = source(), after: Int) { sink(s) } - - @JvmOverloads @JvmStatic - fun noTaintByDefaultStatic(before: Int, s: String = "no taint", after: Int, after2: Int = 1) { sink(s) } - - } - - @JvmOverloads - fun taintSuppliedAsDefault(before: Int, s: String = source(), after: Int) { sink(s) } - - @JvmOverloads - fun noTaintByDefault(before: Int, s: String = "no taint", after: Int, after2: Int = 1) { sink(s) } - -} - -public class GenericTest { - - @JvmOverloads - fun taintSuppliedAsDefault(before: T, s: String = source(), after: T) { sink(s) } - - @JvmOverloads - fun noTaintByDefault(before: T, s: String = "no taint", after: T, after2: Int = 1) { sink(s) } - -} - -public class ConstructorTaintsByDefault @JvmOverloads constructor(before: Int, s: String = source(), after: Int) { - - init { - sink(s) - } - -} - -public class ConstructorDoesNotTaintByDefault @JvmOverloads constructor(before: Int, s: String = "no taint", after: Int, after2: Int = 1) { - - init { - sink(s) - } - -} - -public class GenericConstructorTaintsByDefault @JvmOverloads constructor(before: T, s: String = source(), after: T) { - - init { - sink(s) - } - -} - -public class GenericConstructorDoesNotTaintByDefault @JvmOverloads constructor(before: T, s: String = "no taint", after: T, after2: T? = null) { - - init { - sink(s) - } - -} - diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.py b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.py deleted file mode 100644 index 507cd38a68c..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.py +++ /dev/null @@ -1,4 +0,0 @@ -from create_database_utils import * - -os.mkdir('kbuild') -run_codeql_database_create(["kotlinc test.kt -d kbuild", "javac User.java -cp kbuild"], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.ql b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.ql deleted file mode 100644 index 4ed01f80da8..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.ql +++ /dev/null @@ -1,18 +0,0 @@ -import java -import semmle.code.java.dataflow.DataFlow - -class Config extends DataFlow::Configuration { - Config() { this = "config" } - - override predicate isSource(DataFlow::Node n) { - n.asExpr().(MethodAccess).getCallee().getName() = "source" - } - - override predicate isSink(DataFlow::Node n) { - n.asExpr().(Argument).getCall().getCallee().getName() = "sink" - } -} - -from Config c, DataFlow::Node source, DataFlow::Node sink -where c.hasFlow(source, sink) -select source, sink From a02dcdc5e16430e93de2bc6b0d9083af1a996e5c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 7 Oct 2022 02:20:28 +0000 Subject: [PATCH 069/107] Release preparation for version 2.11.1 --- cpp/ql/lib/CHANGELOG.md | 4 ++++ cpp/ql/lib/change-notes/released/0.4.1.md | 3 +++ cpp/ql/lib/codeql-pack.release.yml | 2 +- cpp/ql/lib/qlpack.yml | 2 +- cpp/ql/src/CHANGELOG.md | 6 +++++ .../ql/src/change-notes/released/0.4.1.md | 7 +++--- cpp/ql/src/codeql-pack.release.yml | 2 +- cpp/ql/src/qlpack.yml | 2 +- .../ql/campaigns/Solorigate/lib/CHANGELOG.md | 4 ++++ .../lib/change-notes/released/1.3.1.md | 3 +++ .../Solorigate/lib/codeql-pack.release.yml | 2 +- csharp/ql/campaigns/Solorigate/lib/qlpack.yml | 2 +- .../ql/campaigns/Solorigate/src/CHANGELOG.md | 4 ++++ .../src/change-notes/released/1.3.1.md | 3 +++ .../Solorigate/src/codeql-pack.release.yml | 2 +- csharp/ql/campaigns/Solorigate/src/qlpack.yml | 2 +- csharp/ql/lib/CHANGELOG.md | 7 ++++++ .../2022-09-23-simpletypesanitizer.md | 4 ---- .../0.4.1.md} | 8 ++++--- csharp/ql/lib/codeql-pack.release.yml | 2 +- csharp/ql/lib/qlpack.yml | 2 +- csharp/ql/src/CHANGELOG.md | 6 +++++ .../ql/src/change-notes/released/0.4.1.md | 9 ++++---- csharp/ql/src/codeql-pack.release.yml | 2 +- csharp/ql/src/qlpack.yml | 2 +- go/ql/lib/CHANGELOG.md | 6 +++++ .../0.3.1.md} | 7 +++--- go/ql/lib/codeql-pack.release.yml | 2 +- go/ql/lib/qlpack.yml | 2 +- go/ql/src/CHANGELOG.md | 4 ++++ go/ql/src/change-notes/released/0.3.1.md | 3 +++ go/ql/src/codeql-pack.release.yml | 2 +- go/ql/src/qlpack.yml | 2 +- java/ql/lib/CHANGELOG.md | 6 +++++ .../0.4.1.md} | 7 +++--- java/ql/lib/codeql-pack.release.yml | 2 +- java/ql/lib/qlpack.yml | 2 +- java/ql/src/CHANGELOG.md | 12 ++++++++++ .../change-notes/2022-08-25-path-sanitizer.md | 6 ----- .../2022-08-31-webview-dubugging.md | 4 ---- .../change-notes/2022-09-23-alert-messages.md | 4 ---- java/ql/src/change-notes/released/0.4.1.md | 11 +++++++++ java/ql/src/codeql-pack.release.yml | 2 +- java/ql/src/qlpack.yml | 2 +- javascript/ql/lib/CHANGELOG.md | 7 ++++++ .../0.3.1.md} | 6 ++--- javascript/ql/lib/codeql-pack.release.yml | 2 +- javascript/ql/lib/qlpack.yml | 2 +- javascript/ql/src/CHANGELOG.md | 4 ++++ .../ql/src/change-notes/released/0.4.1.md | 3 +++ javascript/ql/src/codeql-pack.release.yml | 2 +- javascript/ql/src/qlpack.yml | 2 +- misc/suite-helpers/CHANGELOG.md | 4 ++++ .../change-notes/released/0.3.1.md | 3 +++ misc/suite-helpers/codeql-pack.release.yml | 2 +- misc/suite-helpers/qlpack.yml | 2 +- python/ql/lib/CHANGELOG.md | 7 ++++++ .../change-notes/2022-09-22-flask-jsonify.md | 4 ---- .../0.6.1.md} | 8 ++++--- python/ql/lib/codeql-pack.release.yml | 2 +- python/ql/lib/qlpack.yml | 2 +- python/ql/src/CHANGELOG.md | 4 ++++ python/ql/src/change-notes/released/0.5.1.md | 3 +++ python/ql/src/codeql-pack.release.yml | 2 +- python/ql/src/qlpack.yml | 2 +- ruby/ql/lib/CHANGELOG.md | 23 +++++++++++++++++++ .../2022-08-16-protected-methods.md | 5 ---- .../change-notes/2022-08-30-activestorage.md | 6 ----- .../lib/change-notes/2022-09-27-actionview.md | 4 ---- .../2022-09-27-activerecord-create.md | 5 ---- .../2022-09-28-actioncontroller-metal.md | 4 ---- .../2022-09-28-actioncontroller-sendfile.md | 6 ----- ...022-10-04-actionview-controller-renames.md | 11 --------- ruby/ql/lib/change-notes/released/0.4.1.md | 22 ++++++++++++++++++ ruby/ql/lib/codeql-pack.release.yml | 2 +- ruby/ql/lib/qlpack.yml | 2 +- ruby/ql/src/CHANGELOG.md | 8 +++++++ .../0.4.1.md} | 9 ++++---- ruby/ql/src/codeql-pack.release.yml | 2 +- ruby/ql/src/qlpack.yml | 2 +- shared/ssa/CHANGELOG.md | 4 ++++ shared/ssa/change-notes/released/0.0.2.md | 3 +++ shared/ssa/codeql-pack.release.yml | 2 +- shared/ssa/qlpack.yml | 2 +- shared/typos/CHANGELOG.md | 4 ++++ shared/typos/change-notes/released/0.0.2.md | 3 +++ shared/typos/codeql-pack.release.yml | 2 +- shared/typos/qlpack.yml | 2 +- 88 files changed, 257 insertions(+), 127 deletions(-) create mode 100644 cpp/ql/lib/change-notes/released/0.4.1.md rename csharp/ql/src/change-notes/2022-09-29-alert-messages.md => cpp/ql/src/change-notes/released/0.4.1.md (76%) create mode 100644 csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.3.1.md create mode 100644 csharp/ql/campaigns/Solorigate/src/change-notes/released/1.3.1.md delete mode 100644 csharp/ql/lib/change-notes/2022-09-23-simpletypesanitizer.md rename csharp/ql/lib/change-notes/{2022-08-24-aps-net-core-controllers.md => released/0.4.1.md} (65%) rename cpp/ql/src/change-notes/2022-09-23-alert-messages.md => csharp/ql/src/change-notes/released/0.4.1.md (69%) rename go/ql/lib/change-notes/{2022-10-06-beego-request-body-source.md => released/0.3.1.md} (63%) create mode 100644 go/ql/src/change-notes/released/0.3.1.md rename java/ql/lib/change-notes/{2022-09-23-android-service-sources.md => released/0.4.1.md} (66%) delete mode 100644 java/ql/src/change-notes/2022-08-25-path-sanitizer.md delete mode 100644 java/ql/src/change-notes/2022-08-31-webview-dubugging.md delete mode 100644 java/ql/src/change-notes/2022-09-23-alert-messages.md create mode 100644 java/ql/src/change-notes/released/0.4.1.md rename javascript/ql/lib/change-notes/{2022-09-06-type-defs-squashed.md => released/0.3.1.md} (80%) create mode 100644 javascript/ql/src/change-notes/released/0.4.1.md create mode 100644 misc/suite-helpers/change-notes/released/0.3.1.md delete mode 100644 python/ql/lib/change-notes/2022-09-22-flask-jsonify.md rename python/ql/lib/change-notes/{2022-09-28-api-subscript.md => released/0.6.1.md} (69%) create mode 100644 python/ql/src/change-notes/released/0.5.1.md delete mode 100644 ruby/ql/lib/change-notes/2022-08-16-protected-methods.md delete mode 100644 ruby/ql/lib/change-notes/2022-08-30-activestorage.md delete mode 100644 ruby/ql/lib/change-notes/2022-09-27-actionview.md delete mode 100644 ruby/ql/lib/change-notes/2022-09-27-activerecord-create.md delete mode 100644 ruby/ql/lib/change-notes/2022-09-28-actioncontroller-metal.md delete mode 100644 ruby/ql/lib/change-notes/2022-09-28-actioncontroller-sendfile.md delete mode 100644 ruby/ql/lib/change-notes/2022-10-04-actionview-controller-renames.md create mode 100644 ruby/ql/lib/change-notes/released/0.4.1.md rename ruby/ql/src/change-notes/{2022-09-27-libxml-xxe.md => released/0.4.1.md} (80%) create mode 100644 shared/ssa/change-notes/released/0.0.2.md create mode 100644 shared/typos/change-notes/released/0.0.2.md diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md index f1dfa53f9ba..5ccbbd8592c 100644 --- a/cpp/ql/lib/CHANGELOG.md +++ b/cpp/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1 + +No user-facing changes. + ## 0.4.0 ### Deprecated APIs diff --git a/cpp/ql/lib/change-notes/released/0.4.1.md b/cpp/ql/lib/change-notes/released/0.4.1.md new file mode 100644 index 00000000000..0d865d0571e --- /dev/null +++ b/cpp/ql/lib/change-notes/released/0.4.1.md @@ -0,0 +1,3 @@ +## 0.4.1 + +No user-facing changes. diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/cpp/ql/lib/codeql-pack.release.yml +++ b/cpp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index cb70ba272d3..2746ed855a3 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.4.1-dev +version: 0.4.1 groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index 54dec3b197f..8da02215877 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. + ## 0.4.0 ### New Queries diff --git a/csharp/ql/src/change-notes/2022-09-29-alert-messages.md b/cpp/ql/src/change-notes/released/0.4.1.md similarity index 76% rename from csharp/ql/src/change-notes/2022-09-29-alert-messages.md rename to cpp/ql/src/change-notes/released/0.4.1.md index c6ce24514b8..f5e1dbf00ed 100644 --- a/csharp/ql/src/change-notes/2022-09-29-alert-messages.md +++ b/cpp/ql/src/change-notes/released/0.4.1.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- +## 0.4.1 + +### Minor Analysis Improvements + * The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/cpp/ql/src/codeql-pack.release.yml +++ b/cpp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index 12c12ffe83e..5bb1b4e6c67 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.4.1-dev +version: 0.4.1 groups: - cpp - queries diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md index 49d355ec453..afbbf19794a 100644 --- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.1 + +No user-facing changes. + ## 1.3.0 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.3.1.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.3.1.md new file mode 100644 index 00000000000..8dd9964197c --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.3.1.md @@ -0,0 +1,3 @@ +## 1.3.1 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml index ec16350ed6f..e71b6d081f1 100644 --- a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.3.0 +lastReleaseVersion: 1.3.1 diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 648df77d7ff..2bf4479335c 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.3.1-dev +version: 1.3.1 groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md index 49d355ec453..afbbf19794a 100644 --- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.1 + +No user-facing changes. + ## 1.3.0 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.3.1.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.3.1.md new file mode 100644 index 00000000000..8dd9964197c --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.3.1.md @@ -0,0 +1,3 @@ +## 1.3.1 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml index ec16350ed6f..e71b6d081f1 100644 --- a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.3.0 +lastReleaseVersion: 1.3.1 diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 940cdf055f8..d2bd8afddf1 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.3.1-dev +version: 1.3.1 groups: - csharp - solorigate diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index 83b9e7b837c..c303fa86a4a 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* `DateTime` expressions are now considered simple type sanitizers. This affects a wide range of security queries. +* ASP.NET Core controller definition has been made more precise. The amount of introduced taint sources or eliminated false positives should be low though, since the most common pattern is to derive all user defined ASP.NET Core controllers from the standard Controller class, which is not affected. + ## 0.4.0 ### Deprecated APIs diff --git a/csharp/ql/lib/change-notes/2022-09-23-simpletypesanitizer.md b/csharp/ql/lib/change-notes/2022-09-23-simpletypesanitizer.md deleted file mode 100644 index a4d7e4cde7a..00000000000 --- a/csharp/ql/lib/change-notes/2022-09-23-simpletypesanitizer.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* `DateTime` expressions are now considered simple type sanitizers. This affects a wide range of security queries. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2022-08-24-aps-net-core-controllers.md b/csharp/ql/lib/change-notes/released/0.4.1.md similarity index 65% rename from csharp/ql/lib/change-notes/2022-08-24-aps-net-core-controllers.md rename to csharp/ql/lib/change-notes/released/0.4.1.md index b3b5006bc57..f3bdef7797c 100644 --- a/csharp/ql/lib/change-notes/2022-08-24-aps-net-core-controllers.md +++ b/csharp/ql/lib/change-notes/released/0.4.1.md @@ -1,4 +1,6 @@ ---- -category: minorAnalysis ---- +## 0.4.1 + +### Minor Analysis Improvements + +* `DateTime` expressions are now considered simple type sanitizers. This affects a wide range of security queries. * ASP.NET Core controller definition has been made more precise. The amount of introduced taint sources or eliminated false positives should be low though, since the most common pattern is to derive all user defined ASP.NET Core controllers from the standard Controller class, which is not affected. diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/csharp/ql/lib/codeql-pack.release.yml +++ b/csharp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 270ae8a65aa..5d5e75ad307 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.4.1-dev +version: 0.4.1 groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md index bf47d9f7f70..8bd7652a52c 100644 --- a/csharp/ql/src/CHANGELOG.md +++ b/csharp/ql/src/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. + ## 0.4.0 ### Minor Analysis Improvements diff --git a/cpp/ql/src/change-notes/2022-09-23-alert-messages.md b/csharp/ql/src/change-notes/released/0.4.1.md similarity index 69% rename from cpp/ql/src/change-notes/2022-09-23-alert-messages.md rename to csharp/ql/src/change-notes/released/0.4.1.md index de46b7752eb..f5e1dbf00ed 100644 --- a/cpp/ql/src/change-notes/2022-09-23-alert-messages.md +++ b/csharp/ql/src/change-notes/released/0.4.1.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- -* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. \ No newline at end of file +## 0.4.1 + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/csharp/ql/src/codeql-pack.release.yml +++ b/csharp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index e2721c02552..2a80e25d0b6 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.4.1-dev +version: 0.4.1 groups: - csharp - queries diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md index 1f851cdf663..c38ebde0723 100644 --- a/go/ql/lib/CHANGELOG.md +++ b/go/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.3.1 + +### Minor Analysis Improvements + +* Added support for `BeegoInput.RequestBody` as a source of untrusted data. + ## 0.3.0 ### Deprecated APIs diff --git a/go/ql/lib/change-notes/2022-10-06-beego-request-body-source.md b/go/ql/lib/change-notes/released/0.3.1.md similarity index 63% rename from go/ql/lib/change-notes/2022-10-06-beego-request-body-source.md rename to go/ql/lib/change-notes/released/0.3.1.md index 9980b0aadd2..be16eed5d3e 100644 --- a/go/ql/lib/change-notes/2022-10-06-beego-request-body-source.md +++ b/go/ql/lib/change-notes/released/0.3.1.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- +## 0.3.1 + +### Minor Analysis Improvements + * Added support for `BeegoInput.RequestBody` as a source of untrusted data. diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml index 95f6e3a0ba6..bb106b1cb63 100644 --- a/go/ql/lib/codeql-pack.release.yml +++ b/go/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.0 +lastReleaseVersion: 0.3.1 diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index 8025056129c..cd565f720c5 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.3.1-dev +version: 0.3.1 groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md index 47dabdb2d2e..68880b18281 100644 --- a/go/ql/src/CHANGELOG.md +++ b/go/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1 + +No user-facing changes. + ## 0.3.0 ### Query Metadata Changes diff --git a/go/ql/src/change-notes/released/0.3.1.md b/go/ql/src/change-notes/released/0.3.1.md new file mode 100644 index 00000000000..9fd4efd6c80 --- /dev/null +++ b/go/ql/src/change-notes/released/0.3.1.md @@ -0,0 +1,3 @@ +## 0.3.1 + +No user-facing changes. diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml index 95f6e3a0ba6..bb106b1cb63 100644 --- a/go/ql/src/codeql-pack.release.yml +++ b/go/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.0 +lastReleaseVersion: 0.3.1 diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index f454b5ce9d9..4a85f9fe6f3 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.3.1-dev +version: 0.3.1 groups: - go - queries diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md index 0f9512eabda..2724a6d3cef 100644 --- a/java/ql/lib/CHANGELOG.md +++ b/java/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* Added external flow sources for the intents received in exported Android services. + ## 0.4.0 ### Breaking Changes diff --git a/java/ql/lib/change-notes/2022-09-23-android-service-sources.md b/java/ql/lib/change-notes/released/0.4.1.md similarity index 66% rename from java/ql/lib/change-notes/2022-09-23-android-service-sources.md rename to java/ql/lib/change-notes/released/0.4.1.md index 812ff07422d..866a6cf524b 100644 --- a/java/ql/lib/change-notes/2022-09-23-android-service-sources.md +++ b/java/ql/lib/change-notes/released/0.4.1.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- +## 0.4.1 + +### Minor Analysis Improvements + * Added external flow sources for the intents received in exported Android services. diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/java/ql/lib/codeql-pack.release.yml +++ b/java/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index df1ad196123..3d5ea96dcc0 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.4.1-dev +version: 0.4.1 groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md index 4f6633176f4..055d1327b06 100644 --- a/java/ql/src/CHANGELOG.md +++ b/java/ql/src/CHANGELOG.md @@ -1,3 +1,15 @@ +## 0.4.1 + +### New Queries + +* Added a new query, `java/android/webview-debugging-enabled`, to detect instances of WebView debugging being enabled in production builds. + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. +* `PathSanitizer.qll` has been promoted from experimental to the main query pack. This sanitizer was originally [submitted as part of an experimental query by @luchua-bc](https://github.com/github/codeql/pull/7286). +* The queries `java/path-injection`, `java/path-injection-local` and `java/zipslip` now use the sanitizers provided by `PathSanitizer.qll`. + ## 0.4.0 ### New Queries diff --git a/java/ql/src/change-notes/2022-08-25-path-sanitizer.md b/java/ql/src/change-notes/2022-08-25-path-sanitizer.md deleted file mode 100644 index a883561d59c..00000000000 --- a/java/ql/src/change-notes/2022-08-25-path-sanitizer.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -category: minorAnalysis ---- - -* `PathSanitizer.qll` has been promoted from experimental to the main query pack. This sanitizer was originally [submitted as part of an experimental query by @luchua-bc](https://github.com/github/codeql/pull/7286). -* The queries `java/path-injection`, `java/path-injection-local` and `java/zipslip` now use the sanitizers provided by `PathSanitizer.qll`. \ No newline at end of file diff --git a/java/ql/src/change-notes/2022-08-31-webview-dubugging.md b/java/ql/src/change-notes/2022-08-31-webview-dubugging.md deleted file mode 100644 index 8e6295efeb3..00000000000 --- a/java/ql/src/change-notes/2022-08-31-webview-dubugging.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: newQuery ---- -* Added a new query, `java/android/webview-debugging-enabled`, to detect instances of WebView debugging being enabled in production builds. \ No newline at end of file diff --git a/java/ql/src/change-notes/2022-09-23-alert-messages.md b/java/ql/src/change-notes/2022-09-23-alert-messages.md deleted file mode 100644 index de46b7752eb..00000000000 --- a/java/ql/src/change-notes/2022-09-23-alert-messages.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. \ No newline at end of file diff --git a/java/ql/src/change-notes/released/0.4.1.md b/java/ql/src/change-notes/released/0.4.1.md new file mode 100644 index 00000000000..0ac482407a7 --- /dev/null +++ b/java/ql/src/change-notes/released/0.4.1.md @@ -0,0 +1,11 @@ +## 0.4.1 + +### New Queries + +* Added a new query, `java/android/webview-debugging-enabled`, to detect instances of WebView debugging being enabled in production builds. + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. +* `PathSanitizer.qll` has been promoted from experimental to the main query pack. This sanitizer was originally [submitted as part of an experimental query by @luchua-bc](https://github.com/github/codeql/pull/7286). +* The queries `java/path-injection`, `java/path-injection-local` and `java/zipslip` now use the sanitizers provided by `PathSanitizer.qll`. diff --git a/java/ql/src/codeql-pack.release.yml b/java/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/java/ql/src/codeql-pack.release.yml +++ b/java/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 5f93a953ea6..1377facc607 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.4.1-dev +version: 0.4.1 groups: - java - queries diff --git a/javascript/ql/lib/CHANGELOG.md b/javascript/ql/lib/CHANGELOG.md index d85a14dca02..de3424c2f4d 100644 --- a/javascript/ql/lib/CHANGELOG.md +++ b/javascript/ql/lib/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.3.1 + +### Minor Analysis Improvements + +- Several of the SQL and NoSQL library models have improved, leading to more results for the `js/sql-injection` query, + and in some cases the `js/missing-rate-limiting` query. + ## 0.3.0 ### Breaking Changes diff --git a/javascript/ql/lib/change-notes/2022-09-06-type-defs-squashed.md b/javascript/ql/lib/change-notes/released/0.3.1.md similarity index 80% rename from javascript/ql/lib/change-notes/2022-09-06-type-defs-squashed.md rename to javascript/ql/lib/change-notes/released/0.3.1.md index 9e628b394dc..81c8ef9fcff 100644 --- a/javascript/ql/lib/change-notes/2022-09-06-type-defs-squashed.md +++ b/javascript/ql/lib/change-notes/released/0.3.1.md @@ -1,6 +1,6 @@ ---- -category: minorAnalysis ---- +## 0.3.1 + +### Minor Analysis Improvements - Several of the SQL and NoSQL library models have improved, leading to more results for the `js/sql-injection` query, and in some cases the `js/missing-rate-limiting` query. diff --git a/javascript/ql/lib/codeql-pack.release.yml b/javascript/ql/lib/codeql-pack.release.yml index 95f6e3a0ba6..bb106b1cb63 100644 --- a/javascript/ql/lib/codeql-pack.release.yml +++ b/javascript/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.0 +lastReleaseVersion: 0.3.1 diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 0cf4b33407a..5fe7be54a20 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 0.3.1-dev +version: 0.3.1 groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/src/CHANGELOG.md b/javascript/ql/src/CHANGELOG.md index a5e41a1e50a..b166176b56f 100644 --- a/javascript/ql/src/CHANGELOG.md +++ b/javascript/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1 + +No user-facing changes. + ## 0.4.0 ### Minor Analysis Improvements diff --git a/javascript/ql/src/change-notes/released/0.4.1.md b/javascript/ql/src/change-notes/released/0.4.1.md new file mode 100644 index 00000000000..0d865d0571e --- /dev/null +++ b/javascript/ql/src/change-notes/released/0.4.1.md @@ -0,0 +1,3 @@ +## 0.4.1 + +No user-facing changes. diff --git a/javascript/ql/src/codeql-pack.release.yml b/javascript/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/javascript/ql/src/codeql-pack.release.yml +++ b/javascript/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 44ac00e5caf..9a7548cadb1 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 0.4.1-dev +version: 0.4.1 groups: - javascript - queries diff --git a/misc/suite-helpers/CHANGELOG.md b/misc/suite-helpers/CHANGELOG.md index 6bd73620860..c93557f5801 100644 --- a/misc/suite-helpers/CHANGELOG.md +++ b/misc/suite-helpers/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1 + +No user-facing changes. + ## 0.3.0 No user-facing changes. diff --git a/misc/suite-helpers/change-notes/released/0.3.1.md b/misc/suite-helpers/change-notes/released/0.3.1.md new file mode 100644 index 00000000000..9fd4efd6c80 --- /dev/null +++ b/misc/suite-helpers/change-notes/released/0.3.1.md @@ -0,0 +1,3 @@ +## 0.3.1 + +No user-facing changes. diff --git a/misc/suite-helpers/codeql-pack.release.yml b/misc/suite-helpers/codeql-pack.release.yml index 95f6e3a0ba6..bb106b1cb63 100644 --- a/misc/suite-helpers/codeql-pack.release.yml +++ b/misc/suite-helpers/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.0 +lastReleaseVersion: 0.3.1 diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index aa0a2693b1d..911d334cc09 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,3 +1,3 @@ name: codeql/suite-helpers -version: 0.3.1-dev +version: 0.3.1 groups: shared diff --git a/python/ql/lib/CHANGELOG.md b/python/ql/lib/CHANGELOG.md index 962c7b5d023..10707d9d391 100644 --- a/python/ql/lib/CHANGELOG.md +++ b/python/ql/lib/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.6.1 + +### Minor Analysis Improvements + +* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for reponse objects). +* Added modeling of creating Flask responses with `flask.jsonify`. + ## 0.6.0 ### Deprecated APIs diff --git a/python/ql/lib/change-notes/2022-09-22-flask-jsonify.md b/python/ql/lib/change-notes/2022-09-22-flask-jsonify.md deleted file mode 100644 index cac16e270f4..00000000000 --- a/python/ql/lib/change-notes/2022-09-22-flask-jsonify.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Added modeling of creating Flask responses with `flask.jsonify`. diff --git a/python/ql/lib/change-notes/2022-09-28-api-subscript.md b/python/ql/lib/change-notes/released/0.6.1.md similarity index 69% rename from python/ql/lib/change-notes/2022-09-28-api-subscript.md rename to python/ql/lib/change-notes/released/0.6.1.md index f14b59d643b..e4ca9748e5f 100644 --- a/python/ql/lib/change-notes/2022-09-28-api-subscript.md +++ b/python/ql/lib/change-notes/released/0.6.1.md @@ -1,4 +1,6 @@ ---- -category: minorAnalysis ---- +## 0.6.1 + +### Minor Analysis Improvements + * Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for reponse objects). +* Added modeling of creating Flask responses with `flask.jsonify`. diff --git a/python/ql/lib/codeql-pack.release.yml b/python/ql/lib/codeql-pack.release.yml index a3f820f884d..80fb0899f64 100644 --- a/python/ql/lib/codeql-pack.release.yml +++ b/python/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.6.0 +lastReleaseVersion: 0.6.1 diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 6121fdace8c..2104997ba95 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 0.6.1-dev +version: 0.6.1 groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/src/CHANGELOG.md b/python/ql/src/CHANGELOG.md index b26aede7b0b..aaf184f4e7c 100644 --- a/python/ql/src/CHANGELOG.md +++ b/python/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.1 + +No user-facing changes. + ## 0.5.0 ### Query Metadata Changes diff --git a/python/ql/src/change-notes/released/0.5.1.md b/python/ql/src/change-notes/released/0.5.1.md new file mode 100644 index 00000000000..0275d38f63c --- /dev/null +++ b/python/ql/src/change-notes/released/0.5.1.md @@ -0,0 +1,3 @@ +## 0.5.1 + +No user-facing changes. diff --git a/python/ql/src/codeql-pack.release.yml b/python/ql/src/codeql-pack.release.yml index 30e271c5361..0bf7024c337 100644 --- a/python/ql/src/codeql-pack.release.yml +++ b/python/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.0 +lastReleaseVersion: 0.5.1 diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 6e3e2010677..4f57ea416ec 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 0.5.1-dev +version: 0.5.1 groups: - python - queries diff --git a/ruby/ql/lib/CHANGELOG.md b/ruby/ql/lib/CHANGELOG.md index 1a96d857e7f..677403b9a16 100644 --- a/ruby/ql/lib/CHANGELOG.md +++ b/ruby/ql/lib/CHANGELOG.md @@ -1,3 +1,26 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The following classes have been moved from `codeql.ruby.frameworks.ActionController` to `codeql.ruby.frameworks.Rails`: + * `ParamsCall`, now accessed as `Rails::ParamsCall`. + * `CookieCall`, now accessed as `Rails::CookieCall`. +* The following classes have been moved from `codeql.ruby.frameworks.ActionView` to `codeql.ruby.frameworks.Rails`: + * `HtmlSafeCall`, now accessed as `Rails::HtmlSafeCall`. + * `HtmlEscapeCall`, now accessed as `Rails::HtmlEscapeCall`. + * `RenderCall`, now accessed as `Rails::RenderCall`. + * `RenderToCall`, now accessed as `Rails::RenderToCall`. +* Subclasses of `ActionController::Metal` are now recognised as controllers. +* `ActionController::DataStreaming::send_file` is now recognized as a + `FileSystemAccess`. +* Various XSS sinks in the ActionView library are now recognized. +* Calls to `ActiveRecord::Base.create` are now recognized as model + instantiations. +* Various code executions, command executions and HTTP requests in the + ActiveStorage library are now recognized. +* `MethodBase` now has two new predicates related to visibility: `isPublic` and + `isProtected`. These hold, respectively, if the method is public or protected. + ## 0.4.0 ### Breaking Changes diff --git a/ruby/ql/lib/change-notes/2022-08-16-protected-methods.md b/ruby/ql/lib/change-notes/2022-08-16-protected-methods.md deleted file mode 100644 index 7647517c06c..00000000000 --- a/ruby/ql/lib/change-notes/2022-08-16-protected-methods.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -category: minorAnalysis ---- -* `MethodBase` now has two new predicates related to visibility: `isPublic` and - `isProtected`. These hold, respectively, if the method is public or protected. diff --git a/ruby/ql/lib/change-notes/2022-08-30-activestorage.md b/ruby/ql/lib/change-notes/2022-08-30-activestorage.md deleted file mode 100644 index b5ab9e34479..00000000000 --- a/ruby/ql/lib/change-notes/2022-08-30-activestorage.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -category: minorAnalysis ---- -* Various code executions, command executions and HTTP requests in the - ActiveStorage library are now recognized. - diff --git a/ruby/ql/lib/change-notes/2022-09-27-actionview.md b/ruby/ql/lib/change-notes/2022-09-27-actionview.md deleted file mode 100644 index d8f392971ad..00000000000 --- a/ruby/ql/lib/change-notes/2022-09-27-actionview.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Various XSS sinks in the ActionView library are now recognized. diff --git a/ruby/ql/lib/change-notes/2022-09-27-activerecord-create.md b/ruby/ql/lib/change-notes/2022-09-27-activerecord-create.md deleted file mode 100644 index b16da83f611..00000000000 --- a/ruby/ql/lib/change-notes/2022-09-27-activerecord-create.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -category: minorAnalysis ---- -* Calls to `ActiveRecord::Base.create` are now recognized as model - instantiations. diff --git a/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-metal.md b/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-metal.md deleted file mode 100644 index 4d4e2fef174..00000000000 --- a/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-metal.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Subclasses of `ActionController::Metal` are now recognised as controllers. diff --git a/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-sendfile.md b/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-sendfile.md deleted file mode 100644 index 93bf546f4a5..00000000000 --- a/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-sendfile.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -category: minorAnalysis ---- -* `ActionController::DataStreaming::send_file` is now recognized as a - `FileSystemAccess`. - diff --git a/ruby/ql/lib/change-notes/2022-10-04-actionview-controller-renames.md b/ruby/ql/lib/change-notes/2022-10-04-actionview-controller-renames.md deleted file mode 100644 index f269442dcf4..00000000000 --- a/ruby/ql/lib/change-notes/2022-10-04-actionview-controller-renames.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -category: minorAnalysis ---- -* The following classes have been moved from `codeql.ruby.frameworks.ActionController` to `codeql.ruby.frameworks.Rails`: - * `ParamsCall`, now accessed as `Rails::ParamsCall`. - * `CookieCall`, now accessed as `Rails::CookieCall`. -* The following classes have been moved from `codeql.ruby.frameworks.ActionView` to `codeql.ruby.frameworks.Rails`: - * `HtmlSafeCall`, now accessed as `Rails::HtmlSafeCall`. - * `HtmlEscapeCall`, now accessed as `Rails::HtmlEscapeCall`. - * `RenderCall`, now accessed as `Rails::RenderCall`. - * `RenderToCall`, now accessed as `Rails::RenderToCall`. diff --git a/ruby/ql/lib/change-notes/released/0.4.1.md b/ruby/ql/lib/change-notes/released/0.4.1.md new file mode 100644 index 00000000000..9c492f4ac7e --- /dev/null +++ b/ruby/ql/lib/change-notes/released/0.4.1.md @@ -0,0 +1,22 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The following classes have been moved from `codeql.ruby.frameworks.ActionController` to `codeql.ruby.frameworks.Rails`: + * `ParamsCall`, now accessed as `Rails::ParamsCall`. + * `CookieCall`, now accessed as `Rails::CookieCall`. +* The following classes have been moved from `codeql.ruby.frameworks.ActionView` to `codeql.ruby.frameworks.Rails`: + * `HtmlSafeCall`, now accessed as `Rails::HtmlSafeCall`. + * `HtmlEscapeCall`, now accessed as `Rails::HtmlEscapeCall`. + * `RenderCall`, now accessed as `Rails::RenderCall`. + * `RenderToCall`, now accessed as `Rails::RenderToCall`. +* Subclasses of `ActionController::Metal` are now recognised as controllers. +* `ActionController::DataStreaming::send_file` is now recognized as a + `FileSystemAccess`. +* Various XSS sinks in the ActionView library are now recognized. +* Calls to `ActiveRecord::Base.create` are now recognized as model + instantiations. +* Various code executions, command executions and HTTP requests in the + ActiveStorage library are now recognized. +* `MethodBase` now has two new predicates related to visibility: `isPublic` and + `isProtected`. These hold, respectively, if the method is public or protected. diff --git a/ruby/ql/lib/codeql-pack.release.yml b/ruby/ql/lib/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/ruby/ql/lib/codeql-pack.release.yml +++ b/ruby/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index 97c480b8f6e..8010fd63a50 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 0.4.1-dev +version: 0.4.1 groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/CHANGELOG.md b/ruby/ql/src/CHANGELOG.md index e45d4e8c250..6792b3e61c0 100644 --- a/ruby/ql/src/CHANGELOG.md +++ b/ruby/ql/src/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The `rb/xxe` query has been updated to add the following sinks for XML external entity expansion: + 1. Calls to parse XML using `LibXML` when its `default_substitute_entities` option is enabled. + 2. Uses of the Rails methods `ActiveSupport::XmlMini.parse`, `Hash.from_xml`, and `Hash.from_trusted_xml` when `ActiveSupport::XmlMini` is configured to use `LibXML` as its backend, and its `default_substitute_entities` option is enabled. + ## 0.4.0 ### New Queries diff --git a/ruby/ql/src/change-notes/2022-09-27-libxml-xxe.md b/ruby/ql/src/change-notes/released/0.4.1.md similarity index 80% rename from ruby/ql/src/change-notes/2022-09-27-libxml-xxe.md rename to ruby/ql/src/change-notes/released/0.4.1.md index a3084c62f2a..a3ee4612257 100644 --- a/ruby/ql/src/change-notes/2022-09-27-libxml-xxe.md +++ b/ruby/ql/src/change-notes/released/0.4.1.md @@ -1,6 +1,7 @@ ---- -category: minorAnalysis ---- +## 0.4.1 + +### Minor Analysis Improvements + * The `rb/xxe` query has been updated to add the following sinks for XML external entity expansion: 1. Calls to parse XML using `LibXML` when its `default_substitute_entities` option is enabled. - 2. Uses of the Rails methods `ActiveSupport::XmlMini.parse`, `Hash.from_xml`, and `Hash.from_trusted_xml` when `ActiveSupport::XmlMini` is configured to use `LibXML` as its backend, and its `default_substitute_entities` option is enabled. \ No newline at end of file + 2. Uses of the Rails methods `ActiveSupport::XmlMini.parse`, `Hash.from_xml`, and `Hash.from_trusted_xml` when `ActiveSupport::XmlMini` is configured to use `LibXML` as its backend, and its `default_substitute_entities` option is enabled. diff --git a/ruby/ql/src/codeql-pack.release.yml b/ruby/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/ruby/ql/src/codeql-pack.release.yml +++ b/ruby/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index 66f006ac2d5..344a7b03f93 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 0.4.1-dev +version: 0.4.1 groups: - ruby - queries diff --git a/shared/ssa/CHANGELOG.md b/shared/ssa/CHANGELOG.md index 2c547c365ec..9f2cb351ed0 100644 --- a/shared/ssa/CHANGELOG.md +++ b/shared/ssa/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.2 + +No user-facing changes. + ## 0.0.1 * Initial release. Extracted common SSA code into a library pack to share code between languages. diff --git a/shared/ssa/change-notes/released/0.0.2.md b/shared/ssa/change-notes/released/0.0.2.md new file mode 100644 index 00000000000..5ab250998ed --- /dev/null +++ b/shared/ssa/change-notes/released/0.0.2.md @@ -0,0 +1,3 @@ +## 0.0.2 + +No user-facing changes. diff --git a/shared/ssa/codeql-pack.release.yml b/shared/ssa/codeql-pack.release.yml index c6933410b71..55dc06fbd76 100644 --- a/shared/ssa/codeql-pack.release.yml +++ b/shared/ssa/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.1 +lastReleaseVersion: 0.0.2 diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml index ef21714c8b8..54bf861fa2e 100644 --- a/shared/ssa/qlpack.yml +++ b/shared/ssa/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/ssa -version: 0.0.2-dev +version: 0.0.2 groups: shared library: true diff --git a/shared/typos/CHANGELOG.md b/shared/typos/CHANGELOG.md index 95a5c570ac0..82994494b53 100644 --- a/shared/typos/CHANGELOG.md +++ b/shared/typos/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.2 + +No user-facing changes. + ## 0.0.1 * Initial release. Share the database of common typographical errors between languages. diff --git a/shared/typos/change-notes/released/0.0.2.md b/shared/typos/change-notes/released/0.0.2.md new file mode 100644 index 00000000000..5ab250998ed --- /dev/null +++ b/shared/typos/change-notes/released/0.0.2.md @@ -0,0 +1,3 @@ +## 0.0.2 + +No user-facing changes. diff --git a/shared/typos/codeql-pack.release.yml b/shared/typos/codeql-pack.release.yml index c6933410b71..55dc06fbd76 100644 --- a/shared/typos/codeql-pack.release.yml +++ b/shared/typos/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.1 +lastReleaseVersion: 0.0.2 diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml index 587537220ec..3b52e2e07fb 100644 --- a/shared/typos/qlpack.yml +++ b/shared/typos/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/typos -version: 0.0.2-dev +version: 0.0.2 groups: shared library: true From e9a304bad03176d2b62ed77e6292d5f146509dc3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 7 Oct 2022 09:12:36 +0200 Subject: [PATCH 070/107] Kotlin: Add test for exposed internal representation --- .../ExposeRepresentation/ExposeRepresentation.expected | 1 + .../ExposeRepresentation/ExposeRepresentation.qlref | 1 + .../kotlin/query-tests/ExposeRepresentation/ExposesRep.kt | 3 +++ java/ql/test/kotlin/query-tests/ExposeRepresentation/User.kt | 5 +++++ 4 files changed, 10 insertions(+) create mode 100644 java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected create mode 100644 java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.qlref create mode 100644 java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposesRep.kt create mode 100644 java/ql/test/kotlin/query-tests/ExposeRepresentation/User.kt diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected new file mode 100644 index 00000000000..64b3f15ca4e --- /dev/null +++ b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected @@ -0,0 +1 @@ +| ExposesRep.kt:2:5:2:49 | getStrings | getStrings exposes the internal representation stored in field strings. The value may be modified $@. | User.kt:3:12:3:18 | User.kt:3:12:3:18 | after this call to getStrings | diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.qlref b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.qlref new file mode 100644 index 00000000000..6452bb942d2 --- /dev/null +++ b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.qlref @@ -0,0 +1 @@ +Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposesRep.kt b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposesRep.kt new file mode 100644 index 00000000000..04d8f8f588d --- /dev/null +++ b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposesRep.kt @@ -0,0 +1,3 @@ +class ExposesRep { + val strings: Array = arrayOfNulls(1) +} diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/User.kt b/java/ql/test/kotlin/query-tests/ExposeRepresentation/User.kt new file mode 100644 index 00000000000..aac812be0d0 --- /dev/null +++ b/java/ql/test/kotlin/query-tests/ExposeRepresentation/User.kt @@ -0,0 +1,5 @@ +class User { + fun test1(er: ExposesRep) { + er.strings[0] = "Hello world" + } +} From cd64faf635b207d84f5d680bf6f1aa85ead0a4f3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 7 Oct 2022 09:13:10 +0200 Subject: [PATCH 071/107] Kotlin: ignore properties in `java/internal-representation-exposure` check --- .../Implementation Hiding/ExposeRepresentation.ql | 8 ++++++-- .../ExposeRepresentation/ExposeRepresentation.expected | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql b/java/ql/src/Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql index 8fe3d4e6ba6..9f24744fa0c 100644 --- a/java/ql/src/Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql +++ b/java/ql/src/Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql @@ -120,8 +120,12 @@ predicate exposesByStore(Callable c, Field f, Expr why, string whyText) { from Callable c, Field f, Expr why, string whyText where - exposesByReturn(c, f, why, whyText) or - exposesByStore(c, f, why, whyText) + ( + exposesByReturn(c, f, why, whyText) or + exposesByStore(c, f, why, whyText) + ) and + // Kotlin properties expose internal representation, but it's not accidental, so ignore them + not exists(Property p | p.getBackingField() = f) select c, c.getName() + " exposes the internal representation stored in field " + f.getName() + ". The value may be modified $@.", why.getLocation(), whyText diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected index 64b3f15ca4e..e69de29bb2d 100644 --- a/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected +++ b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected @@ -1 +0,0 @@ -| ExposesRep.kt:2:5:2:49 | getStrings | getStrings exposes the internal representation stored in field strings. The value may be modified $@. | User.kt:3:12:3:18 | User.kt:3:12:3:18 | after this call to getStrings | From f7f12076df9f3d88ebcc8b1a8c9014b67100546d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 7 Oct 2022 09:22:06 +0200 Subject: [PATCH 072/107] Kotlin: Add test case for `::class` type check in `equals` --- .../MissingInstanceofInEquals.expected | 1 + .../kotlin/query-tests/MissingInstanceofInEquals/Test.kt | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected b/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected index e69de29bb2d..304a0f245be 100644 --- a/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected +++ b/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected @@ -0,0 +1 @@ +| Test.kt:10:14:12:5 | equals | This 'equals()' method does not check argument type. | diff --git a/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/Test.kt b/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/Test.kt index 7e8fa2619e2..f6252b5d3f2 100644 --- a/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/Test.kt +++ b/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/Test.kt @@ -5,3 +5,9 @@ data class E(val x: Int) { return (other as? E)?.x == this.x } } + +data class F(val x: Int) { + override fun equals(other: Any?): Boolean { + return other != null && other::class == this::class + } +} From 51f9314a50fbf081a8521ddc08a9cc48ae7b8a44 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 7 Oct 2022 09:22:57 +0200 Subject: [PATCH 073/107] Kotlin: Consider `::class` type check in `equals` --- java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql | 2 ++ .../MissingInstanceofInEquals.expected | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql b/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql index 999edaa0b38..1f05298878a 100644 --- a/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql +++ b/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql @@ -30,6 +30,8 @@ predicate hasTypeTest(Variable v) { or any(SafeCastExpr sce).getExpr() = v.getAnAccess() or + any(ClassExpr c).getExpr() = v.getAnAccess() + or exists(MethodAccess ma | ma.getMethod().getName() = "getClass" and ma.getQualifier() = v.getAnAccess() diff --git a/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected b/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected index 304a0f245be..e69de29bb2d 100644 --- a/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected +++ b/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected @@ -1 +0,0 @@ -| Test.kt:10:14:12:5 | equals | This 'equals()' method does not check argument type. | From f51c13f0c160e00b9b56999abfb5d077f96ea22b Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 7 Oct 2022 09:32:00 +0200 Subject: [PATCH 074/107] Kotlin: Recognize generated files --- java/ql/lib/semmle/code/java/GeneratedFiles.qll | 11 +++++++++-- .../library-tests/GeneratedFiles/Generated.expected | 2 ++ .../kotlin/library-tests/GeneratedFiles/Generated.kt | 3 +++ .../kotlin/library-tests/GeneratedFiles/Generated.ql | 4 ++++ .../library-tests/GeneratedFiles/NonGenerated.kt | 3 +++ .../GeneratedFiles/generated/source/NonGenerated.kt | 1 + .../GeneratedFiles/generated/source/kapt/Generated.kt | 1 + 7 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected create mode 100644 java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.kt create mode 100644 java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.ql create mode 100644 java/ql/test/kotlin/library-tests/GeneratedFiles/NonGenerated.kt create mode 100644 java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/NonGenerated.kt create mode 100644 java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/kapt/Generated.kt diff --git a/java/ql/lib/semmle/code/java/GeneratedFiles.qll b/java/ql/lib/semmle/code/java/GeneratedFiles.qll index a7d1ae628f0..cfd72e02938 100644 --- a/java/ql/lib/semmle/code/java/GeneratedFiles.qll +++ b/java/ql/lib/semmle/code/java/GeneratedFiles.qll @@ -51,9 +51,9 @@ library class MarkerCommentGeneratedFile extends GeneratedFile { /** * A marker comment that indicates that it is in a generated file. */ -private class GeneratedFileMarker extends Top instanceof JavadocElement { +private class GeneratedFileMarker extends Top { GeneratedFileMarker() { - exists(string msg | msg = this.getText() | + exists(string msg | msg = this.(JavadocElement).getText() or msg = this.(KtComment).getText() | msg.regexpMatch("(?i).*\\bGenerated By\\b.*\\bDo not edit\\b.*") or msg.regexpMatch("(?i).*\\bThis (file|class|interface|art[ei]fact) (was|is|(has been)) (?:auto[ -]?)?gener(e?)ated.*") or msg.regexpMatch("(?i).*\\bAny modifications to this file will be lost\\b.*") or @@ -65,3 +65,10 @@ private class GeneratedFileMarker extends Top instanceof JavadocElement { ) } } + +/** + * A file detected as generated by the Kotlin Annotation Processing Tool (kapt). Detection is based on file path. + */ +private class KaptFile extends GeneratedFile { + KaptFile() { this.getRelativePath().matches("%/generated/source/kapt%") } +} diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected new file mode 100644 index 00000000000..0a5b4c6ff29 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected @@ -0,0 +1,2 @@ +| Generated.kt:0:0:0:0 | Generated | +| generated/source/kapt/Generated.kt:0:0:0:0 | Generated | diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.kt b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.kt new file mode 100644 index 00000000000..4aa496a1b7d --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.kt @@ -0,0 +1,3 @@ +// This file was auto generated by me + +class B \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.ql b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.ql new file mode 100644 index 00000000000..131acde1993 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.ql @@ -0,0 +1,4 @@ +import java + +from GeneratedFile f +select f diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/NonGenerated.kt b/java/ql/test/kotlin/library-tests/GeneratedFiles/NonGenerated.kt new file mode 100644 index 00000000000..4fd8af3f7a3 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/NonGenerated.kt @@ -0,0 +1,3 @@ +// This file was not generated + +class A \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/NonGenerated.kt b/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/NonGenerated.kt new file mode 100644 index 00000000000..a7f289eeb2f --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/NonGenerated.kt @@ -0,0 +1 @@ +class D \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/kapt/Generated.kt b/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/kapt/Generated.kt new file mode 100644 index 00000000000..9dccdd5e595 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/kapt/Generated.kt @@ -0,0 +1 @@ +class C \ No newline at end of file From 69fc59930fa25ac322d094da6bd34b8c85fbf6d8 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 7 Oct 2022 10:55:30 +0200 Subject: [PATCH 075/107] Ruby: Add ql doc to `lookupSingletonMethod` --- .../ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll index 355b235e926..f988ea43779 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll @@ -736,6 +736,10 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module ) } +/** + * Holds if `method` is a singleton method named `name`, defined on module + * `m`, or any transitive base class of `m`. + */ pragma[nomagic] private MethodBase lookupSingletonMethod(Module m, string name) { singletonMethodOnModule(result, name, m) From a30b7120a706df9ffbb9a1549d5d89df8fc15a74 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Fri, 7 Oct 2022 11:17:39 +0200 Subject: [PATCH 076/107] fix some more style-guide violations in the alert-messages --- .../src/experimental/CWE-099/TaintedWebClient.ql | 4 ++-- ...ated-security-validations-always-return-true.ql | 5 +++-- .../backdoor/ProcessNameToHashTaintFlow.ql | 4 ++-- ...ecurity-validations-always-return-true.expected | 14 +++++++------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql b/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql index 513c658cf92..8cee95a3d54 100644 --- a/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql +++ b/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql @@ -19,5 +19,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ flows to here and is used in a method of WebClient.", - source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "A method of WebClient depepends on a $@.", source.getNode(), + "user-provided value" diff --git a/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql b/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql index 57561944718..753dfb82999 100644 --- a/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql +++ b/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql @@ -17,5 +17,6 @@ import JsonWebTokenHandlerLib from TokenValidationParametersProperty p, CallableAlwaysReturnsTrueHigherPrecision e where e = p.getAnAssignedValue() -select e, "JsonWebTokenHandler security-sensitive property $@ is being delegated to $@.", p, - p.getQualifiedName().toString(), e, "a callable that always returns \"true\"" +select e, + "JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns \"true\".", + p, p.getQualifiedName().toString() diff --git a/csharp/ql/src/experimental/Security Features/backdoor/ProcessNameToHashTaintFlow.ql b/csharp/ql/src/experimental/Security Features/backdoor/ProcessNameToHashTaintFlow.ql index 14d0cc02e44..5bb8a1dc6e9 100644 --- a/csharp/ql/src/experimental/Security Features/backdoor/ProcessNameToHashTaintFlow.ql +++ b/csharp/ql/src/experimental/Security Features/backdoor/ProcessNameToHashTaintFlow.ql @@ -50,5 +50,5 @@ predicate isSuspiciousPropertyName(PropertyRead pr) { from DataFlow::PathNode src, DataFlow::PathNode sink, DataFlowFromMethodToHash conf where conf.hasFlow(src.getNode(), sink.getNode()) select src.getNode(), src, sink, - "The hash is calculated on the process name $@, may be related to a backdoor. Please review the code for possible malicious intent.", - sink.getNode(), "here" + "The hash is calculated on $@, may be related to a backdoor. Please review the code for possible malicious intent.", + sink.getNode(), "this process name" diff --git a/csharp/ql/test/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.expected b/csharp/ql/test/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.expected index dc224c9586e..a76e9660cec 100644 --- a/csharp/ql/test/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.expected +++ b/csharp/ql/test/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.expected @@ -1,7 +1,7 @@ -| delegation-test.cs:101:63:101:186 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:54:34:54:50 | LifetimeValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.LifetimeValidator | delegation-test.cs:101:63:101:186 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:102:63:102:178 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:102:63:102:178 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:115:63:115:190 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:115:63:115:190 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:116:63:116:180 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:116:63:116:180 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:117:63:117:217 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:117:63:117:217 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:118:63:118:248 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:118:63:118:248 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:119:63:119:177 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:119:63:119:177 | (...) => ... | a callable that always returns "true" | +| delegation-test.cs:101:63:101:186 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:54:34:54:50 | LifetimeValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.LifetimeValidator | +| delegation-test.cs:102:63:102:178 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:115:63:115:190 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:116:63:116:180 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:117:63:117:217 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:118:63:118:248 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:119:63:119:177 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | From 66c97055029b86e2ad8d1a7bc69f559e3bf27bb8 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Fri, 7 Oct 2022 11:19:46 +0200 Subject: [PATCH 077/107] fix some more style-guide violations in the alert-messages --- .../LocalVariableHidesGlobalVariable.ql | 2 +- cpp/ql/src/Likely Bugs/ShortLoopVarName.ql | 4 +- .../CWE/CWE-190/ArithmeticUncontrolled.ql | 2 +- .../LocalVariableHidesGlobalVariable.expected | 2 +- .../LocalVariableHidesGlobalVariable.expected | 10 ++-- .../ShortLoopVarName.expected | 8 +-- .../SAMATE/ArithmeticUncontrolled.expected | 48 ++++++++-------- .../ArithmeticUncontrolled.expected | 56 +++++++++---------- 8 files changed, 66 insertions(+), 66 deletions(-) diff --git a/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql b/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql index 53c96c4beb7..ef9135f1c0a 100644 --- a/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql +++ b/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql @@ -35,4 +35,4 @@ from LocalVariableOrParameter lv, GlobalVariable gv where lv.getName() = gv.getName() and lv.getFile() = gv.getFile() -select lv, lv.type() + gv.getName() + " hides $@ with the same name.", gv, "a global variable" +select lv, lv.type() + gv.getName() + " hides a $@ with the same name.", gv, "global variable" diff --git a/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql b/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql index 87dee3c8e30..298e4c1051a 100644 --- a/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql +++ b/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql @@ -48,5 +48,5 @@ where not coordinatePair(iterationVar, innerVar) select iterationVar, "Iteration variable " + iterationVar.getName() + - " for $@ should have a descriptive name, since there is $@.", outer, "this loop", inner, - "a nested loop" + " for $@ should have a descriptive name, since there is a $@.", outer, "this loop", inner, + "nested loop" diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index 76ee3b60e13..964b2ff33d8 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -135,5 +135,5 @@ where sink.getNode().asExpr() = va and missingGuard(va, effect) select sink.getNode(), source, sink, - "Arithmetic expression depends on an $@, potentially causing an " + effect + ".", + "This arithmetic expression depends on an $@, potentially causing an " + effect + ".", getExpr(source.getNode()), "uncontrolled value" diff --git a/cpp/ql/test/examples/BadLocking/LocalVariableHidesGlobalVariable.expected b/cpp/ql/test/examples/BadLocking/LocalVariableHidesGlobalVariable.expected index 4aaecc3b3bd..531452ba1b4 100644 --- a/cpp/ql/test/examples/BadLocking/LocalVariableHidesGlobalVariable.expected +++ b/cpp/ql/test/examples/BadLocking/LocalVariableHidesGlobalVariable.expected @@ -1 +1 @@ -| UnintendedDeclaration.cpp:65:14:65:20 | definition of myMutex | Local variable myMutex hides $@ with the same name. | UnintendedDeclaration.cpp:40:7:40:13 | myMutex | a global variable | +| UnintendedDeclaration.cpp:65:14:65:20 | definition of myMutex | Local variable myMutex hides a $@ with the same name. | UnintendedDeclaration.cpp:40:7:40:13 | myMutex | global variable | diff --git a/cpp/ql/test/query-tests/Best Practices/Hiding/LocalVariableHidesGlobalVariable/LocalVariableHidesGlobalVariable.expected b/cpp/ql/test/query-tests/Best Practices/Hiding/LocalVariableHidesGlobalVariable/LocalVariableHidesGlobalVariable.expected index 1ad05dacf8b..d79adba14e4 100644 --- a/cpp/ql/test/query-tests/Best Practices/Hiding/LocalVariableHidesGlobalVariable/LocalVariableHidesGlobalVariable.expected +++ b/cpp/ql/test/query-tests/Best Practices/Hiding/LocalVariableHidesGlobalVariable/LocalVariableHidesGlobalVariable.expected @@ -1,5 +1,5 @@ -| Hiding.c:22:25:22:26 | definition of gi | Local variable gi hides $@ with the same name. | Hiding.c:2:5:2:6 | gi | a global variable | -| Hiding.c:23:25:23:26 | definition of gj | Local variable gj hides $@ with the same name. | Hiding.c:3:12:3:13 | gj | a global variable | -| Hiding.c:24:25:24:26 | definition of gk | Local variable gk hides $@ with the same name. | Hiding.c:4:12:4:13 | gk | a global variable | -| Hiding.c:37:20:37:21 | definition of g3 | Parameter g3 hides $@ with the same name. | Hiding.c:33:13:33:14 | g3 | a global variable | -| Hiding.c:40:20:40:21 | definition of g5 | Parameter g5 hides $@ with the same name. | Hiding.c:33:21:33:22 | g5 | a global variable | +| Hiding.c:22:25:22:26 | definition of gi | Local variable gi hides a $@ with the same name. | Hiding.c:2:5:2:6 | gi | global variable | +| Hiding.c:23:25:23:26 | definition of gj | Local variable gj hides a $@ with the same name. | Hiding.c:3:12:3:13 | gj | global variable | +| Hiding.c:24:25:24:26 | definition of gk | Local variable gk hides a $@ with the same name. | Hiding.c:4:12:4:13 | gk | global variable | +| Hiding.c:37:20:37:21 | definition of g3 | Parameter g3 hides a $@ with the same name. | Hiding.c:33:13:33:14 | g3 | global variable | +| Hiding.c:40:20:40:21 | definition of g5 | Parameter g5 hides a $@ with the same name. | Hiding.c:33:21:33:22 | g5 | global variable | diff --git a/cpp/ql/test/query-tests/Likely Bugs/ShortLoopVarName/ShortLoopVarName.expected b/cpp/ql/test/query-tests/Likely Bugs/ShortLoopVarName/ShortLoopVarName.expected index 16c5690bf75..22b1f8f4456 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/ShortLoopVarName/ShortLoopVarName.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/ShortLoopVarName/ShortLoopVarName.expected @@ -1,4 +1,4 @@ -| ShortLoopVarName.cpp:6:6:6:6 | i | Iteration variable i for $@ should have a descriptive name, since there is $@. | ShortLoopVarName.cpp:12:2:18:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:14:3:17:3 | for(...;...;...) ... | a nested loop | -| ShortLoopVarName.cpp:30:13:30:13 | a | Iteration variable a for $@ should have a descriptive name, since there is $@. | ShortLoopVarName.cpp:30:2:38:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:34:3:37:3 | for(...;...;...) ... | a nested loop | -| ShortLoopVarName.cpp:73:11:73:11 | y | Iteration variable y for $@ should have a descriptive name, since there is $@. | ShortLoopVarName.cpp:73:2:80:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:75:3:79:3 | for(...;...;...) ... | a nested loop | -| ShortLoopVarName.cpp:96:12:96:12 | i | Iteration variable i for $@ should have a descriptive name, since there is $@. | ShortLoopVarName.cpp:96:3:102:3 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:98:4:101:4 | for(...;...;...) ... | a nested loop | +| ShortLoopVarName.cpp:6:6:6:6 | i | Iteration variable i for $@ should have a descriptive name, since there is a $@. | ShortLoopVarName.cpp:12:2:18:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:14:3:17:3 | for(...;...;...) ... | nested loop | +| ShortLoopVarName.cpp:30:13:30:13 | a | Iteration variable a for $@ should have a descriptive name, since there is a $@. | ShortLoopVarName.cpp:30:2:38:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:34:3:37:3 | for(...;...;...) ... | nested loop | +| ShortLoopVarName.cpp:73:11:73:11 | y | Iteration variable y for $@ should have a descriptive name, since there is a $@. | ShortLoopVarName.cpp:73:2:80:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:75:3:79:3 | for(...;...;...) ... | nested loop | +| ShortLoopVarName.cpp:96:12:96:12 | i | Iteration variable i for $@ should have a descriptive name, since there is a $@. | ShortLoopVarName.cpp:96:3:102:3 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:98:4:101:4 | for(...;...;...) ... | nested loop | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected index b672d501c5e..3834d769463 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected @@ -52,27 +52,27 @@ nodes | examples.cpp:38:9:38:12 | data | semmle.label | data | subpaths #select -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected index efec436a131..011f8f73819 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected @@ -92,31 +92,31 @@ nodes | test.cpp:219:8:219:8 | x | semmle.label | x | subpaths #select -| test.c:21:17:21:17 | r | test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | uncontrolled value | -| test.c:35:5:35:5 | r | test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | uncontrolled value | -| test.c:45:5:45:5 | r | test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | uncontrolled value | -| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:75:13:75:19 | call to rand | uncontrolled value | -| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:75:13:75:19 | call to rand | uncontrolled value | -| test.c:83:9:83:9 | r | test.c:81:14:81:17 | call to rand | test.c:83:9:83:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:81:14:81:17 | call to rand | uncontrolled value | -| test.c:83:9:83:9 | r | test.c:81:23:81:26 | call to rand | test.c:83:9:83:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:81:23:81:26 | call to rand | uncontrolled value | -| test.c:127:9:127:9 | r | test.c:125:13:125:16 | call to rand | test.c:127:9:127:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:125:13:125:16 | call to rand | uncontrolled value | -| test.c:133:5:133:5 | r | test.c:131:13:131:16 | call to rand | test.c:133:5:133:5 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:131:13:131:16 | call to rand | uncontrolled value | -| test.c:139:10:139:10 | r | test.c:137:13:137:16 | call to rand | test.c:139:10:139:10 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:137:13:137:16 | call to rand | uncontrolled value | -| test.c:157:9:157:9 | r | test.c:155:22:155:25 | call to rand | test.c:157:9:157:9 | r | Arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | -| test.c:157:9:157:9 | r | test.c:155:22:155:27 | (unsigned int)... | test.c:157:9:157:9 | r | Arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | -| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | uncontrolled value | -| test.cpp:31:7:31:7 | r | test.cpp:13:10:13:13 | call to rand | test.cpp:31:7:31:7 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | uncontrolled value | -| test.cpp:37:7:37:7 | r | test.cpp:18:9:18:12 | call to rand | test.cpp:37:7:37:7 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | uncontrolled value | -| test.cpp:90:10:90:10 | x | test.cpp:86:10:86:13 | call to rand | test.cpp:90:10:90:10 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:86:10:86:13 | call to rand | uncontrolled value | -| test.cpp:102:10:102:10 | x | test.cpp:98:10:98:13 | call to rand | test.cpp:102:10:102:10 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:98:10:98:13 | call to rand | uncontrolled value | -| test.cpp:146:9:146:9 | y | test.cpp:137:10:137:13 | call to rand | test.cpp:146:9:146:9 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:137:10:137:13 | call to rand | uncontrolled value | -| test.cpp:154:10:154:10 | b | test.cpp:151:10:151:13 | call to rand | test.cpp:154:10:154:10 | b | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:151:10:151:13 | call to rand | uncontrolled value | -| test.cpp:171:11:171:16 | (int)... | test.cpp:169:11:169:14 | call to rand | test.cpp:171:11:171:16 | (int)... | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | -| test.cpp:171:16:171:16 | y | test.cpp:169:11:169:14 | call to rand | test.cpp:171:16:171:16 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | -| test.cpp:196:7:196:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:196:7:196:7 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | -| test.cpp:198:7:198:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:198:7:198:7 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | -| test.cpp:199:7:199:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:199:7:199:7 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | -| test.cpp:204:7:204:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:204:7:204:7 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | -| test.cpp:205:7:205:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:205:7:205:7 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | -| test.cpp:208:7:208:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:208:7:208:7 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | -| test.cpp:219:8:219:8 | x | test.cpp:215:11:215:14 | call to rand | test.cpp:219:8:219:8 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:215:11:215:14 | call to rand | uncontrolled value | +| test.c:21:17:21:17 | r | test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | uncontrolled value | +| test.c:35:5:35:5 | r | test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | uncontrolled value | +| test.c:45:5:45:5 | r | test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | uncontrolled value | +| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:75:13:75:19 | call to rand | uncontrolled value | +| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:75:13:75:19 | call to rand | uncontrolled value | +| test.c:83:9:83:9 | r | test.c:81:14:81:17 | call to rand | test.c:83:9:83:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:81:14:81:17 | call to rand | uncontrolled value | +| test.c:83:9:83:9 | r | test.c:81:23:81:26 | call to rand | test.c:83:9:83:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:81:23:81:26 | call to rand | uncontrolled value | +| test.c:127:9:127:9 | r | test.c:125:13:125:16 | call to rand | test.c:127:9:127:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:125:13:125:16 | call to rand | uncontrolled value | +| test.c:133:5:133:5 | r | test.c:131:13:131:16 | call to rand | test.c:133:5:133:5 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:131:13:131:16 | call to rand | uncontrolled value | +| test.c:139:10:139:10 | r | test.c:137:13:137:16 | call to rand | test.c:139:10:139:10 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:137:13:137:16 | call to rand | uncontrolled value | +| test.c:157:9:157:9 | r | test.c:155:22:155:25 | call to rand | test.c:157:9:157:9 | r | This arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | +| test.c:157:9:157:9 | r | test.c:155:22:155:27 | (unsigned int)... | test.c:157:9:157:9 | r | This arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | +| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | uncontrolled value | +| test.cpp:31:7:31:7 | r | test.cpp:13:10:13:13 | call to rand | test.cpp:31:7:31:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | uncontrolled value | +| test.cpp:37:7:37:7 | r | test.cpp:18:9:18:12 | call to rand | test.cpp:37:7:37:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | uncontrolled value | +| test.cpp:90:10:90:10 | x | test.cpp:86:10:86:13 | call to rand | test.cpp:90:10:90:10 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:86:10:86:13 | call to rand | uncontrolled value | +| test.cpp:102:10:102:10 | x | test.cpp:98:10:98:13 | call to rand | test.cpp:102:10:102:10 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:98:10:98:13 | call to rand | uncontrolled value | +| test.cpp:146:9:146:9 | y | test.cpp:137:10:137:13 | call to rand | test.cpp:146:9:146:9 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:137:10:137:13 | call to rand | uncontrolled value | +| test.cpp:154:10:154:10 | b | test.cpp:151:10:151:13 | call to rand | test.cpp:154:10:154:10 | b | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:151:10:151:13 | call to rand | uncontrolled value | +| test.cpp:171:11:171:16 | (int)... | test.cpp:169:11:169:14 | call to rand | test.cpp:171:11:171:16 | (int)... | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | +| test.cpp:171:16:171:16 | y | test.cpp:169:11:169:14 | call to rand | test.cpp:171:16:171:16 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | +| test.cpp:196:7:196:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:196:7:196:7 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | +| test.cpp:198:7:198:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:198:7:198:7 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | +| test.cpp:199:7:199:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:199:7:199:7 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | +| test.cpp:204:7:204:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:204:7:204:7 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | +| test.cpp:205:7:205:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:205:7:205:7 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | +| test.cpp:208:7:208:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:208:7:208:7 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | +| test.cpp:219:8:219:8 | x | test.cpp:215:11:215:14 | call to rand | test.cpp:219:8:219:8 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:215:11:215:14 | call to rand | uncontrolled value | From d5c45056bd945835a10328d19aeb2785cc7ea3b0 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Fri, 7 Oct 2022 11:21:01 +0200 Subject: [PATCH 078/107] fix some more style-guide violations in the alert-messages --- .../InsecureRandomnessCustomizations.qll | 4 +-- .../InconsistentCode/WrappedErrorAlwaysNil.ql | 2 +- .../CWE-020/SuspiciousCharacterInRegexp.ql | 2 +- go/ql/src/Security/CWE-117/LogInjection.ql | 2 +- .../Security/CWE-338/InsecureRandomness.ql | 6 ++-- .../src/experimental/CWE-369/DivideByZero.ql | 3 +- .../CWE-400/DatabaseCallInLoop.ql | 2 +- go/ql/src/experimental/CWE-918/SSRF.ql | 2 +- .../IntegerOverflow/IntegerOverflow.ql | 2 +- .../CWE-369/DivideByZero.expected | 12 +++---- .../CWE-400/DatabaseCallInLoop.expected | 6 ++-- go/ql/test/experimental/CWE-918/SSRF.expected | 34 +++++++++---------- .../WrappedErrorAlwaysNil.expected | 8 ++--- .../SuspiciousCharacterInRegexp.expected | 22 ++++++------ .../InsecureRandomness.expected | 10 +++--- 15 files changed, 58 insertions(+), 59 deletions(-) diff --git a/go/ql/lib/semmle/go/security/InsecureRandomnessCustomizations.qll b/go/ql/lib/semmle/go/security/InsecureRandomnessCustomizations.qll index 2cbb350461b..3bc6b5f5eec 100644 --- a/go/ql/lib/semmle/go/security/InsecureRandomnessCustomizations.qll +++ b/go/ql/lib/semmle/go/security/InsecureRandomnessCustomizations.qll @@ -64,7 +64,7 @@ module InsecureRandomness { ) } - override string getKind() { result = "this cryptographic algorithm" } + override string getKind() { result = "This cryptographic algorithm" } } /** @@ -75,7 +75,7 @@ module InsecureRandomness { this.getRoot().(FuncDef).getName().regexpMatch("(?i).*(gen(erate)?|salt|make|mk)Password.*") } - override string getKind() { result = "a password-related function" } + override string getKind() { result = "A password-related function" } } /** Gets a package that implements hash algorithms. */ diff --git a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql index c846ef16303..93889b0a23e 100644 --- a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql +++ b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql @@ -61,4 +61,4 @@ where // } n = DataFlow::BarrierGuard::getABarrierNode() ) -select n, "The first argument to 'errors.Wrap' is always nil" +select n, "The first argument to 'errors.Wrap' is always nil." diff --git a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql index 71ae1ac183a..5c1b4528302 100644 --- a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql +++ b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql @@ -48,5 +48,5 @@ class Config extends DataFlow::Configuration { from Config c, DataFlow::PathNode source, DataFlow::PathNode sink, string report where c.hasFlowPath(source, sink) and c.isSource(source.getNode(), report) -select source, source, sink, "$@ that is $@ contains " + report, source, "A string literal", sink, +select source, source, sink, "This string literal that is $@ contains " + report, sink, "used as a regular expression" diff --git a/go/ql/src/Security/CWE-117/LogInjection.ql b/go/ql/src/Security/CWE-117/LogInjection.ql index 070788af884..dbf0c767bb3 100644 --- a/go/ql/src/Security/CWE-117/LogInjection.ql +++ b/go/ql/src/Security/CWE-117/LogInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from LogInjection::Configuration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Log entry depends on a $@.", source.getNode(), +select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(), "user-provided value" diff --git a/go/ql/src/Security/CWE-338/InsecureRandomness.ql b/go/ql/src/Security/CWE-338/InsecureRandomness.ql index 37ec1c21655..e87bbbae37b 100644 --- a/go/ql/src/Security/CWE-338/InsecureRandomness.ql +++ b/go/ql/src/Security/CWE-338/InsecureRandomness.ql @@ -19,7 +19,7 @@ where cfg.hasFlowPath(source, sink) and cfg.isSink(sink.getNode(), kind) and ( - kind != "a password-related function" + kind != "A password-related function" or sink = min(DataFlow::PathNode sink2, int line | @@ -31,5 +31,5 @@ where ) ) select sink.getNode(), source, sink, - "$@ generated with a cryptographically weak RNG is used in $@.", source.getNode(), - "A random number", sink.getNode(), kind + kind + " depends on a $@ generated with a cryptographically weak RNG.", source.getNode(), + "random number" diff --git a/go/ql/src/experimental/CWE-369/DivideByZero.ql b/go/ql/src/experimental/CWE-369/DivideByZero.ql index 8aa12f7f66e..b2e61bef37d 100644 --- a/go/ql/src/experimental/CWE-369/DivideByZero.ql +++ b/go/ql/src/experimental/CWE-369/DivideByZero.ql @@ -54,5 +54,4 @@ class DivideByZeroCheckConfig extends TaintTracking::Configuration { from DataFlow::PathNode source, DataFlow::PathNode sink, DivideByZeroCheckConfig cfg where cfg.hasFlowPath(source, sink) -select sink, source, sink, "Variable $@ might be zero leading to a division-by-zero panic.", sink, - sink.getNode().toString() +select sink, source, sink, "This variable might be zero leading to a division-by-zero panic." diff --git a/go/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql b/go/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql index 253d598835d..66fb90664ea 100644 --- a/go/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql +++ b/go/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql @@ -66,4 +66,4 @@ query predicate edges(CallGraphNode pred, CallGraphNode succ) { from LoopStmt loop, DatabaseAccess dbAccess where edges*(loop, dbAccess.asExpr()) -select dbAccess, loop, dbAccess, "$@ is called in $@", dbAccess, dbAccess.toString(), loop, "a loop" +select dbAccess, loop, dbAccess, "This calls " + dbAccess.toString() + " in a $@.", loop, "loop" diff --git a/go/ql/src/experimental/CWE-918/SSRF.ql b/go/ql/src/experimental/CWE-918/SSRF.ql index 41c41bb18de..4c14969c35f 100644 --- a/go/ql/src/experimental/CWE-918/SSRF.ql +++ b/go/ql/src/experimental/CWE-918/SSRF.ql @@ -19,4 +19,4 @@ from where cfg.hasFlowPath(source, sink) and request = sink.getNode().(ServerSideRequestForgery::Sink).getARequest() -select request, source, sink, "The URL of this request depends on a user-provided value" +select request, source, sink, "The URL of this request depends on a user-provided value." diff --git a/go/ql/src/experimental/IntegerOverflow/IntegerOverflow.ql b/go/ql/src/experimental/IntegerOverflow/IntegerOverflow.ql index 3a3c6b1d745..ca17228816c 100644 --- a/go/ql/src/experimental/IntegerOverflow/IntegerOverflow.ql +++ b/go/ql/src/experimental/IntegerOverflow/IntegerOverflow.ql @@ -11,4 +11,4 @@ import RangeAnalysis from Expr expr where exprMayOverflow(expr) or exprMayUnderflow(expr) -select expr, "this expression may cause an integer overflow" +select expr, "This expression may cause an integer overflow." diff --git a/go/ql/test/experimental/CWE-369/DivideByZero.expected b/go/ql/test/experimental/CWE-369/DivideByZero.expected index 35a3e399cb7..e80e3295c22 100644 --- a/go/ql/test/experimental/CWE-369/DivideByZero.expected +++ b/go/ql/test/experimental/CWE-369/DivideByZero.expected @@ -24,9 +24,9 @@ nodes | DivideByZero.go:57:17:57:21 | value | semmle.label | value | subpaths #select -| DivideByZero.go:12:16:12:20 | value | DivideByZero.go:10:12:10:16 | selection of URL : pointer type | DivideByZero.go:12:16:12:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:12:16:12:20 | value | value | -| DivideByZero.go:19:16:19:20 | value | DivideByZero.go:17:12:17:16 | selection of URL : pointer type | DivideByZero.go:19:16:19:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:19:16:19:20 | value | value | -| DivideByZero.go:26:16:26:20 | value | DivideByZero.go:24:12:24:16 | selection of URL : pointer type | DivideByZero.go:26:16:26:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:26:16:26:20 | value | value | -| DivideByZero.go:33:16:33:20 | value | DivideByZero.go:31:12:31:16 | selection of URL : pointer type | DivideByZero.go:33:16:33:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:33:16:33:20 | value | value | -| DivideByZero.go:40:16:40:20 | value | DivideByZero.go:38:12:38:16 | selection of URL : pointer type | DivideByZero.go:40:16:40:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:40:16:40:20 | value | value | -| DivideByZero.go:57:17:57:21 | value | DivideByZero.go:54:12:54:16 | selection of URL : pointer type | DivideByZero.go:57:17:57:21 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:57:17:57:21 | value | value | +| DivideByZero.go:12:16:12:20 | value | DivideByZero.go:10:12:10:16 | selection of URL : pointer type | DivideByZero.go:12:16:12:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:19:16:19:20 | value | DivideByZero.go:17:12:17:16 | selection of URL : pointer type | DivideByZero.go:19:16:19:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:26:16:26:20 | value | DivideByZero.go:24:12:24:16 | selection of URL : pointer type | DivideByZero.go:26:16:26:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:33:16:33:20 | value | DivideByZero.go:31:12:31:16 | selection of URL : pointer type | DivideByZero.go:33:16:33:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:40:16:40:20 | value | DivideByZero.go:38:12:38:16 | selection of URL : pointer type | DivideByZero.go:40:16:40:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:57:17:57:21 | value | DivideByZero.go:54:12:54:16 | selection of URL : pointer type | DivideByZero.go:57:17:57:21 | value | This variable might be zero leading to a division-by-zero panic. | diff --git a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected index bb197203f22..074dfaa134f 100644 --- a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected +++ b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected @@ -8,6 +8,6 @@ edges | test.go:24:2:26:2 | for statement | test.go:25:3:25:17 | call to runRunQuery | | test.go:25:3:25:17 | call to runRunQuery | test.go:14:1:16:1 | function declaration | #select -| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | $@ is called in $@ | DatabaseCallInLoop.go:9:3:9:41 | call to First | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | a loop | -| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | $@ is called in $@ | test.go:11:2:11:13 | call to Take | call to Take | test.go:20:2:22:2 | for statement | a loop | -| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | $@ is called in $@ | test.go:11:2:11:13 | call to Take | call to Take | test.go:24:2:26:2 | for statement | a loop | +| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop | +| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop | +| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop | diff --git a/go/ql/test/experimental/CWE-918/SSRF.expected b/go/ql/test/experimental/CWE-918/SSRF.expected index a0b9993a4ca..5fdd1775d3d 100644 --- a/go/ql/test/experimental/CWE-918/SSRF.expected +++ b/go/ql/test/experimental/CWE-918/SSRF.expected @@ -55,20 +55,20 @@ nodes | new-tests.go:96:11:96:46 | ...+... | semmle.label | ...+... | subpaths #select -| builtin.go:22:12:22:63 | call to Get | builtin.go:19:12:19:34 | call to FormValue : string | builtin.go:22:21:22:62 | ...+... | The URL of this request depends on a user-provided value | -| builtin.go:88:12:88:53 | call to Dial | builtin.go:83:21:83:31 | call to Referer : string | builtin.go:88:27:88:40 | untrustedInput | The URL of this request depends on a user-provided value | -| builtin.go:102:13:102:40 | call to DialConfig | builtin.go:97:21:97:31 | call to Referer : string | builtin.go:101:36:101:49 | untrustedInput | The URL of this request depends on a user-provided value | -| builtin.go:114:3:114:39 | call to Dial | builtin.go:111:21:111:31 | call to Referer : string | builtin.go:114:15:114:28 | untrustedInput | The URL of this request depends on a user-provided value | -| builtin.go:132:3:132:62 | call to DialContext | builtin.go:129:21:129:31 | call to Referer : string | builtin.go:132:38:132:51 | untrustedInput | The URL of this request depends on a user-provided value | -| new-tests.go:31:2:31:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:31:11:31:57 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:32:2:32:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:32:11:32:57 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:35:3:35:59 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:35:12:35:58 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:47:2:47:47 | call to Get | new-tests.go:39:18:39:30 | call to Param : string | new-tests.go:47:11:47:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:50:2:50:47 | call to Get | new-tests.go:49:18:49:30 | call to Query : string | new-tests.go:50:11:50:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:68:2:68:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:68:11:68:57 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:69:2:69:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:69:11:69:57 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:74:3:74:59 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:74:12:74:58 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:79:2:79:47 | call to Get | new-tests.go:78:18:78:24 | selection of URL : pointer type | new-tests.go:79:11:79:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:82:2:82:47 | call to Get | new-tests.go:81:37:81:43 | selection of URL : pointer type | new-tests.go:82:11:82:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:88:2:88:47 | call to Get | new-tests.go:86:10:86:20 | call to Vars : map type | new-tests.go:88:11:88:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:96:2:96:47 | call to Get | new-tests.go:95:18:95:45 | call to URLParam : string | new-tests.go:96:11:96:46 | ...+... | The URL of this request depends on a user-provided value | +| builtin.go:22:12:22:63 | call to Get | builtin.go:19:12:19:34 | call to FormValue : string | builtin.go:22:21:22:62 | ...+... | The URL of this request depends on a user-provided value. | +| builtin.go:88:12:88:53 | call to Dial | builtin.go:83:21:83:31 | call to Referer : string | builtin.go:88:27:88:40 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:102:13:102:40 | call to DialConfig | builtin.go:97:21:97:31 | call to Referer : string | builtin.go:101:36:101:49 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:114:3:114:39 | call to Dial | builtin.go:111:21:111:31 | call to Referer : string | builtin.go:114:15:114:28 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:132:3:132:62 | call to DialContext | builtin.go:129:21:129:31 | call to Referer : string | builtin.go:132:38:132:51 | untrustedInput | The URL of this request depends on a user-provided value. | +| new-tests.go:31:2:31:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:31:11:31:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:32:2:32:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:32:11:32:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:35:3:35:59 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:35:12:35:58 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:47:2:47:47 | call to Get | new-tests.go:39:18:39:30 | call to Param : string | new-tests.go:47:11:47:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:50:2:50:47 | call to Get | new-tests.go:49:18:49:30 | call to Query : string | new-tests.go:50:11:50:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:68:2:68:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:68:11:68:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:69:2:69:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:69:11:69:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:74:3:74:59 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:74:12:74:58 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:79:2:79:47 | call to Get | new-tests.go:78:18:78:24 | selection of URL : pointer type | new-tests.go:79:11:79:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:82:2:82:47 | call to Get | new-tests.go:81:37:81:43 | selection of URL : pointer type | new-tests.go:82:11:82:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:88:2:88:47 | call to Get | new-tests.go:86:10:86:20 | call to Vars : map type | new-tests.go:88:11:88:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:96:2:96:47 | call to Get | new-tests.go:95:18:95:45 | call to URLParam : string | new-tests.go:96:11:96:46 | ...+... | The URL of this request depends on a user-provided value. | diff --git a/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.expected b/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.expected index 4ac2411d7ca..43853d29664 100644 --- a/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.expected +++ b/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.expected @@ -1,4 +1,4 @@ -| WrappedErrorAlwaysNil.go:31:22:31:24 | err | The first argument to 'errors.Wrap' is always nil | -| WrappedErrorAlwaysNil.go:41:14:41:16 | nil | The first argument to 'errors.Wrap' is always nil | -| WrappedErrorAlwaysNil.go:45:14:45:16 | err | The first argument to 'errors.Wrap' is always nil | -| WrappedErrorAlwaysNil.go:49:14:49:21 | localErr | The first argument to 'errors.Wrap' is always nil | +| WrappedErrorAlwaysNil.go:31:22:31:24 | err | The first argument to 'errors.Wrap' is always nil. | +| WrappedErrorAlwaysNil.go:41:14:41:16 | nil | The first argument to 'errors.Wrap' is always nil. | +| WrappedErrorAlwaysNil.go:45:14:45:16 | err | The first argument to 'errors.Wrap' is always nil. | +| WrappedErrorAlwaysNil.go:49:14:49:21 | localErr | The first argument to 'errors.Wrap' is always nil. | diff --git a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected index 130894d0639..cea5780a6c5 100644 --- a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected +++ b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected @@ -13,14 +13,14 @@ nodes | test.go:23:21:23:36 | "hello\\\\\\bworld" | semmle.label | "hello\\\\\\bworld" | subpaths #select -| SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | A string literal | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | used as a regular expression | -| test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:7:21:7:24 | "\\a" | A string literal | test.go:7:21:7:24 | "\\a" | used as a regular expression | -| test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:9:21:9:26 | "\\\\\\a" | A string literal | test.go:9:21:9:26 | "\\\\\\a" | used as a regular expression | -| test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:10:21:10:27 | "x\\\\\\a" | A string literal | test.go:10:21:10:27 | "x\\\\\\a" | used as a regular expression | -| test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:12:21:12:28 | "\\\\\\\\\\a" | A string literal | test.go:12:21:12:28 | "\\\\\\\\\\a" | used as a regular expression | -| test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | A string literal | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | used as a regular expression | -| test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | A string literal | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | used as a regular expression | -| test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:20:21:20:34 | "hello\\aworld" | A string literal | test.go:20:21:20:34 | "hello\\aworld" | used as a regular expression | -| test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:21:21:21:36 | "hello\\\\\\aworld" | A string literal | test.go:21:21:21:36 | "hello\\\\\\aworld" | used as a regular expression | -| test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:22:21:22:34 | "hello\\bworld" | A string literal | test.go:22:21:22:34 | "hello\\bworld" | used as a regular expression | -| test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:23:21:23:36 | "hello\\\\\\bworld" | A string literal | test.go:23:21:23:36 | "hello\\\\\\bworld" | used as a regular expression | +| SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | This string literal that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | used as a regular expression | +| test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:7:21:7:24 | "\\a" | used as a regular expression | +| test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:9:21:9:26 | "\\\\\\a" | used as a regular expression | +| test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:10:21:10:27 | "x\\\\\\a" | used as a regular expression | +| test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:12:21:12:28 | "\\\\\\\\\\a" | used as a regular expression | +| test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | used as a regular expression | +| test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | used as a regular expression | +| test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:20:21:20:34 | "hello\\aworld" | used as a regular expression | +| test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:21:21:21:36 | "hello\\\\\\aworld" | used as a regular expression | +| test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | This string literal that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:22:21:22:34 | "hello\\bworld" | used as a regular expression | +| test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | This string literal that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:23:21:23:36 | "hello\\\\\\bworld" | used as a regular expression | diff --git a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected index be68561ca27..2ba310c6ee1 100644 --- a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected +++ b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected @@ -20,8 +20,8 @@ nodes | sample.go:47:17:47:39 | call to Intn | semmle.label | call to Intn | subpaths #select -| InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | $@ generated with a cryptographically weak RNG is used in $@. | InsecureRandomness.go:12:18:12:40 | call to Intn | A random number | InsecureRandomness.go:12:18:12:40 | call to Intn | a password-related function | -| sample.go:26:25:26:30 | call to Guid | sample.go:15:49:15:61 | call to Uint32 : uint32 | sample.go:26:25:26:30 | call to Guid | $@ generated with a cryptographically weak RNG is used in $@. | sample.go:15:49:15:61 | call to Uint32 | A random number | sample.go:26:25:26:30 | call to Guid | this cryptographic algorithm | -| sample.go:37:25:37:29 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:25:37:29 | nonce | $@ generated with a cryptographically weak RNG is used in $@. | sample.go:34:12:34:40 | call to New | A random number | sample.go:37:25:37:29 | nonce | this cryptographic algorithm | -| sample.go:37:32:37:36 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:32:37:36 | nonce | $@ generated with a cryptographically weak RNG is used in $@. | sample.go:34:12:34:40 | call to New | A random number | sample.go:37:32:37:36 | nonce | this cryptographic algorithm | -| sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | $@ generated with a cryptographically weak RNG is used in $@. | sample.go:43:17:43:39 | call to Intn | A random number | sample.go:43:17:43:39 | call to Intn | a password-related function | +| InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | A password-related function depends on a $@ generated with a cryptographically weak RNG. | InsecureRandomness.go:12:18:12:40 | call to Intn | random number | +| sample.go:26:25:26:30 | call to Guid | sample.go:15:49:15:61 | call to Uint32 : uint32 | sample.go:26:25:26:30 | call to Guid | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:15:49:15:61 | call to Uint32 | random number | +| sample.go:37:25:37:29 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:25:37:29 | nonce | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:34:12:34:40 | call to New | random number | +| sample.go:37:32:37:36 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:32:37:36 | nonce | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:34:12:34:40 | call to New | random number | +| sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | A password-related function depends on a $@ generated with a cryptographically weak RNG. | sample.go:43:17:43:39 | call to Intn | random number | From 9f6240b38c56e7914119431de10905adb098db1e Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 7 Oct 2022 11:22:12 +0200 Subject: [PATCH 079/107] Kotlin: Add test for missing `override` modifier on SAM methods --- .../library-tests/exprs/funcExprs.expected | 169 +++++++++++++++++- .../kotlin/library-tests/exprs/funcExprs.ql | 7 +- 2 files changed, 174 insertions(+), 2 deletions(-) diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected index 8b4da235ba0..997f0b05599 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected @@ -42,7 +42,7 @@ memberRefExprs | kFunctionInvoke.kt:8:44:8:47 | ...::... | kFunctionInvoke.kt:8:44:8:47 | invoke | invoke(java.lang.String) | kFunctionInvoke.kt:8:44:8:47 | new Function1(...) { ... } | | samConversion.kt:5:27:5:31 | ...::... | samConversion.kt:5:27:5:31 | invoke | invoke(int,int) | samConversion.kt:5:27:5:31 | new Function2(...) { ... } | | samConversion.kt:41:13:41:16 | ...::... | samConversion.kt:41:13:41:16 | invoke | invoke(java.lang.Object[]) | samConversion.kt:41:13:41:16 | new FunctionN(...) { ... } | -modifiers +lambda_modifiers | delegatedProperties.kt:6:32:9:9 | ...->... | delegatedProperties.kt:6:32:9:9 | invoke | override, public | | funcExprs.kt:22:26:22:33 | ...->... | funcExprs.kt:22:26:22:33 | invoke | override, public | | funcExprs.kt:23:26:23:33 | ...->... | funcExprs.kt:23:26:23:33 | invoke | override, public | @@ -74,6 +74,173 @@ modifiers | samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | public | | samConversion.kt:46:32:46:44 | ...->... | samConversion.kt:46:32:46:44 | invoke | override, public | | samConversion.kt:58:30:58:45 | ...->... | samConversion.kt:58:30:58:45 | invoke | override, public, suspend | +anon_class_member_modifiers +| delegatedProperties.kt:6:24:9:9 | new KProperty0(...) { ... } | delegatedProperties.kt:6:24:9:9 | get | override, public | +| delegatedProperties.kt:6:24:9:9 | new KProperty0(...) { ... } | delegatedProperties.kt:6:24:9:9 | invoke | override, public | +| delegatedProperties.kt:6:32:9:9 | new Function0(...) { ... } | delegatedProperties.kt:6:32:9:9 | invoke | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | get | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | get | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | invoke | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | invoke | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | set | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | set | override, public | +| delegatedProperties.kt:23:26:23:31 | new KProperty0(...) { ... } | delegatedProperties.kt:23:26:23:31 | get | override, public | +| delegatedProperties.kt:23:26:23:31 | new KProperty0(...) { ... } | delegatedProperties.kt:23:26:23:31 | invoke | override, public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | getCurValue | public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | setCurValue | public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:27:22:27:88 | getValue | override, public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:28:22:30:13 | setValue | override, public | +| delegatedProperties.kt:33:27:33:47 | new KProperty0(...) { ... } | delegatedProperties.kt:33:27:33:47 | get | override, public | +| delegatedProperties.kt:33:27:33:47 | new KProperty0(...) { ... } | delegatedProperties.kt:33:27:33:47 | invoke | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | get | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | get | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | invoke | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | invoke | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | set | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | set | override, public | +| delegatedProperties.kt:39:31:39:51 | new KProperty0(...) { ... } | delegatedProperties.kt:39:31:39:51 | get | override, public | +| delegatedProperties.kt:39:31:39:51 | new KProperty0(...) { ... } | delegatedProperties.kt:39:31:39:51 | get | override, public | +| delegatedProperties.kt:39:31:39:51 | new KProperty0(...) { ... } | delegatedProperties.kt:39:31:39:51 | invoke | override, public | +| delegatedProperties.kt:39:31:39:51 | new KProperty0(...) { ... } | delegatedProperties.kt:39:31:39:51 | invoke | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | get | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | get | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | invoke | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | invoke | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | set | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | set | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | get | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | get | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | invoke | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | invoke | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | set | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | set | override, public | +| delegatedProperties.kt:66:36:66:50 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:66:36:66:50 | get | override, public | +| delegatedProperties.kt:66:36:66:50 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:66:36:66:50 | invoke | override, public | +| delegatedProperties.kt:66:36:66:50 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:66:36:66:50 | set | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | get | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | get | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | invoke | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | invoke | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | set | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | set | override, public | +| delegatedProperties.kt:67:36:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:36:67:53 | get | override, public | +| delegatedProperties.kt:67:36:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:36:67:53 | invoke | override, public | +| delegatedProperties.kt:67:36:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:36:67:53 | set | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | get | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | get | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | invoke | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | invoke | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | set | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | set | override, public | +| delegatedProperties.kt:69:39:69:56 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:69:39:69:56 | get | override, public | +| delegatedProperties.kt:69:39:69:56 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:69:39:69:56 | invoke | override, public | +| delegatedProperties.kt:69:39:69:56 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:69:39:69:56 | set | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | get | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | get | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | invoke | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | invoke | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | set | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | set | override, public | +| delegatedProperties.kt:70:39:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:39:70:59 | get | override, public | +| delegatedProperties.kt:70:39:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:39:70:59 | invoke | override, public | +| delegatedProperties.kt:70:39:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:39:70:59 | set | override, public | +| delegatedProperties.kt:72:36:72:56 | new KProperty1(...) { ... } | delegatedProperties.kt:72:36:72:56 | get | override, public | +| delegatedProperties.kt:72:36:72:56 | new KProperty1(...) { ... } | delegatedProperties.kt:72:36:72:56 | invoke | override, public | +| delegatedProperties.kt:72:39:72:56 | new KProperty0(...) { ... } | delegatedProperties.kt:72:39:72:56 | get | override, public | +| delegatedProperties.kt:72:39:72:56 | new KProperty0(...) { ... } | delegatedProperties.kt:72:39:72:56 | invoke | override, public | +| delegatedProperties.kt:73:36:73:56 | new KProperty1(...) { ... } | delegatedProperties.kt:73:36:73:56 | get | override, public | +| delegatedProperties.kt:73:36:73:56 | new KProperty1(...) { ... } | delegatedProperties.kt:73:36:73:56 | invoke | override, public | +| delegatedProperties.kt:73:39:73:56 | new KProperty1(...) { ... } | delegatedProperties.kt:73:39:73:56 | get | override, public | +| delegatedProperties.kt:73:39:73:56 | new KProperty1(...) { ... } | delegatedProperties.kt:73:39:73:56 | invoke | override, public | +| delegatedProperties.kt:75:39:75:78 | new KProperty1(...) { ... } | delegatedProperties.kt:75:39:75:78 | get | override, public | +| delegatedProperties.kt:75:39:75:78 | new KProperty1(...) { ... } | delegatedProperties.kt:75:39:75:78 | invoke | override, public | +| delegatedProperties.kt:75:42:75:78 | new KProperty0(...) { ... } | delegatedProperties.kt:75:42:75:78 | get | override, public | +| delegatedProperties.kt:75:42:75:78 | new KProperty0(...) { ... } | delegatedProperties.kt:75:42:75:78 | invoke | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | get | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | get | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | invoke | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | invoke | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | set | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | set | override, public | +| delegatedProperties.kt:77:37:77:49 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:77:37:77:49 | get | override, public | +| delegatedProperties.kt:77:37:77:49 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:77:37:77:49 | invoke | override, public | +| delegatedProperties.kt:77:37:77:49 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:77:37:77:49 | set | override, public | +| delegatedProperties.kt:79:18:79:38 | new KProperty1(...) { ... } | delegatedProperties.kt:79:18:79:38 | get | override, public | +| delegatedProperties.kt:79:18:79:38 | new KProperty1(...) { ... } | delegatedProperties.kt:79:18:79:38 | invoke | override, public | +| delegatedProperties.kt:79:21:79:38 | new KProperty0(...) { ... } | delegatedProperties.kt:79:21:79:38 | get | override, public | +| delegatedProperties.kt:79:21:79:38 | new KProperty0(...) { ... } | delegatedProperties.kt:79:21:79:38 | invoke | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | get | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | get | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | invoke | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | invoke | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | set | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | set | override, public | +| delegatedProperties.kt:82:40:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:40:82:54 | get | override, public | +| delegatedProperties.kt:82:40:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:40:82:54 | invoke | override, public | +| delegatedProperties.kt:82:40:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:40:82:54 | set | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | get | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | get | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | invoke | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | invoke | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | set | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | set | override, public | +| delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | get | override, public | +| delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | invoke | override, public | +| delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | set | override, public | +| exprs.kt:189:16:191:9 | new Interface1(...) { ... } | exprs.kt:190:13:190:49 | getA3 | public | +| funcExprs.kt:22:26:22:33 | new Function0(...) { ... } | funcExprs.kt:22:26:22:33 | invoke | override, public | +| funcExprs.kt:23:26:23:33 | new Function0(...) { ... } | funcExprs.kt:23:26:23:33 | invoke | override, public | +| funcExprs.kt:24:26:24:33 | new Function0(...) { ... } | funcExprs.kt:24:26:24:33 | invoke | override, public | +| funcExprs.kt:25:29:25:38 | new Function1(...) { ... } | funcExprs.kt:25:29:25:38 | invoke | override, public | +| funcExprs.kt:26:29:26:34 | new Function1(...) { ... } | funcExprs.kt:26:29:26:34 | invoke | override, public | +| funcExprs.kt:27:29:27:42 | new Function1(...) { ... } | funcExprs.kt:27:29:27:42 | invoke | override, public | +| funcExprs.kt:29:29:29:37 | new Function1(...) { ... } | funcExprs.kt:29:29:29:37 | invoke | override, public | +| funcExprs.kt:30:28:30:50 | new Function2(...) { ... } | funcExprs.kt:30:28:30:50 | invoke | override, public | +| funcExprs.kt:31:28:31:40 | new Function2(...) { ... } | funcExprs.kt:31:28:31:40 | invoke | override, public | +| funcExprs.kt:32:28:32:44 | new Function2(...) { ... } | funcExprs.kt:32:28:32:44 | invoke | override, public | +| funcExprs.kt:33:28:33:51 | new Function1>(...) { ... } | funcExprs.kt:33:28:33:51 | invoke | override, public | +| funcExprs.kt:33:37:33:47 | new Function1(...) { ... } | funcExprs.kt:33:37:33:47 | invoke | override, public | +| funcExprs.kt:35:29:35:112 | new Function22(...) { ... } | funcExprs.kt:35:29:35:112 | invoke | override, public | +| funcExprs.kt:36:29:36:117 | new FunctionN(...) { ... } | funcExprs.kt:36:29:36:117 | invoke | override, public | +| funcExprs.kt:36:29:36:117 | new FunctionN(...) { ... } | funcExprs.kt:36:29:36:117 | invoke | public | +| funcExprs.kt:38:26:38:38 | new Function0(...) { ... } | funcExprs.kt:38:26:38:38 | invoke | override, public | +| funcExprs.kt:39:26:39:36 | new Function0(...) { ... } | funcExprs.kt:39:26:39:36 | invoke | override, public | +| funcExprs.kt:40:29:40:41 | new Function1(...) { ... } | funcExprs.kt:40:29:40:41 | invoke | override, public | +| funcExprs.kt:41:29:41:39 | new Function2(...) { ... } | funcExprs.kt:41:29:41:39 | invoke | override, public | +| funcExprs.kt:42:29:42:33 | new Function1(...) { ... } | funcExprs.kt:42:29:42:33 | invoke | override, public | +| funcExprs.kt:43:28:43:34 | new Function2(...) { ... } | funcExprs.kt:43:28:43:34 | invoke | override, public | +| funcExprs.kt:44:29:44:42 | new Function22(...) { ... } | funcExprs.kt:44:29:44:42 | invoke | override, public | +| funcExprs.kt:45:29:45:42 | new FunctionN(...) { ... } | funcExprs.kt:45:29:45:42 | invoke | override, public | +| funcExprs.kt:46:30:46:41 | new FunctionN(...) { ... } | funcExprs.kt:46:30:46:41 | invoke | override, public | +| funcExprs.kt:49:26:49:32 | new Function0(...) { ... } | funcExprs.kt:49:26:49:32 | invoke | override, public | +| funcExprs.kt:51:8:51:16 | new Function0(...) { ... } | funcExprs.kt:51:8:51:16 | invoke | override, public | +| funcExprs.kt:75:12:75:22 | new Function1>,String>(...) { ... } | funcExprs.kt:75:12:75:22 | invoke | override, public | +| funcExprs.kt:83:31:83:51 | new Function1(...) { ... } | funcExprs.kt:83:31:83:51 | invoke | override, public | +| funcExprs.kt:86:39:86:59 | new Function1(...) { ... } | funcExprs.kt:86:39:86:59 | invoke | override, public, suspend | +| funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | funcExprs.kt:90:15:90:69 | invoke | override, public | +| funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | funcExprs.kt:90:15:90:69 | invoke | public | +| funcExprs.kt:94:15:94:67 | new Function22(...) { ... } | funcExprs.kt:94:15:94:67 | invoke | override, public, suspend | +| kFunctionInvoke.kt:8:44:8:47 | new Function1(...) { ... } | kFunctionInvoke.kt:8:44:8:47 | invoke | override, public | +| samConversion.kt:2:18:2:45 | new IntPredicate(...) { ... } | samConversion.kt:2:18:2:45 | accept | public | +| samConversion.kt:2:31:2:45 | new Function1(...) { ... } | samConversion.kt:2:31:2:45 | invoke | override, public | +| samConversion.kt:4:14:4:42 | new InterfaceFn1(...) { ... } | samConversion.kt:4:14:4:42 | fn1 | public | +| samConversion.kt:4:27:4:42 | new Function2(...) { ... } | samConversion.kt:4:27:4:42 | invoke | override, public | +| samConversion.kt:5:14:5:32 | new InterfaceFn1(...) { ... } | samConversion.kt:5:14:5:32 | fn1 | public | +| samConversion.kt:5:27:5:31 | new Function2(...) { ... } | samConversion.kt:5:27:5:31 | invoke | override, public | +| samConversion.kt:7:13:7:46 | new InterfaceFnExt1(...) { ... } | samConversion.kt:7:13:7:46 | ext | public | +| samConversion.kt:7:29:7:46 | new Function2(...) { ... } | samConversion.kt:7:29:7:46 | invoke | override, public | +| samConversion.kt:9:13:13:6 | new IntPredicate(...) { ... } | samConversion.kt:9:13:13:6 | accept | public | +| samConversion.kt:9:33:11:5 | new Function1(...) { ... } | samConversion.kt:9:33:11:5 | invoke | override, public | +| samConversion.kt:11:12:13:5 | new Function1(...) { ... } | samConversion.kt:11:12:13:5 | invoke | override, public | +| samConversion.kt:41:13:41:16 | new FunctionN(...) { ... } | samConversion.kt:41:13:41:16 | invoke | override, public | +| samConversion.kt:42:13:42:32 | new BigArityPredicate(...) { ... } | samConversion.kt:42:13:42:32 | accept | public | +| samConversion.kt:43:13:45:68 | new BigArityPredicate(...) { ... } | samConversion.kt:43:13:45:68 | accept | public | +| samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | override, public | +| samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | public | +| samConversion.kt:46:13:46:44 | new SomePredicate(...) { ... } | samConversion.kt:46:13:46:44 | fn | public | +| samConversion.kt:46:32:46:44 | new Function1(...) { ... } | samConversion.kt:46:32:46:44 | invoke | override, public | +| samConversion.kt:58:14:58:45 | new InterfaceFn1Sus(...) { ... } | samConversion.kt:58:14:58:45 | fn1 | public, suspend | +| samConversion.kt:58:30:58:45 | new Function2(...) { ... } | samConversion.kt:58:30:58:45 | invoke | override, public, suspend | nonOverrideInvoke | funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | 23 | | funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | 23 | diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql b/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql index fa2b5fda2a2..f6e233336f3 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql @@ -19,11 +19,16 @@ query predicate memberRefExprs(MemberRefExpr e, Method m, string signature, Anon e.getAnonymousClass() = an } -query predicate modifiers(LambdaExpr le, Method m, string modifiers) { +query predicate lambda_modifiers(LambdaExpr le, Method m, string modifiers) { le.getAnonymousClass().getAMethod() = m and modifiers = concat(string s | m.hasModifier(s) | s, ", ") } +query predicate anon_class_member_modifiers(AnonymousClass ac, Method m, string modifiers) { + ac.getAMethod() = m and + modifiers = concat(string s | m.hasModifier(s) | s, ", ") +} + query predicate nonOverrideInvoke(LambdaExpr le, Method m, int pCount) { le.getAnonymousClass().getAMethod() = m and not m.hasModifier("override") and From 26c4216fef92b3375e1a85a10aa4f31f0113bac7 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 7 Oct 2022 11:23:10 +0200 Subject: [PATCH 080/107] Kotlin: Extract `override` modifier on SAM methods --- .../src/main/kotlin/KotlinFileExtractor.kt | 3 ++- .../library-tests/exprs/funcExprs.expected | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index b7aff59b599..a83dafa1df6 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -4731,7 +4731,7 @@ open class KotlinFileExtractor( class extends Object implements IntPredicate { Function1 ; public (Function1 ) { this. = ; } - public Boolean accept(Integer i) { return .invoke(i); } + public override Boolean accept(Integer i) { return .invoke(i); } } IntPredicate x = (IntPredicate)new (...); @@ -4811,6 +4811,7 @@ open class KotlinFileExtractor( // the real underlying R Function.apply(T t). forceExtractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, typeSub, classTypeArgs, overriddenAttributes = OverriddenFunctionAttributes(id = ids.function, sourceLoc = tw.getLocation(e))) + addModifiers(ids.function, "override") if (st.isSuspendFunctionOrKFunction()) { addModifiers(ids.function, "suspend") } diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected index 997f0b05599..7e636762d16 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected @@ -221,25 +221,25 @@ anon_class_member_modifiers | funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | funcExprs.kt:90:15:90:69 | invoke | public | | funcExprs.kt:94:15:94:67 | new Function22(...) { ... } | funcExprs.kt:94:15:94:67 | invoke | override, public, suspend | | kFunctionInvoke.kt:8:44:8:47 | new Function1(...) { ... } | kFunctionInvoke.kt:8:44:8:47 | invoke | override, public | -| samConversion.kt:2:18:2:45 | new IntPredicate(...) { ... } | samConversion.kt:2:18:2:45 | accept | public | +| samConversion.kt:2:18:2:45 | new IntPredicate(...) { ... } | samConversion.kt:2:18:2:45 | accept | override, public | | samConversion.kt:2:31:2:45 | new Function1(...) { ... } | samConversion.kt:2:31:2:45 | invoke | override, public | -| samConversion.kt:4:14:4:42 | new InterfaceFn1(...) { ... } | samConversion.kt:4:14:4:42 | fn1 | public | +| samConversion.kt:4:14:4:42 | new InterfaceFn1(...) { ... } | samConversion.kt:4:14:4:42 | fn1 | override, public | | samConversion.kt:4:27:4:42 | new Function2(...) { ... } | samConversion.kt:4:27:4:42 | invoke | override, public | -| samConversion.kt:5:14:5:32 | new InterfaceFn1(...) { ... } | samConversion.kt:5:14:5:32 | fn1 | public | +| samConversion.kt:5:14:5:32 | new InterfaceFn1(...) { ... } | samConversion.kt:5:14:5:32 | fn1 | override, public | | samConversion.kt:5:27:5:31 | new Function2(...) { ... } | samConversion.kt:5:27:5:31 | invoke | override, public | -| samConversion.kt:7:13:7:46 | new InterfaceFnExt1(...) { ... } | samConversion.kt:7:13:7:46 | ext | public | +| samConversion.kt:7:13:7:46 | new InterfaceFnExt1(...) { ... } | samConversion.kt:7:13:7:46 | ext | override, public | | samConversion.kt:7:29:7:46 | new Function2(...) { ... } | samConversion.kt:7:29:7:46 | invoke | override, public | -| samConversion.kt:9:13:13:6 | new IntPredicate(...) { ... } | samConversion.kt:9:13:13:6 | accept | public | +| samConversion.kt:9:13:13:6 | new IntPredicate(...) { ... } | samConversion.kt:9:13:13:6 | accept | override, public | | samConversion.kt:9:33:11:5 | new Function1(...) { ... } | samConversion.kt:9:33:11:5 | invoke | override, public | | samConversion.kt:11:12:13:5 | new Function1(...) { ... } | samConversion.kt:11:12:13:5 | invoke | override, public | | samConversion.kt:41:13:41:16 | new FunctionN(...) { ... } | samConversion.kt:41:13:41:16 | invoke | override, public | -| samConversion.kt:42:13:42:32 | new BigArityPredicate(...) { ... } | samConversion.kt:42:13:42:32 | accept | public | -| samConversion.kt:43:13:45:68 | new BigArityPredicate(...) { ... } | samConversion.kt:43:13:45:68 | accept | public | +| samConversion.kt:42:13:42:32 | new BigArityPredicate(...) { ... } | samConversion.kt:42:13:42:32 | accept | override, public | +| samConversion.kt:43:13:45:68 | new BigArityPredicate(...) { ... } | samConversion.kt:43:13:45:68 | accept | override, public | | samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | override, public | | samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | public | -| samConversion.kt:46:13:46:44 | new SomePredicate(...) { ... } | samConversion.kt:46:13:46:44 | fn | public | +| samConversion.kt:46:13:46:44 | new SomePredicate(...) { ... } | samConversion.kt:46:13:46:44 | fn | override, public | | samConversion.kt:46:32:46:44 | new Function1(...) { ... } | samConversion.kt:46:32:46:44 | invoke | override, public | -| samConversion.kt:58:14:58:45 | new InterfaceFn1Sus(...) { ... } | samConversion.kt:58:14:58:45 | fn1 | public, suspend | +| samConversion.kt:58:14:58:45 | new InterfaceFn1Sus(...) { ... } | samConversion.kt:58:14:58:45 | fn1 | override, public, suspend | | samConversion.kt:58:30:58:45 | new Function2(...) { ... } | samConversion.kt:58:30:58:45 | invoke | override, public, suspend | nonOverrideInvoke | funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | 23 | From bb6e5756898acca2b6fedcd7f5323a49d2d3fc4b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 6 Oct 2022 15:59:33 +0100 Subject: [PATCH 081/107] Kotlin: allow building a single embeddable plugin version --- java/kotlin-extractor/build.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/java/kotlin-extractor/build.py b/java/kotlin-extractor/build.py index a4da1a2ea23..d714c799eed 100755 --- a/java/kotlin-extractor/build.py +++ b/java/kotlin-extractor/build.py @@ -25,6 +25,8 @@ def parse_args(): dest='many', help='Build for a single version/kind') parser.add_argument('--single-version', help='Build for a specific version/kind') + parser.add_argument('--single-version-embeddable', action='store_true', + help='When building a single version, build an embeddable extractor (default is standalone)') return parser.parse_args() @@ -233,12 +235,13 @@ def compile_standalone(version): 'build_standalone_' + version, version) +compile_single_version = compile_embeddable if args.single_version_embeddable == True else compile_standalone if args.single_version: - compile_standalone(args.single_version) + compile_single_version(args.single_version) elif args.many: for version in kotlin_plugin_versions.many_versions: compile_standalone(version) compile_embeddable(version) else: - compile_standalone(kotlin_plugin_versions.get_single_version()) + compile_single_version(kotlin_plugin_versions.get_single_version()) From 5d9c68c962e586f7de0620df4d12379d4224a848 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Fri, 7 Oct 2022 13:21:24 +0200 Subject: [PATCH 082/107] remove the taint-steps meta query --- ruby/ql/src/queries/meta/TaintSteps.ql | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 ruby/ql/src/queries/meta/TaintSteps.ql diff --git a/ruby/ql/src/queries/meta/TaintSteps.ql b/ruby/ql/src/queries/meta/TaintSteps.ql deleted file mode 100644 index c86a6ba1d3a..00000000000 --- a/ruby/ql/src/queries/meta/TaintSteps.ql +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @name Taint steps - * @description All taint steps. - * @kind problem - * @problem.severity recommendation - * @id rb/meta/taint-steps - * @tags meta - * @precision very-low - */ - -import ruby -import internal.TaintMetrics -import codeql.ruby.dataflow.internal.TaintTrackingPublic - -predicate relevantStep(DataFlow::Node pred, DataFlow::Node succ) { localTaintStep(pred, succ) } - -from File file, int numSteps -where - numSteps = - strictcount(DataFlow::Node pred, DataFlow::Node succ | - relevantStep(pred, succ) and pred.getLocation().getFile() = file - ) -select file, "File has " + numSteps + " taint steps." From 2df1d63d1c9c0f3310d91ac54c453feaeed3eaa2 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Oct 2022 12:23:08 +0100 Subject: [PATCH 083/107] Extract the corresponding classes of enum entries, where they exist. --- .../src/main/kotlin/KotlinFileExtractor.kt | 10 ++++-- .../library-tests/methods/clinit.expected | 1 + .../kotlin/library-tests/methods/enumClass.kt | 12 +++++++ .../library-tests/methods/exprs.expected | 31 +++++++++++++++++++ .../library-tests/methods/methods.expected | 9 ++++++ .../library-tests/methods/parameters.expected | 5 +++ 6 files changed, 65 insertions(+), 3 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index fc28db0a3b0..9ff04cf6ade 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -155,7 +155,7 @@ open class KotlinFileExtractor( is IrEnumEntry -> { val parentId = useDeclarationParent(declaration.parent, false)?.cast() if (parentId != null) { - extractEnumEntry(declaration, parentId, extractFunctionBodies) + extractEnumEntry(declaration, parentId, extractPrivateMembers, extractFunctionBodies) } Unit } @@ -1254,7 +1254,7 @@ open class KotlinFileExtractor( } } - private fun extractEnumEntry(ee: IrEnumEntry, parentId: Label, extractTypeAccess: Boolean) { + private fun extractEnumEntry(ee: IrEnumEntry, parentId: Label, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean) { with("enum entry", ee) { DeclarationStackAdjuster(ee).use { val id = useEnumEntry(ee) @@ -1265,7 +1265,7 @@ open class KotlinFileExtractor( tw.writeHasLocation(id, locId) tw.writeIsEnumConst(id) - if (extractTypeAccess) { + if (extractFunctionBodies) { val fieldDeclarationId = tw.getFreshIdLabel() tw.writeFielddecls(fieldDeclarationId, parentId) tw.writeFieldDeclaredIn(id, fieldDeclarationId, 0) @@ -1273,6 +1273,10 @@ open class KotlinFileExtractor( extractTypeAccess(type, locId, fieldDeclarationId, 0) } + + ee.correspondingClass?.let { + extractDeclaration(it, extractPrivateMembers, extractFunctionBodies) + } } } } diff --git a/java/ql/test/kotlin/library-tests/methods/clinit.expected b/java/ql/test/kotlin/library-tests/methods/clinit.expected index ea5b5392d82..3bf5f170f08 100644 --- a/java/ql/test/kotlin/library-tests/methods/clinit.expected +++ b/java/ql/test/kotlin/library-tests/methods/clinit.expected @@ -1,2 +1,3 @@ | clinit.kt:0:0:0:0 | | file://:0:0:0:0 | void | | enumClass.kt:0:0:0:0 | | file://:0:0:0:0 | void | +| enumClass.kt:0:0:0:0 | | file://:0:0:0:0 | void | diff --git a/java/ql/test/kotlin/library-tests/methods/enumClass.kt b/java/ql/test/kotlin/library-tests/methods/enumClass.kt index 89568c0d5f4..9f3acad608a 100644 --- a/java/ql/test/kotlin/library-tests/methods/enumClass.kt +++ b/java/ql/test/kotlin/library-tests/methods/enumClass.kt @@ -2,3 +2,15 @@ enum class EnumClass(val v: Int) { enum1(1), enum2(1) } + +enum class EnumWithFunctions { + + VAL { + override fun f(i: Int) = i + override fun g(i: Int) = this.f(i) + i + }; + + abstract fun f(i: Int): Int + abstract fun g(i: Int): Int + +} diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index 77033a11bbe..bf15f66b6ef 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -226,6 +226,10 @@ | enumClass.kt:0:0:0:0 | EnumClass | TypeAccess | | enumClass.kt:0:0:0:0 | EnumClass | TypeAccess | | enumClass.kt:0:0:0:0 | EnumClass[] | TypeAccess | +| enumClass.kt:0:0:0:0 | EnumWithFunctions | TypeAccess | +| enumClass.kt:0:0:0:0 | EnumWithFunctions | TypeAccess | +| enumClass.kt:0:0:0:0 | EnumWithFunctions[] | TypeAccess | +| enumClass.kt:0:0:0:0 | String | TypeAccess | | enumClass.kt:0:0:0:0 | String | TypeAccess | | enumClass.kt:1:1:4:1 | Enum | TypeAccess | | enumClass.kt:1:1:4:1 | EnumClass | TypeAccess | @@ -252,6 +256,33 @@ | enumClass.kt:3:5:3:12 | EnumClass.enum2 | VarAccess | | enumClass.kt:3:5:3:12 | new EnumClass(...) | ClassInstanceExpr | | enumClass.kt:3:11:3:11 | 1 | IntegerLiteral | +| enumClass.kt:6:1:16:1 | Enum | TypeAccess | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | TypeAccess | +| enumClass.kt:6:1:16:1 | new Enum(...) | ClassInstanceExpr | +| enumClass.kt:8:3:11:4 | ...=... | KtInitializerAssignExpr | +| enumClass.kt:8:3:11:4 | | ImplicitCoercionToUnitExpr | +| enumClass.kt:8:3:11:4 | EnumWithFunctions | TypeAccess | +| enumClass.kt:8:3:11:4 | EnumWithFunctions | TypeAccess | +| enumClass.kt:8:3:11:4 | EnumWithFunctions | TypeAccess | +| enumClass.kt:8:3:11:4 | EnumWithFunctions.VAL | VarAccess | +| enumClass.kt:8:3:11:4 | Unit | TypeAccess | +| enumClass.kt:8:3:11:4 | VAL | TypeAccess | +| enumClass.kt:8:3:11:4 | new EnumWithFunctions(...) | ClassInstanceExpr | +| enumClass.kt:8:3:11:4 | new VAL(...) | ClassInstanceExpr | +| enumClass.kt:9:14:9:30 | int | TypeAccess | +| enumClass.kt:9:20:9:25 | int | TypeAccess | +| enumClass.kt:9:30:9:30 | i | VarAccess | +| enumClass.kt:10:14:10:42 | int | TypeAccess | +| enumClass.kt:10:20:10:25 | int | TypeAccess | +| enumClass.kt:10:30:10:33 | this | ThisAccess | +| enumClass.kt:10:30:10:42 | ... + ... | AddExpr | +| enumClass.kt:10:35:10:38 | f(...) | MethodAccess | +| enumClass.kt:10:37:10:37 | i | VarAccess | +| enumClass.kt:10:42:10:42 | i | VarAccess | +| enumClass.kt:13:12:13:29 | int | TypeAccess | +| enumClass.kt:13:18:13:23 | int | TypeAccess | +| enumClass.kt:14:12:14:29 | int | TypeAccess | +| enumClass.kt:14:18:14:23 | int | TypeAccess | | methods2.kt:4:1:5:1 | Unit | TypeAccess | | methods2.kt:4:26:4:31 | int | TypeAccess | | methods2.kt:4:34:4:39 | int | TypeAccess | diff --git a/java/ql/test/kotlin/library-tests/methods/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index 69c8e1ab214..8ee20aac587 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -29,6 +29,13 @@ methods | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | valueOf | valueOf(java.lang.String) | public, static | Compiler generated | | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | values | values() | public, static | Compiler generated | | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:1:22:1:31 | getV | getV() | public | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | | () | | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | valueOf | valueOf(java.lang.String) | public, static | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | values | values() | public, static | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:13:12:13:29 | f | f(int) | public | | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:14:12:14:29 | g | g(int) | public | | +| enumClass.kt:8:3:11:4 | VAL | enumClass.kt:9:14:9:30 | f | f(int) | override, public | | +| enumClass.kt:8:3:11:4 | VAL | enumClass.kt:10:14:10:42 | g | g(int) | override, public | | | methods2.kt:0:0:0:0 | Methods2Kt | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | fooBarTopLevelMethod(int,int) | public, static | | | methods2.kt:7:1:10:1 | Class2 | methods2.kt:8:5:9:5 | fooBarClassMethod | fooBarClassMethod(int,int) | public | | | methods3.kt:0:0:0:0 | Methods3Kt | methods3.kt:3:1:3:42 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | public, static | | @@ -56,6 +63,8 @@ constructors | delegates.kt:8:32:11:5 | new KMutableProperty1(...) { ... } | delegates.kt:8:32:11:5 | | | | delegates.kt:8:66:11:5 | new Function3,String,String,Unit>(...) { ... } | delegates.kt:8:66:11:5 | | | | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:1:6:4:1 | EnumClass | EnumClass(int) | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:6:6:16:1 | EnumWithFunctions | EnumWithFunctions() | +| enumClass.kt:8:3:11:4 | VAL | enumClass.kt:8:3:11:4 | VAL | VAL() | | methods2.kt:7:1:10:1 | Class2 | methods2.kt:7:1:10:1 | Class2 | Class2() | | methods3.kt:5:1:7:1 | Class3 | methods3.kt:5:1:7:1 | Class3 | Class3() | | methods4.kt:3:1:11:1 | NestedTest | methods4.kt:3:1:11:1 | NestedTest | NestedTest() | diff --git a/java/ql/test/kotlin/library-tests/methods/parameters.expected b/java/ql/test/kotlin/library-tests/methods/parameters.expected index 7e76cdcb55b..4475aeba459 100644 --- a/java/ql/test/kotlin/library-tests/methods/parameters.expected +++ b/java/ql/test/kotlin/library-tests/methods/parameters.expected @@ -23,6 +23,11 @@ | delegates.kt:8:66:11:5 | invoke | delegates.kt:9:15:9:17 | old | 1 | | delegates.kt:8:66:11:5 | invoke | delegates.kt:9:20:9:22 | new | 2 | | enumClass.kt:0:0:0:0 | valueOf | enumClass.kt:0:0:0:0 | value | 0 | +| enumClass.kt:0:0:0:0 | valueOf | enumClass.kt:0:0:0:0 | value | 0 | +| enumClass.kt:9:14:9:30 | f | enumClass.kt:9:20:9:25 | i | 0 | +| enumClass.kt:10:14:10:42 | g | enumClass.kt:10:20:10:25 | i | 0 | +| enumClass.kt:13:12:13:29 | f | enumClass.kt:13:18:13:23 | i | 0 | +| enumClass.kt:14:12:14:29 | g | enumClass.kt:14:18:14:23 | i | 0 | | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:26:4:31 | x | 0 | | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:34:4:39 | y | 1 | | methods2.kt:8:5:9:5 | fooBarClassMethod | methods2.kt:8:27:8:32 | x | 0 | From 99b7c77abc0b85354d7a6675cd8d2bc0c27ecbf2 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Fri, 7 Oct 2022 13:44:36 +0200 Subject: [PATCH 084/107] add change-note --- go/ql/src/change-notes/2022-10-07-alert-messages.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 go/ql/src/change-notes/2022-10-07-alert-messages.md diff --git a/go/ql/src/change-notes/2022-10-07-alert-messages.md b/go/ql/src/change-notes/2022-10-07-alert-messages.md new file mode 100644 index 00000000000..de46b7752eb --- /dev/null +++ b/go/ql/src/change-notes/2022-10-07-alert-messages.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. \ No newline at end of file From a6674a5313a6e2bd5127535266d1a9154f91efd7 Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Fri, 7 Oct 2022 12:49:08 +0100 Subject: [PATCH 085/107] Ruby: fix uses of deprecated class name --- ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll | 2 +- .../frameworks/action_controller/params-flow.ql | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll index 839e197307c..8556c167b5d 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll @@ -392,7 +392,7 @@ private module ParamsSummaries { */ private class ParamsInstance extends DataFlow::Node { ParamsInstance() { - this.asExpr().getExpr() instanceof ParamsCall + this.asExpr().getExpr() instanceof Rails::ParamsCall or this = any(DataFlow::CallNode call | diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql index 3121b1e71ef..412ba5534b8 100644 --- a/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql +++ b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql @@ -5,10 +5,12 @@ import ruby import TestUtilities.InlineFlowTest import PathGraph -import codeql.ruby.frameworks.ActionController +import codeql.ruby.frameworks.Rails class ParamsTaintFlowConf extends DefaultTaintFlowConf { - override predicate isSource(DataFlow::Node n) { n.asExpr().getExpr() instanceof ParamsCall } + override predicate isSource(DataFlow::Node n) { + n.asExpr().getExpr() instanceof Rails::ParamsCall + } } from DataFlow::PathNode source, DataFlow::PathNode sink, ParamsTaintFlowConf conf From 115d4de0e0c6ac0e6cbf69043b52b171cb2fe9a5 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Oct 2022 13:50:27 +0100 Subject: [PATCH 086/107] Kotlin: keep method overloads together --- .../src/main/kotlin/KotlinFileExtractor.kt | 99 +++++++++---------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index fc28db0a3b0..09e15bb4f67 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1769,56 +1769,6 @@ open class KotlinFileExtractor( extractCallValueArguments(id, valueArgsWithDummies + extraArgs, enclosingStmt, enclosingCallable, nextIdx) } - fun extractRawMethodAccess( - syntacticCallTarget: IrFunction, - callsite: IrCall, - enclosingCallable: Label, - callsiteParent: Label, - childIdx: Int, - enclosingStmt: Label, - valueArguments: List, - dispatchReceiver: IrExpression?, - extensionReceiver: IrExpression?, - typeArguments: List = listOf(), - extractClassTypeArguments: Boolean = false, - superQualifierSymbol: IrClassSymbol? = null) { - - val locId = tw.getLocation(callsite) - - if (valueArguments.any { it == null }) { - extractsDefaultsCall( - syntacticCallTarget, - locId, - callsite, - enclosingCallable, - callsiteParent, - childIdx, - enclosingStmt, - valueArguments, - dispatchReceiver, - extensionReceiver - ) - } else { - extractRawMethodAccess( - syntacticCallTarget, - locId, - callsite.type, - enclosingCallable, - callsiteParent, - childIdx, - enclosingStmt, - valueArguments.size, - { argParent, idxOffset -> extractCallValueArguments(argParent, valueArguments, enclosingStmt, enclosingCallable, idxOffset) }, - dispatchReceiver?.type, - dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } }, - extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } }, - typeArguments, - extractClassTypeArguments, - superQualifierSymbol - ) - } - } - private fun getFunctionInvokeMethod(typeArgs: List): IrFunction? { // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`. @@ -1877,6 +1827,55 @@ open class KotlinFileExtractor( } } + fun extractRawMethodAccess( + syntacticCallTarget: IrFunction, + callsite: IrCall, + enclosingCallable: Label, + callsiteParent: Label, + childIdx: Int, + enclosingStmt: Label, + valueArguments: List, + dispatchReceiver: IrExpression?, + extensionReceiver: IrExpression?, + typeArguments: List = listOf(), + extractClassTypeArguments: Boolean = false, + superQualifierSymbol: IrClassSymbol? = null) { + + val locId = tw.getLocation(callsite) + + if (valueArguments.any { it == null }) { + extractsDefaultsCall( + syntacticCallTarget, + locId, + callsite, + enclosingCallable, + callsiteParent, + childIdx, + enclosingStmt, + valueArguments, + dispatchReceiver, + extensionReceiver + ) + } else { + extractRawMethodAccess( + syntacticCallTarget, + locId, + callsite.type, + enclosingCallable, + callsiteParent, + childIdx, + enclosingStmt, + valueArguments.size, + { argParent, idxOffset -> extractCallValueArguments(argParent, valueArguments, enclosingStmt, enclosingCallable, idxOffset) }, + dispatchReceiver?.type, + dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } }, + extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } }, + typeArguments, + extractClassTypeArguments, + superQualifierSymbol + ) + } + } fun extractRawMethodAccess( syntacticCallTarget: IrFunction, From b8ef9e0ddc271fc6713da74ae6f1c6387e5c9a9b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 7 Oct 2022 15:59:45 +0000 Subject: [PATCH 087/107] Post-release preparation for codeql-cli-2.11.1 --- cpp/ql/lib/qlpack.yml | 2 +- cpp/ql/src/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/lib/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/src/qlpack.yml | 2 +- csharp/ql/lib/qlpack.yml | 2 +- csharp/ql/src/qlpack.yml | 2 +- go/ql/lib/qlpack.yml | 2 +- go/ql/src/qlpack.yml | 2 +- java/ql/lib/qlpack.yml | 2 +- java/ql/src/qlpack.yml | 2 +- javascript/ql/lib/qlpack.yml | 2 +- javascript/ql/src/qlpack.yml | 2 +- misc/suite-helpers/qlpack.yml | 2 +- python/ql/lib/qlpack.yml | 2 +- python/ql/src/qlpack.yml | 2 +- ruby/ql/lib/qlpack.yml | 2 +- ruby/ql/src/qlpack.yml | 2 +- shared/ssa/qlpack.yml | 2 +- shared/typos/qlpack.yml | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 2746ed855a3..fade2cc7c96 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.4.1 +version: 0.4.2-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index 5bb1b4e6c67..169ac0a41ee 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.4.1 +version: 0.4.2-dev groups: - cpp - queries diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 2bf4479335c..96ed3493829 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.3.1 +version: 1.3.2-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index d2bd8afddf1..888b9099b3d 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.3.1 +version: 1.3.2-dev groups: - csharp - solorigate diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 5d5e75ad307..8b00f8845c2 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.4.1 +version: 0.4.2-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index 2a80e25d0b6..682028cf7cc 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.4.1 +version: 0.4.2-dev groups: - csharp - queries diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index cd565f720c5..3b38291ebb5 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.3.1 +version: 0.3.2-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 4a85f9fe6f3..574b63f69c1 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.3.1 +version: 0.3.2-dev groups: - go - queries diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 3d5ea96dcc0..fc774265862 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.4.1 +version: 0.4.2-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 1377facc607..d74415382a4 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.4.1 +version: 0.4.2-dev groups: - java - queries diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 5fe7be54a20..d5442a13f13 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 0.3.1 +version: 0.3.2-dev groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 9a7548cadb1..c3157ce5043 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 0.4.1 +version: 0.4.2-dev groups: - javascript - queries diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index 911d334cc09..0c38110c86a 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,3 +1,3 @@ name: codeql/suite-helpers -version: 0.3.1 +version: 0.3.2-dev groups: shared diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 2104997ba95..aea8a2fe067 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 0.6.1 +version: 0.6.2-dev groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 4f57ea416ec..31b6ab69f2e 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 0.5.1 +version: 0.5.2-dev groups: - python - queries diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index 8010fd63a50..1ed112d89d4 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 0.4.1 +version: 0.4.2-dev groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index 344a7b03f93..43e9df97f13 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 0.4.1 +version: 0.4.2-dev groups: - ruby - queries diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml index 54bf861fa2e..3fc606ae5ed 100644 --- a/shared/ssa/qlpack.yml +++ b/shared/ssa/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/ssa -version: 0.0.2 +version: 0.0.3-dev groups: shared library: true diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml index 3b52e2e07fb..a8adea7ab70 100644 --- a/shared/typos/qlpack.yml +++ b/shared/typos/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/typos -version: 0.0.2 +version: 0.0.3-dev groups: shared library: true From bef40119476bd035415fa56d12baa5b6ee08bca7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Oct 2022 17:31:38 +0100 Subject: [PATCH 088/107] Kotlin: fix type variable erasure inside default function values Previously because extractClassInstance didn't use the declaration stack, we wouldn't notice that it was legal to refer to its type variable in the context of extracting a specialised method <-> method source-decl edge. This led to erasing the types of the source-decl, so that e.g. Map.put(...) would have signature (Object, Object) not (K, V) as it should. --- .../src/main/kotlin/KotlinFileExtractor.kt | 16 +++++- .../src/main/kotlin/KotlinUsesExtractor.kt | 13 +---- .../parameter-defaults/PrintAst.expected | 56 +++++++++++++++++++ .../parameter-defaults/erasure.ql | 10 +++- .../library-tests/parameter-defaults/test.kt | 12 ++++ 5 files changed, 94 insertions(+), 13 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index fc28db0a3b0..e859a24141c 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -254,9 +254,23 @@ open class KotlinFileExtractor( } } + fun extractClassInstance(classLabel: Label, c: IrClass, argsIncludingOuterClasses: List?, shouldExtractOutline: Boolean, shouldExtractDetails: Boolean) { + DeclarationStackAdjuster(c).use { + if (shouldExtractOutline) { + extractClassWithoutMembers(c, argsIncludingOuterClasses) + } + + if (shouldExtractDetails) { + val supertypeMode = if (argsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(argsIncludingOuterClasses) + extractClassSupertypes(c, classLabel, supertypeMode, true) + extractNonPrivateMemberPrototypes(c, argsIncludingOuterClasses, classLabel) + } + } + } + // `argsIncludingOuterClasses` can be null to describe a raw generic type. // For non-generic types it will be zero-length list. - fun extractClassInstance(c: IrClass, argsIncludingOuterClasses: List?): Label { + private fun extractClassWithoutMembers(c: IrClass, argsIncludingOuterClasses: List?): Label { with("class instance", c) { if (argsIncludingOuterClasses?.isEmpty() == true) { logger.error("Instance without type arguments: " + c.name.asString()) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index da87bfe1169..1bd27278da0 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -411,16 +411,9 @@ open class KotlinUsesExtractor( if (replacedArgsIncludingOuterClasses == null || replacedArgsIncludingOuterClasses.isNotEmpty()) { // If this is a generic type instantiation or a raw type then it has no // source entity, so we need to extract it here - val extractorWithCSource by lazy { this.withFileOfClass(replacedClass) } - - if (!instanceSeenBefore) { - extractorWithCSource.extractClassInstance(replacedClass, replacedArgsIncludingOuterClasses) - } - - if (inReceiverContext && tw.lm.genericSpecialisationsExtracted.add(classLabelResult.classLabel)) { - val supertypeMode = if (replacedArgsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(replacedArgsIncludingOuterClasses) - extractorWithCSource.extractClassSupertypes(replacedClass, classLabel, supertypeMode, true) - extractorWithCSource.extractNonPrivateMemberPrototypes(replacedClass, replacedArgsIncludingOuterClasses, classLabel) + val shouldExtractClassDetails = inReceiverContext && tw.lm.genericSpecialisationsExtracted.add(classLabelResult.classLabel) + if (!instanceSeenBefore || shouldExtractClassDetails) { + this.withFileOfClass(replacedClass).extractClassInstance(classLabel, replacedClass, replacedArgsIncludingOuterClasses, !instanceSeenBefore, shouldExtractClassDetails) } } diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected index ed590470d20..95198f2beaa 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -1165,3 +1165,59 @@ test.kt: # 161| -1: [VarAccess] p0 # 161| 0: [VarAccess] p1 # 161| 1: [VarAccess] p2 +# 165| 15: [Class,GenericType,ParameterizedType] TestGenericUsedWithinDefaultValue +#-----| -2: (Generic Parameters) +# 165| 0: [TypeVariable] T +# 165| 1: [Constructor] TestGenericUsedWithinDefaultValue +# 165| 5: [BlockStmt] { ... } +# 165| 0: [SuperConstructorInvocationStmt] super(...) +# 165| 1: [BlockStmt] { ... } +# 171| 2: [Method] f +# 171| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 171| 0: [Parameter] x +# 171| 0: [TypeAccess] int +# 171| 1: [Parameter] y +# 171| 0: [TypeAccess] String +# 171| 5: [BlockStmt] { ... } +# 171| 3: [Method] f$default +# 171| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 171| 0: [Parameter] p0 +# 171| 0: [TypeAccess] TestGenericUsedWithinDefaultValue<> +# 171| 1: [Parameter] p1 +# 171| 0: [TypeAccess] int +# 171| 2: [Parameter] p2 +# 171| 0: [TypeAccess] String +# 171| 3: [Parameter] p3 +# 171| 0: [TypeAccess] int +# 171| 4: [Parameter] p4 +# 171| 0: [TypeAccess] Object +# 171| 5: [BlockStmt] { ... } +# 171| 0: [IfStmt] if (...) +# 171| 0: [EQExpr] ... == ... +# 171| 0: [AndBitwiseExpr] ... & ... +# 171| 0: [IntegerLiteral] 2 +# 171| 1: [VarAccess] p3 +# 171| 1: [IntegerLiteral] 0 +# 171| 1: [ExprStmt] ; +# 171| 0: [AssignExpr] ...=... +# 171| 0: [VarAccess] p2 +# 171| 1: [MethodAccess] ident(...) +# 171| -1: [ClassInstanceExpr] new TestGenericUsedWithinDefaultValue(...) +# 171| -3: [TypeAccess] TestGenericUsedWithinDefaultValue +# 171| 0: [TypeAccess] String +# 171| 0: [StringLiteral] Hello world +# 171| 1: [ReturnStmt] return ... +# 171| 0: [MethodAccess] f(...) +# 171| -1: [VarAccess] p0 +# 171| 0: [VarAccess] p1 +# 171| 1: [VarAccess] p2 +# 173| 4: [Method] ident +# 173| 3: [TypeAccess] T +#-----| 4: (Parameters) +# 173| 0: [Parameter] t +# 173| 0: [TypeAccess] T +# 173| 5: [BlockStmt] { ... } +# 173| 0: [ReturnStmt] return ... +# 173| 0: [VarAccess] t diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql b/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql index b53a83e436c..9bb2ad44c15 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql @@ -1,9 +1,15 @@ import java +class InstantiatedType extends ParameterizedType { + InstantiatedType() { typeArgs(_, _, this) } +} + // This checks that all type parameter references are erased in the context of a $default function. predicate containsTypeVariables(Type t) { - t != t.getErasure() and - not t.getErasure().(GenericType).getRawType() = t + t instanceof TypeVariable or + containsTypeVariables(t.(InstantiatedType).getATypeArgument()) or + containsTypeVariables(t.(NestedType).getEnclosingType()) or + containsTypeVariables(t.(Wildcard).getATypeBound().getType()) } from Expr e diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt index aa8684e8e70..25a29fb468f 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt @@ -161,3 +161,15 @@ class VisibilityTests { private fun i(x: Int, y: Int = 0) = x + y } + +class TestGenericUsedWithinDefaultValue { + + // This tests parameter erasure works properly: we should notice that here the type variable T + // isn't used in the specialisation TestGenericUsedWithinDefaultValue, but it can be + // cited in contexts like "the signature of the source declaration of 'TestGenericUsedWithinDefaultValue.f(String)' is 'f(T)'", + // not 'f(Object)' as we might mistakenly conclude if we're inappropriately erasing 'T'. + fun f(x: Int, y: String = TestGenericUsedWithinDefaultValue().ident("Hello world")) { } + + fun ident(t: T) = t + +} From 85f92ff80a5eaaef829956d7fcccdab4a72a2264 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Oct 2022 17:49:03 +0100 Subject: [PATCH 089/107] Require --single-version with --single-version-embeddable --- java/kotlin-extractor/build.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/java/kotlin-extractor/build.py b/java/kotlin-extractor/build.py index d714c799eed..8ea0162bf17 100755 --- a/java/kotlin-extractor/build.py +++ b/java/kotlin-extractor/build.py @@ -235,13 +235,19 @@ def compile_standalone(version): 'build_standalone_' + version, version) -compile_single_version = compile_embeddable if args.single_version_embeddable == True else compile_standalone + if args.single_version: - compile_single_version(args.single_version) + if args.single_version_embeddable == True: + compile_embeddable(args.single_version) + else: + compile_standalone(args.single_version) +elif args.single_version_embeddable != None: + print("--single-version-embeddable requires --single-version", file=sys.stderr) + sys.exit(1) elif args.many: for version in kotlin_plugin_versions.many_versions: compile_standalone(version) compile_embeddable(version) else: - compile_single_version(kotlin_plugin_versions.get_single_version()) + compile_standalone(kotlin_plugin_versions.get_single_version()) From 68967c40bcccfaac3a8170f3ca4371a780332bba Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Oct 2022 17:49:51 +0100 Subject: [PATCH 090/107] Remove whitespace --- java/kotlin-extractor/build.py | 1 - 1 file changed, 1 deletion(-) diff --git a/java/kotlin-extractor/build.py b/java/kotlin-extractor/build.py index 8ea0162bf17..3aabeab2cec 100755 --- a/java/kotlin-extractor/build.py +++ b/java/kotlin-extractor/build.py @@ -236,7 +236,6 @@ def compile_standalone(version): version) - if args.single_version: if args.single_version_embeddable == True: compile_embeddable(args.single_version) From 9c0cdfde6b94a73eb1d8fbe23998f2e5e239095f Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Oct 2022 18:02:32 +0100 Subject: [PATCH 091/107] Note store_true params default to False not None --- java/kotlin-extractor/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/build.py b/java/kotlin-extractor/build.py index 3aabeab2cec..9525522869b 100755 --- a/java/kotlin-extractor/build.py +++ b/java/kotlin-extractor/build.py @@ -241,7 +241,7 @@ if args.single_version: compile_embeddable(args.single_version) else: compile_standalone(args.single_version) -elif args.single_version_embeddable != None: +elif args.single_version_embeddable == True: print("--single-version-embeddable requires --single-version", file=sys.stderr) sys.exit(1) elif args.many: From 5dcb70e4821635ff743fb00e9a36a12e05a40a2f Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 7 Oct 2022 18:10:52 +0100 Subject: [PATCH 092/107] Make method private --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index e859a24141c..a6412efdc0e 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -356,7 +356,7 @@ open class KotlinFileExtractor( // `argsIncludingOuterClasses` can be null to describe a raw generic type. // For non-generic types it will be zero-length list. - fun extractNonPrivateMemberPrototypes(c: IrClass, argsIncludingOuterClasses: List?, id: Label) { + private fun extractNonPrivateMemberPrototypes(c: IrClass, argsIncludingOuterClasses: List?, id: Label) { with("member prototypes", c) { val typeParamSubstitution = when (argsIncludingOuterClasses) { From d707c526e5680913ec7180cd1a83c6edcfa91c36 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 9 Oct 2022 10:24:40 +0200 Subject: [PATCH 093/107] Ruby: Avoid computing full `fastTC` for `AstNode::getParent` DIL before ``` /* AST::AstNode */ AST#87953007::Cached::TAstNode result) = fastTC(Module#fe82a56b::parent#1#ff/2) . Module#fe82a56b::enclosingModule#1#ff(/* AST::AstNode */ AST#87953007::Cached::TAstNode node, /* Module::ModuleBase */ AST#87953007::Cached::TAstNode result) :- exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode call_result#2 | Module#2a43f566::ModuleBase#f(result), project#AST#a6718388::AstNode::getAChild#1#dispred(result, call_result#2), ( node = call_result#2; #Module#fe82a56b::parent#1Plus#ff(node, call_result#2) ) ) . ``` DIL after ``` incremental Module#fe82a56b::enclosingModule#1#ff(/* AST::AstNode */ AST#87953007::Cached::TAstNode node, /* Module::ModuleBase */ AST#87953007::Cached::TAstNode result) :- ( Module#2a43f566::ModuleBase#f(result), exists(cached dontcare string _ | AST#a6718388::AstNode::getAChild#1#dispred(result, _, node) ) ); exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode mid | Module#2a43f566::ModuleBase#f(result), rec Module#fe82a56b::enclosingModule#1#ff(mid, result), not(Module#2a43f566::ModuleBase#f(mid)), not(Method#8b49e67f::Block#f(mid)), exists(cached dontcare string _ | AST#a6718388::AstNode::getAChild#1#dispred(mid, _, node) ) ) | [base_case] Module#2a43f566::ModuleBase#f(result), project#AST#a6718388::AstNode::getAChild#1#dispred(result, node) | [delta_order] exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode mid | Module#2a43f566::ModuleBase#f(result), delta previous rec Module#fe82a56b::enclosingModule#1#ff(mid, result), not(Module#2a43f566::ModuleBase#f(mid)), not(Method#8b49e67f::Block#f(mid)), project#AST#a6718388::AstNode::getAChild#1#dispred(mid, node) ), not(previous rec Module#fe82a56b::enclosingModule#1#ff(node, result)) | [delta_order_up_to_500000] exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode mid | delta previous rec Module#fe82a56b::enclosingModule#1#ff(mid, result), Module#2a43f566::ModuleBase#f(result), not(Module#2a43f566::ModuleBase#f(mid)), not(Method#8b49e67f::Block#f(mid)), project#AST#a6718388::AstNode::getAChild#1#dispred(mid, node) ), not(previous rec Module#fe82a56b::enclosingModule#1#ff(node, result)) . ``` --- ruby/ql/lib/codeql/ruby/ast/internal/Module.qll | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll index 9a9626cf74f..67b53baa51c 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll @@ -486,12 +486,15 @@ private import ResolveImpl * methods evaluate the block in the context of some other module/class instead of * the enclosing one. */ -private ModuleBase enclosingModule(AstNode node) { result = parent*(node).getParent() } - -private AstNode parent(AstNode n) { - result = n.getParent() and - not result instanceof ModuleBase and - not result instanceof Block +private ModuleBase enclosingModule(AstNode node) { + result = node.getParent() + or + exists(AstNode mid | + result = enclosingModule(mid) and + mid = node.getParent() and + not mid instanceof ModuleBase and + not mid instanceof Block + ) } private Module getAncestors(Module m) { From 262a74d03d9efe64abf050cb7943ddd457ee6d63 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 9 Oct 2022 10:50:32 +0200 Subject: [PATCH 094/107] Ruby: Avoid computing full `fastTC` for `AstNode::getParent` DIL before ``` /* AST::AstNode */ AST#87953007::Cached::TAstNode result) = fastTC(AST#a6718388::AstNode::getAChild#0#dispred#ff/2) . Completion#445d5844::mayRaise#1#f(/* Call::Call */ unique AST#87953007::Cached::TAstNode c) :- exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode call_result#2 | exists(/* ControlFlowGraphImpl::Trees::BodyStmtTree */ AST#87953007::Cached::TAstNode bst | ( ( project#Expr#6fb2af19::BodyStmt::getRescue#1#dispred#fff(bst), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst) ); ( exists(/* Expr::StmtSequence */ dontcare AST#87953007::Cached::TAstNode _ | Expr#6fb2af19::BodyStmt::getEnsure#0#dispred#ff(bst, _) ), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst) ) ), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst), project#ControlFlowGraphImpl#288ae92e::Trees::StmtSequenceTree::getBodyChild#2#dispred#ffff(bst, call_result#2) ), ( (c = call_result#2, Call#841c84e8::Call#f(c)); ( #AST#a6718388::AstNode::getAChild#0#dispredPlus#ff(call_result#2, c), Call#841c84e8::Call#f(c) ) ) ) . ``` DIL after ``` incremental Completion#445d5844::getARescuableBodyChild#0#f(/* AST::AstNode */ unique AST#87953007::Cached::TAstNode result) :- exists(/* ControlFlowGraphImpl::Trees::BodyStmtTree */ AST#87953007::Cached::TAstNode bst | ( ( exists(dontcare int _, /* Expr::RescueClause */ dontcare AST#87953007::Cached::TAstNode _1 | Expr#6fb2af19::BodyStmt::getRescue#1#dispred#fff(bst, _, _1) ), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst) ); ( exists(/* Expr::StmtSequence */ dontcare AST#87953007::Cached::TAstNode _ | Expr#6fb2af19::BodyStmt::getEnsure#0#dispred#ff(bst, _) ), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst) ) ), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst), exists(boolean arg2, dontcare int _ | arg2 = true, ControlFlowGraphImpl#288ae92e::Trees::StmtSequenceTree::getBodyChild#2#dispred#ffff(bst, _, arg2, result) ) ); exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode call_result#5 | rec Completion#445d5844::getARescuableBodyChild#0#f(call_result#5), exists(cached dontcare string _ | AST#a6718388::AstNode::getAChild#1#dispred(call_result#5, _, result) ) ) | [base_case] exists(/* ControlFlowGraphImpl::Trees::BodyStmtTree */ AST#87953007::Cached::TAstNode bst | ( ( project#Expr#6fb2af19::BodyStmt::getRescue#1#dispred#fff(bst), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst) ); ( exists(/* Expr::StmtSequence */ dontcare AST#87953007::Cached::TAstNode _ | Expr#6fb2af19::BodyStmt::getEnsure#0#dispred#ff(bst, _) ), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst) ) ), ControlFlowGraphImpl#288ae92e::Trees::BodyStmtTree#class#f(bst), project#ControlFlowGraphImpl#288ae92e::Trees::StmtSequenceTree::getBodyChild#2#dispred#ffff(bst, result) ) | [delta_order] exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode call_result#5 | delta previous rec Completion#445d5844::getARescuableBodyChild#0#f(call_result#5), project#AST#a6718388::AstNode::getAChild#1#dispred(call_result#5, result) ), not(previous rec Completion#445d5844::getARescuableBodyChild#0#f(result)) . ``` --- .../ruby/controlflow/internal/Completion.qll | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll index 7615357453d..fe4cca24d69 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll @@ -71,18 +71,22 @@ private predicate completionIsValidForStmt(AstNode n, Completion c) { c = TReturnCompletion() } +private AstNode getARescuableBodyChild() { + exists(Trees::BodyStmtTree bst | result = bst.getBodyChild(_, true) | + exists(bst.getARescue()) + or + exists(bst.getEnsure()) + ) + or + result = getARescuableBodyChild().getAChild() +} + /** * Holds if `c` happens in an exception-aware context, that is, it may be * `rescue`d or `ensure`d. In such cases, we assume that the target of `c` * may raise an exception (in addition to evaluating normally). */ -private predicate mayRaise(Call c) { - exists(Trees::BodyStmtTree bst | c = bst.getBodyChild(_, true).getAChild*() | - exists(bst.getARescue()) - or - exists(bst.getEnsure()) - ) -} +private predicate mayRaise(Call c) { c = getARescuableBodyChild() } /** A completion of a statement or an expression. */ abstract class Completion extends TCompletion { From d39b0fd3f42e9f0e5699ec19b2f67d775a0f804e Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 9 Oct 2022 10:52:06 +0200 Subject: [PATCH 095/107] Ruby: Avoid computing full `fastTC` for `AstNode::getParent` DIL before ``` /* AST::AstNode */ AST#87953007::Cached::TAstNode result) = fastTC(AST#a6718388::AstNode::getAChild#0#dispred#ff/2) . Synthesis#d9ff06b1::isInDesugaredContext#1#f(/* AST::AstNode */ unique AST#87953007::Cached::TAstNode n) :- exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, n) ); exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode call_result#2 | exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, call_result#2) ), #AST#a6718388::AstNode::getAChild#0#dispredPlus#ff(call_result#2, n) ) . ``` DIL after ``` incremental Synthesis#d9ff06b1::isInDesugaredContext#1#f(/* AST::AstNode */ unique AST#87953007::Cached::TAstNode n) :- exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, n) ); exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode any#expr##2 | rec Synthesis#d9ff06b1::isInDesugaredContext#1#f(any#expr##2), exists(cached dontcare string _ | AST#a6718388::AstNode::getAChild#1#dispred(any#expr##2, _, n) ) ) | [base_case] exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, n) ) | [delta_order] exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode any#expr##2 | delta previous rec Synthesis#d9ff06b1::isInDesugaredContext#1#f(any#expr##2), project#AST#a6718388::AstNode::getAChild#1#dispred(any#expr##2, n) ), not(previous rec Synthesis#d9ff06b1::isInDesugaredContext#1#f(n)) . `` --- ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll index 6eaafee71af..5b18756bd5b 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll @@ -132,7 +132,10 @@ int desugarLevel(AstNode n) { result = count(Desugared desugared | n = desugared * Holds if `n` appears in a context that is desugared. That is, a * transitive, reflexive parent of `n` is a desugared node. */ -predicate isInDesugaredContext(AstNode n) { n = any(AstNode sugar).getDesugared().getAChild*() } +predicate isInDesugaredContext(AstNode n) { + n = any(AstNode sugar).getDesugared() or + n = any(AstNode mid | isInDesugaredContext(mid)).getAChild() +} /** * Holds if `n` is a node that only exists as a result of desugaring some From 02192acd5fc1e6aac03b1c13ea83c827ca6ca7be Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 9 Oct 2022 10:53:23 +0200 Subject: [PATCH 096/107] Ruby: Avoid computing full `fastTC` for `AstNode::getParent` DIL before ``` /* AST::AstNode */ AST#87953007::Cached::TAstNode result) = fastTC(AST#a6718388::AstNode::getAChild#0#dispred#ff/2) . Synthesis#d9ff06b1::Desugared::getADescendant#0#dispred#ff(/* Synthesis::Desugared */ AST#87953007::Cached::TAstNode this, /* AST::AstNode */ AST#87953007::Cached::TAstNode result) :- ( exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, this) ), result = this ); ( exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, this) ), #AST#a6718388::AstNode::getAChild#0#dispredPlus#ff(this, result) ) . ``` DIL after ``` incremental Synthesis#d9ff06b1::Desugared::getADescendant#ff(/* Synthesis::Desugared */ AST#87953007::Cached::TAstNode this, /* AST::AstNode */ AST#87953007::Cached::TAstNode result) :- ( exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, this) ), result = this ); exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode call_result#2 | exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, this) ), rec Synthesis#d9ff06b1::Desugared::getADescendant#ff(this, call_result#2), exists(cached dontcare string _ | AST#a6718388::AstNode::getAChild#1#dispred(call_result#2, _, result) ) ) | [base_case] exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, this) ), result = this | [delta_order] exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode call_result#2 | exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, this) ), delta previous rec Synthesis#d9ff06b1::Desugared::getADescendant#ff(this, call_result#2), project#AST#a6718388::AstNode::getAChild#1#dispred(call_result#2, result) ), not( previous rec Synthesis#d9ff06b1::Desugared::getADescendant#ff(this, result) ) | [delta_order_up_to_500000] exists(/* AST::AstNode */ AST#87953007::Cached::TAstNode call_result#2 | delta previous rec Synthesis#d9ff06b1::Desugared::getADescendant#ff(this, call_result#2), exists(int arg1, /* AST::AstNode */ dontcare AST#87953007::Cached::TAstNode _ | arg1 = -1, AST#87953007::Cached::getSynthChild#2(_, arg1, this) ), project#AST#a6718388::AstNode::getAChild#1#dispred(call_result#2, result) ), not( previous rec Synthesis#d9ff06b1::Desugared::getADescendant#ff(this, result) ) . ``` --- ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll index 5b18756bd5b..1ab4435a85a 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll @@ -118,7 +118,11 @@ class Synthesis extends TSynthesis { private class Desugared extends AstNode { Desugared() { this = any(AstNode sugar).getDesugared() } - AstNode getADescendant() { result = this.getAChild*() } + AstNode getADescendant() { + result = this + or + result = this.getADescendant().getAChild() + } } /** From d1c8c40c1705baba33b85b50425f85078375960d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 9 Oct 2022 19:46:48 +0200 Subject: [PATCH 097/107] Data flow: Avoid call to `pathSuccPlus` in `Configuration::hasFlowTo(Expr)` --- .../codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. From 296ec94a2a958fb9c223433c6e06a2420bd46de2 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 9 Oct 2022 19:47:48 +0200 Subject: [PATCH 098/107] Data flow: Sync files --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll | 4 +++- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll | 4 +++- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll | 4 +++- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll | 4 +++- cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll | 4 +++- .../lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll | 4 +++- .../lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll | 4 +++- .../lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll | 4 +++- .../semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll | 4 +++- .../lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll | 4 +++- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll | 4 +++- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll | 4 +++- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll | 4 +++- .../lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll | 4 +++- .../semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll | 4 +++- .../semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll | 4 +++- .../semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll | 4 +++- .../semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll | 4 +++- .../dataflow/internal/DataFlowImplForContentDataFlow.qll | 4 +++- .../lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll | 4 +++- .../lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll | 4 +++- .../lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll | 4 +++- .../lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll | 4 +++- .../lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll | 4 +++- .../lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll | 4 +++- .../dataflow/internal/DataFlowImplForOnActivityResult.qll | 4 +++- .../java/dataflow/internal/DataFlowImplForSerializability.qll | 4 +++- .../lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll | 4 +++- .../lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll | 4 +++- .../lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll | 4 +++- .../lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll | 4 +++- ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll | 4 +++- ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll | 4 +++- .../dataflow/internal/DataFlowImplForHttpClientLibraries.qll | 4 +++- .../codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll | 4 +++- swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll | 4 +++- 36 files changed, 108 insertions(+), 36 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 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 @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 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 @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 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 @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 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 @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ 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) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. From 9f34bf80fd15ac682cef9aa16a1d7e45541c3b71 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 9 Oct 2022 19:59:05 +0200 Subject: [PATCH 099/107] Ruby: Cache use of `DataFlowImplForPathname` --- ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll b/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll index 0939e6c17c8..85db78252c8 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll @@ -27,6 +27,7 @@ module Pathname { * Every `PathnameInstance` is considered to be a `FileNameSource`. */ class PathnameInstance extends FileNameSource { + cached PathnameInstance() { any(PathnameConfiguration c).hasFlowTo(this) } } From efa6b3c0c656dd46c341ba8e56a11ff44bf7a99d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 9 Oct 2022 19:59:56 +0200 Subject: [PATCH 100/107] Ruby: Cache uses of `DataFlowImplForHttpClientLibraries` --- ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll | 1 + ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll | 1 + ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll | 1 + ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll | 1 + ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll | 1 + ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll | 2 ++ ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll | 1 + ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll | 1 + 8 files changed, 9 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll index 4468f8ffa58..37b3cdbd576 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll @@ -70,6 +70,7 @@ class ExconHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll index ae4bb25c265..139a484f87a 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll @@ -71,6 +71,7 @@ class FaradayHttpRequest extends Http::Client::Request::Range, DataFlow::CallNod ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll index 0d8e6cfa0fc..51537e25148 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll @@ -61,6 +61,7 @@ class HttpClientRequest extends Http::Client::Request::Range, DataFlow::CallNode .getArgument(0) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll index 08ab0f94141..e0b5de43351 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll @@ -53,6 +53,7 @@ class HttpartyRequest extends Http::Client::Request::Range, DataFlow::CallNode { result = this.getKeywordArgumentIncludeHashArgument(["verify", "verify_peer"]) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll index f12f6fa8e30..d6dbd581f86 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll @@ -80,6 +80,7 @@ class NetHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode { ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll index f11a4b2908f..68ca62beaf8 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll @@ -42,6 +42,7 @@ class OpenUriRequest extends Http::Client::Request::Range, DataFlow::CallNode { result = this.getKeywordArgumentIncludeHashArgument("ssl_verify_mode") } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { @@ -91,6 +92,7 @@ class OpenUriKernelOpenRequest extends Http::Client::Request::Range, DataFlow::C ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll index 4b9ddfaab41..7df9875b00c 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll @@ -54,6 +54,7 @@ class RestClientHttpRequest extends Http::Client::Request::Range, DataFlow::Call ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll index 163560e61f9..e41add437d3 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll @@ -34,6 +34,7 @@ class TyphoeusHttpRequest extends Http::Client::Request::Range, DataFlow::CallNo result = this.getKeywordArgumentIncludeHashArgument("ssl_verifypeer") } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { From 059864587e7ed39b1674062b1ce56dfd2bdc95e4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 10 Oct 2022 11:00:18 +0100 Subject: [PATCH 101/107] C++: Add 'mremap' to whitelist. --- cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql index a378d50b0df..9c456f71bbb 100644 --- a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql @@ -67,11 +67,7 @@ class VarargsFunction extends Function { not exists(FunctionCall fc, int index | this.nonTrailingVarArgValue(fc, index) = result) } - predicate isWhitelisted() { - this.hasGlobalName("open") or - this.hasGlobalName("fcntl") or - this.hasGlobalName("ptrace") - } + predicate isWhitelisted() { this.hasGlobalName(["open", "fcntl", "ptrace", "mremap"]) } } from VarargsFunction f, FunctionCall fc, string terminator, int cnt, int totalCount From 08d6b2f30ae8a8d5343c0e732db8d08e595ec1ea Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 10 Oct 2022 13:46:18 +0200 Subject: [PATCH 102/107] Python: Fix typo in qldoc --- python/ql/lib/semmle/python/Concepts.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index b4f1c73e633..fe091f84e9c 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -344,7 +344,7 @@ module SqlConstruction { * A data-flow node that executes SQL statements. * * If the context of interest is such that merely constructing an SQL statement - * would be valuabe to report, then consider using `SqlConstruction`. + * would be valuable to report, then consider using `SqlConstruction`. * * Extend this class to refine existing API models. If you want to model new APIs, * extend `SqlExecution::Range` instead. @@ -360,7 +360,7 @@ module SqlExecution { * A data-flow node that executes SQL statements. * * If the context of interest is such that merely constructing an SQL statement - * would be valuabe to report, then consider using `SqlConstruction`. + * would be valuable to report, then consider using `SqlConstruction`. * * Extend this class to model new APIs. If you want to refine existing API models, * extend `SqlExecution` instead. @@ -465,7 +465,7 @@ module XML { * A data-flow node that executes a xpath expression. * * If the context of interest is such that merely constructing an XPath expression - * would be valuabe to report, then consider using `XPathConstruction`. + * would be valuable to report, then consider using `XPathConstruction`. * * Extend this class to refine existing API models. If you want to model new APIs, * extend `XPathExecution::Range` instead. @@ -487,7 +487,7 @@ module XML { * A data-flow node that executes a XPath expression. * * If the context of interest is such that merely constructing an XPath expression - * would be valuabe to report, then consider using `XPathConstruction`. + * would be valuable to report, then consider using `XPathConstruction`. * * Extend this class to model new APIs. If you want to refine existing API models, * extend `XPathExecution` instead. From 544e2e4107528ad57bf71cc64bc4b8bbaabd6332 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 10 Oct 2022 14:42:15 +0200 Subject: [PATCH 103/107] Remove path based generated file classification --- java/ql/lib/semmle/code/java/GeneratedFiles.qll | 7 ------- .../kotlin/library-tests/GeneratedFiles/Generated.expected | 1 - .../GeneratedFiles/generated/source/NonGenerated.kt | 1 - .../GeneratedFiles/generated/source/kapt/Generated.kt | 1 - 4 files changed, 10 deletions(-) delete mode 100644 java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/NonGenerated.kt delete mode 100644 java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/kapt/Generated.kt diff --git a/java/ql/lib/semmle/code/java/GeneratedFiles.qll b/java/ql/lib/semmle/code/java/GeneratedFiles.qll index cfd72e02938..79197653848 100644 --- a/java/ql/lib/semmle/code/java/GeneratedFiles.qll +++ b/java/ql/lib/semmle/code/java/GeneratedFiles.qll @@ -65,10 +65,3 @@ private class GeneratedFileMarker extends Top { ) } } - -/** - * A file detected as generated by the Kotlin Annotation Processing Tool (kapt). Detection is based on file path. - */ -private class KaptFile extends GeneratedFile { - KaptFile() { this.getRelativePath().matches("%/generated/source/kapt%") } -} diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected index 0a5b4c6ff29..6b4abd0e1a4 100644 --- a/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected @@ -1,2 +1 @@ | Generated.kt:0:0:0:0 | Generated | -| generated/source/kapt/Generated.kt:0:0:0:0 | Generated | diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/NonGenerated.kt b/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/NonGenerated.kt deleted file mode 100644 index a7f289eeb2f..00000000000 --- a/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/NonGenerated.kt +++ /dev/null @@ -1 +0,0 @@ -class D \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/kapt/Generated.kt b/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/kapt/Generated.kt deleted file mode 100644 index 9dccdd5e595..00000000000 --- a/java/ql/test/kotlin/library-tests/GeneratedFiles/generated/source/kapt/Generated.kt +++ /dev/null @@ -1 +0,0 @@ -class C \ No newline at end of file From f7203bfcb82b5cf3907c0deacbf094fa8b7e7008 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Mon, 10 Oct 2022 15:27:45 +0200 Subject: [PATCH 104/107] CI: fix qhelp preview The command to gather the changed files uses NULL character terminated "lines", therefore we should supply the `-z` flag to `basename` as well. Otherwise we end up calling `git grep -l "\n"` which would list all files containing a newline. --- .github/workflows/qhelp-pr-preview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qhelp-pr-preview.yml b/.github/workflows/qhelp-pr-preview.yml index 5cca4faf540..a44ef5ad48d 100644 --- a/.github/workflows/qhelp-pr-preview.yml +++ b/.github/workflows/qhelp-pr-preview.yml @@ -52,7 +52,7 @@ jobs: id: changes run: | (git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.qhelp$' | grep -z -v '.inc.qhelp'; - git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.inc.qhelp$' | xargs --null -rn1 basename | xargs --null -rn1 git grep -z -l) | + git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.inc.qhelp$' | xargs --null -rn1 basename -z | xargs --null -rn1 git grep -z -l) | grep -z '.qhelp$' | grep -z -v '^-' | sort -z -u > "${RUNNER_TEMP}/paths.txt" - name: QHelp preview From 67cef92f94bf3adf412b1ca41e5b72b63c0f8a9b Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 7 Oct 2022 12:38:46 +0200 Subject: [PATCH 105/107] JS: Rewrite to use DataFlow::Node API and restrict context --- .../javascript/dataflow/TaintTracking.qll | 44 +++++++------------ .../Security/CWE-079/DomBasedXss/Xss.expected | 7 --- .../XssWithAdditionalSources.expected | 7 --- 3 files changed, 17 insertions(+), 41 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index c3cc9869cc4..fc78c8a9ad1 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -711,41 +711,31 @@ module TaintTracking { } } + /** + * Gets a local source of any part of the input to the given stringification `call`. + */ + private DataFlow::Node getAJsonLocalInput(JsonStringifyCall call) { + result = call.getInput() + or + exists(DataFlow::SourceNode source | source = getAJsonLocalInput(call).getALocalSource() | + result = source.getAPropertyWrite().getRhs() + or + result = source.(DataFlow::ObjectLiteralNode).getASpreadProperty() + or + result = source.(DataFlow::ArrayCreationNode).getASpreadArgument() + ) + } + /** * A taint propagating data flow edge arising from JSON unparsing. */ private class JsonStringifyTaintStep extends SharedTaintStep { override predicate serializeStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(JsonStringifyCall call, DataFlow::Node arg | - arg = call.getArgument(0) and - this.findInObject(arg.asExpr(), pred.asExpr()) and + exists(JsonStringifyCall call | + pred = getAJsonLocalInput(call) and succ = call ) } - - // find target in root object recursively - private predicate findInObject(Expr root, Expr target) { - // base case - root = target - or - // when root is Object - exists(Property property | - root instanceof ObjectExpr and - property = root.(ObjectExpr).getAProperty() and - ( - this.findInObject(property.getNameExpr(), target) or - this.findInObject(property.getInit(), target) - ) - ) - or - // when root is Array - root instanceof ArrayExpr and - this.findInObject(root.(ArrayExpr).getAChildExpr(), target) - or - // when root is VarRef - root instanceof VarRef and - this.findInObject(root.(VarRef).getAVariable().getAnAssignedExpr(), target) - } } /** diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected index 6303a737716..4582ba675a4 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected @@ -1533,13 +1533,6 @@ edges | json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | | json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | | json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | | json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | | json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | | json-stringify.jsx:11:51:11:56 | locale | json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index 82fb3119575..5c5232b11d2 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected @@ -1583,13 +1583,6 @@ edges | json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | | json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | | json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | -| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | | json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | | json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | | json-stringify.jsx:11:51:11:56 | locale | json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | From ecf7ed38e01483cacbc0d1928e55777e21fee76c Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 10 Oct 2022 11:55:54 +0200 Subject: [PATCH 106/107] JS: Performance tweak --- .../ql/lib/semmle/javascript/dataflow/TaintTracking.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index fc78c8a9ad1..2e7a9dd4f34 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -714,10 +714,13 @@ module TaintTracking { /** * Gets a local source of any part of the input to the given stringification `call`. */ + pragma[nomagic] private DataFlow::Node getAJsonLocalInput(JsonStringifyCall call) { result = call.getInput() or - exists(DataFlow::SourceNode source | source = getAJsonLocalInput(call).getALocalSource() | + exists(DataFlow::SourceNode source | + source = pragma[only_bind_out](getAJsonLocalInput(call)).getALocalSource() + | result = source.getAPropertyWrite().getRhs() or result = source.(DataFlow::ObjectLiteralNode).getASpreadProperty() From b1a165ee980085910619ec62f878ed6ce3145e07 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 10 Oct 2022 15:12:23 +0200 Subject: [PATCH 107/107] JS: Edit change note --- .../src/change-notes/2022-10-04-json-stringify-improvement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/change-notes/2022-10-04-json-stringify-improvement.md b/javascript/ql/src/change-notes/2022-10-04-json-stringify-improvement.md index 5d488ff0a48..0480c231a16 100644 --- a/javascript/ql/src/change-notes/2022-10-04-json-stringify-improvement.md +++ b/javascript/ql/src/change-notes/2022-10-04-json-stringify-improvement.md @@ -1,4 +1,4 @@ --- category: minorAnalysis --- -* Improved taint tracking behavior when the `JSON.stringify` method called. Previously, `JsonStringifyTaintStep` detects only if the source is equal to an argument. Now, it can detect the case that the argument is object and source is located in its property. +* Improved taint tracking through `JSON.stringify` in cases where a tainted value is stored somewhere in the input object.